xbinser 0.1.0

library for binary structure transporation
Documentation
use std::io;

pub trait Encoded {
    fn encode(&self, output: &mut impl io::Write) -> io::Result<()>;
}

pub trait Decoded: Sized {
    fn decode(input: &mut impl io::Read) -> io::Result<Self>;
}

impl Encoded for bool {
    fn encode(&self, output: &mut impl io::Write) -> io::Result<()> {
        let byte = if *self { 1 } else { 0 };
        output.write_all(&[byte])
    }
}

impl Decoded for bool {
    fn decode(input: &mut impl io::Read) -> io::Result<Self> {
        let mut byte = [0];
        input.read_exact(&mut byte)?;
        Ok(byte[0] != 0)
    }
}

macro_rules! implement_int_trait {
    ($int:ident) => {
        impl Encoded for $int {
            fn encode(&self, output: &mut impl io::Write) -> io::Result<()> {
                let bytes = self.to_le_bytes();
                output.write_all(&bytes)
            }
        }
        
        impl Decoded for $int {
            fn decode(input: &mut impl io::Read) -> io::Result<Self> {
                let mut bytes = [0; std::mem::size_of::<$int>()];
                input.read_exact(&mut bytes)?;
                Ok($int::from_le_bytes(bytes))
            }
        }
    };
}

implement_int_trait!(u8);
implement_int_trait!(u16);
implement_int_trait!(u32);
implement_int_trait!(u64);
implement_int_trait!(i8);
implement_int_trait!(i16);
implement_int_trait!(i32);
implement_int_trait!(i64);

impl<T: Encoded, const N: usize> Encoded for [T; N] {
    fn encode(&self, output: &mut impl io::Write) -> io::Result<()> {
        for item in self.iter() { item.encode(output)?; }
        Ok(())
    }
}

impl<T: Decoded, const N: usize> Decoded for [T; N] {
    fn decode(input: &mut impl io::Read) -> io::Result<Self> {
        let mut array: [T; N] = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
        for item in &mut array { *item = T::decode(input)?; }
        Ok(array)
    }
}

impl<T: Encoded> Encoded for Vec<T> {
    fn encode(&self, output: &mut impl io::Write) -> io::Result<()> {
        let length = self.len() as u64;
        output.write_all(&length.to_le_bytes())?;

        for item in self.iter() {
            item.encode(output)?;
        }

        Ok(())
    }
}

impl<T: Decoded> Decoded for Vec<T> {
    fn decode(input: &mut impl io::Read) -> io::Result<Self> {
        let mut length_bytes = [0u8; 8];
        input.read_exact(&mut length_bytes)?;
        let length = u64::from_le_bytes(length_bytes) as usize;

        let mut vec = Vec::with_capacity(length);

        for _ in 0..length {
            let item = T::decode(input)?;
            vec.push(item);
        }

        Ok(vec)
    }
}

impl Encoded for String {
    fn encode(&self, output: &mut impl io::Write) -> io::Result<()> {
        let bytes = self.as_bytes();
        let length = bytes.len() as u64;

        output.write_all(&length.to_le_bytes())?;
        output.write_all(bytes)?;

        Ok(())
    }
}

impl Decoded for String {
    fn decode(input: &mut impl io::Read) -> io::Result<Self> {
        let mut length_bytes = [0u8; 8];
        input.read_exact(&mut length_bytes)?;

        let length = u64::from_le_bytes(length_bytes) as usize;

        let mut string_bytes = vec![0u8; length];
        input.read_exact(&mut string_bytes)?;

        let decoded_string = String::from_utf8(string_bytes)
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

        Ok(decoded_string)
    }
}