flour 2.0.1

Serializes and deserializes BCCAD / BRCAD files to and from JSON
Documentation
use crate::{error::Result, Color, VarLenString};
use bytestream::*;
use std::{
    io::{Read, Write},
    marker::Sized,
};

pub trait ByteStream {
    fn read_from<T: Read>(file: &mut T, order: ByteOrder) -> Result<Self>
    where
        Self: Sized;
    fn write_to<T: Write>(&self, file: &mut T, order: ByteOrder) -> Result<()>
    where
        Self: Sized;
}

impl ByteStream for f32 {
    fn read_from<T: Read>(file: &mut T, order: ByteOrder) -> Result<Self> {
        let mut bytes = [0; 4];
        file.read_exact(&mut bytes)?;
        match order {
            ByteOrder::BigEndian => Ok(Self::from_be_bytes(bytes)),
            ByteOrder::LittleEndian => Ok(Self::from_le_bytes(bytes)),
        }
    }
    fn write_to<T: Write>(&self, file: &mut T, order: ByteOrder) -> Result<()> {
        let bytes = match order {
            ByteOrder::BigEndian => self.to_be_bytes(),
            ByteOrder::LittleEndian => self.to_le_bytes(),
        };
        file.write_all(&bytes)?;
        Ok(())
    }
}

impl ByteStream for Color {
    fn read_from<T: Read>(file: &mut T, order: ByteOrder) -> Result<Self> {
        let red = u8::read_from(file, order)?;
        let green = u8::read_from(file, order)?;
        let blue = u8::read_from(file, order)?;
        Ok(Self { red, green, blue })
    }
    fn write_to<W: Write>(&self, file: &mut W, order: ByteOrder) -> Result<()> {
        self.red.write_to(file, order)?;
        self.green.write_to(file, order)?;
        self.blue.write_to(file, order)?;
        Ok(())
    }
}

impl ByteStream for VarLenString {
    fn read_from<T: Read>(file: &mut T, order: ByteOrder) -> Result<Self> {
        let mut bytes = vec![];
        let size = u8::read_from(file, order)?;
        for _ in 0..size {
            bytes.push(u8::read_from(file, order)?);
        }
        let padding_size = 4 - ((size + 1) % 4);
        for _ in 0..padding_size {
            u8::read_from(file, order)?;
        }
        let string = String::from_utf8(bytes)?;
        Ok(Self(string))
    }
    fn write_to<T: Write>(&self, file: &mut T, order: ByteOrder) -> Result<()> {
        let string = &self.0;
        let size = string.len() as u8;
        let bytes = string.as_bytes();
        let padding_size = 4 - ((size + 1) % 4);
        size.write_to(file, order)?;
        file.write_all(bytes)?;
        for _ in 0..padding_size {
            0u8.write_to(file, order)?;
        }
        Ok(())
    }
}