Skip to content

Commit

Permalink
feat: ensure bit-for-bit accurate roundtrips are possible
Browse files Browse the repository at this point in the history
  • Loading branch information
justjanne committed Feb 25, 2024
1 parent a03bd59 commit 5302262
Show file tree
Hide file tree
Showing 5 changed files with 1,179 additions and 1,211 deletions.
Binary file removed samples/test/square_roundtrip.fcm
Binary file not shown.
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ pub mod generator;
pub mod outline;
mod outline_tag;
pub mod path;
pub mod path_rhinestones;
pub mod path_shape;
pub mod path_tool;
pub mod piece;
Expand Down
95 changes: 46 additions & 49 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,33 @@ use std::io;
use std::io::Write;

use nom::combinator::{flat_map, map};
use nom::multi::length_value;
use nom::IResult;
use nom::multi::{count, length_value};
use nom::number::complete::le_u32;
use nom::sequence::tuple;
use nom::IResult;

use crate::{path_shape, path_tool};
use crate::encode::Encode;
use crate::path_rhinestones::PathRhinestones;
use crate::path_shape::PathShape;
use crate::path_tool::PathTool;
use crate::{path_rhinestones, path_shape, path_tool};
use crate::point::{Point, read_point};

#[derive(Debug)]
pub struct Path {
pub tool: PathTool,
pub shape: Option<PathShape>,
pub rhinestones: Option<PathRhinestones>,
pub rhinestone_diameter: Option<u32>,
pub rhinestones: Vec<Point>,
}

impl Encode for Path {
fn encode(&self, buffer: &mut Vec<u8>) -> io::Result<()> {
self.tool.encode(buffer)?;
buffer.write(
&self
.shape
.as_ref()
.map(|it| it.outlines.len() as u32)
.unwrap_or_default()
.to_le_bytes(),
)?;
buffer.write(
&self
.rhinestones
.as_ref()
.map(|it| it.points.len() as u32)
.unwrap_or_default()
.to_le_bytes(),
)?;
buffer.write(
&self
.rhinestones
.as_ref()
.map(|it| it.diameter)
.unwrap_or_default()
.to_le_bytes(),
)?;
if let Some(shape) = &self.shape {
shape.start.encode(buffer)?;
for outline in &shape.outlines {
outline.encode(buffer)?;
}
}
if let Some(rhinestones) = &self.rhinestones {
for rhinestone in &rhinestones.points {
rhinestone.encode(buffer)?;
}
fn read_rhinestone_diameter(input: &[u8]) -> IResult<&[u8], Option<u32>> {
map(le_u32, |diameter| {
if diameter == 0x3f000000 {
None
} else {
Some(diameter)
}
Ok(())
}
})(input)
}

pub(crate) fn read_path(input: &[u8]) -> IResult<&[u8], Path> {
Expand All @@ -68,23 +37,51 @@ pub(crate) fn read_path(input: &[u8]) -> IResult<&[u8], Path> {
length_value(le_u32, path_tool::read_path_tool),
le_u32,
le_u32,
le_u32,
read_rhinestone_diameter,
)),
|(tool, outline_count, rhinestone_count, rhinestone_diameter)| {
map(
tuple((
path_shape::read_path_shape(outline_count as usize),
path_rhinestones::read_path_rhinestones(
rhinestone_count as usize,
rhinestone_diameter,
),
count(read_point, rhinestone_count as usize),
)),
move |(shape, rhinestones)| Path {
tool,
shape,
rhinestone_diameter,
rhinestones,
},
)
},
)(input)
}

impl Encode for Path {
fn encode(&self, buffer: &mut Vec<u8>) -> io::Result<()> {
self.tool.encode(buffer)?;
buffer.write(
&self
.shape
.as_ref()
.map(|it| it.outlines.len() as u32)
.unwrap_or_default()
.to_le_bytes(),
)?;
(self.rhinestones.len() as u32).encode(buffer)?;
if let Some(rhinestone_diameter) = &self.rhinestone_diameter {
rhinestone_diameter.encode(buffer)?;
} else {
0x3f000000u32.encode(buffer)?;
}
if let Some(shape) = &self.shape {
shape.start.encode(buffer)?;
for outline in &shape.outlines {
outline.encode(buffer)?;
}
}
for rhinestone in &self.rhinestones {
rhinestone.encode(buffer)?;
}
Ok(())
}
}
24 changes: 0 additions & 24 deletions src/path_rhinestones.rs

This file was deleted.

Loading

0 comments on commit 5302262

Please sign in to comment.