fcmlib 0.1.0

Library to read and write Brother's FCM plotter files
Documentation
use std::io::Write;

use nom::combinator::{flat_map, map};
use nom::multi::length_count;
use nom::number::complete::le_u32;
use nom::IResult;

use crate::encode::Encode;
use crate::outline_tag::OutlineTag;
use crate::segment_bezier::SegmentBezier;
use crate::segment_line::SegmentLine;
use crate::{outline_tag, segment_bezier, segment_line};

#[derive(Debug, Clone)]
pub enum Outline {
    Line(Vec<SegmentLine>),
    Bezier(Vec<SegmentBezier>),
}

pub(crate) fn read_outline(input: &[u8]) -> IResult<&[u8], Outline> {
    flat_map(outline_tag::read_outline_tag, |tag| match tag {
        OutlineTag::Line => read_outline_line,
        OutlineTag::Bezier => read_outline_bezier,
    })(input)
}

fn read_outline_line(input: &[u8]) -> IResult<&[u8], Outline> {
    map(
        length_count(le_u32, segment_line::read_segment_line),
        Outline::Line,
    )(input)
}

fn read_outline_bezier(input: &[u8]) -> IResult<&[u8], Outline> {
    map(
        length_count(le_u32, segment_bezier::read_segment_bezier),
        Outline::Bezier,
    )(input)
}

impl Encode for Outline {
    fn encode(&self, buffer: &mut Vec<u8>) -> std::io::Result<()> {
        match self {
            Outline::Line(segments) => {
                OutlineTag::Line.encode(buffer)?;
                buffer.write_all(&(segments.len() as u32).to_le_bytes())?;
                for segment in segments {
                    segment.encode(buffer)?;
                }
            }
            Outline::Bezier(segments) => {
                OutlineTag::Bezier.encode(buffer)?;
                buffer.write_all(&(segments.len() as u32).to_le_bytes())?;
                for segment in segments {
                    segment.encode(buffer)?;
                }
            }
        }
        Ok(())
    }
}