rmesh 0.4.0

A parser for the rmesh extension
Documentation
use std::fmt;

use binrw::{BinRead, BinWrite};

#[derive(BinRead, BinWrite, Clone, Eq, PartialEq, Default)]
pub struct FixedLengthString {
    pub len: u32,
    #[br(count = len)]
    pub values: Vec<u8>,
}

impl fmt::Debug for FixedLengthString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "FixedLengthString(\"")?;
        write!(f, "{}", String::from_utf8(self.values.clone()).unwrap())?;
        write!(f, "\")")
    }
}

impl From<&str> for FixedLengthString {
    fn from(s: &str) -> Self {
        let values = s.as_bytes().to_vec();
        Self {
            len: values.len() as u32,
            values,
        }
    }
}

impl From<String> for FixedLengthString {
    fn from(s: String) -> Self {
        let values = s.into_bytes();
        Self {
            len: values.len() as u32,
            values,
        }
    }
}

impl From<FixedLengthString> for String {
    fn from(value: FixedLengthString) -> Self {
        String::from_utf8(value.values).unwrap()
    }
}

impl From<&FixedLengthString> for String {
    fn from(value: &FixedLengthString) -> Self {
        String::from_utf8(value.values.clone()).unwrap()
    }
}

#[derive(Clone, Eq, PartialEq, Default, Debug)]
pub struct ThreeTypeString(pub Vec<u8>);

impl BinRead for ThreeTypeString {
    type Args<'a> = ();

    fn read_options<R: std::io::Read + std::io::Seek>(
        reader: &mut R,
        endian: binrw::Endian,
        _args: Self::Args<'_>,
    ) -> binrw::BinResult<Self> {
        let len = <u32>::read_options(reader, endian, ())?;

        let mut values = vec![];

        for _ in 0..len {
            let val = <u8>::read_options(reader, endian, ())?;
            values.push(val);
        }

        let string = String::from_utf8(values).unwrap();
        let stuff: Vec<_> = string
            .split(' ')
            .map(|c| c.parse::<u8>().unwrap())
            .collect();

        Ok(Self(stuff))
    }
}

impl BinWrite for ThreeTypeString {
    type Args<'a> = ();

    fn write_options<W: std::io::Write + std::io::Seek>(
        &self,
        writer: &mut W,
        endian: binrw::Endian,
        _args: Self::Args<'_>,
    ) -> binrw::BinResult<()> {
        let string = self
            .0
            .iter()
            .map(|num| num.to_string())
            .collect::<Vec<String>>()
            .join(" ");

        let bytes = string.into_bytes();
        let len = bytes.len() as u32;

        len.write_options(writer, endian, ())?;
        writer.write_all(&bytes[..])?;

        Ok(())
    }
}

impl From<Vec<u8>> for ThreeTypeString {
    fn from(value: Vec<u8>) -> Self {
        Self(value)
    }
}

impl From<[u8; 3]> for ThreeTypeString {
    fn from(value: [u8; 3]) -> Self {
        Self(value.to_vec())
    }
}