codec 0.0.7

Codec trait to assist in making codecs
Documentation
use heapless::{String, Vec};

use crate::{codec::{Codec, DecodeError, EncodeError}, DecodeBuffer, EncodeBuffer};


#[derive(Copy, Clone)]
pub enum Endian {
    Big,
    Little,
    Host
}

impl Codec<()> for u8 {
    fn encode(self, buf: & mut impl EncodeBuffer, _: ()) -> Result<(), EncodeError> {
        buf.push(self)
    }
    fn decode(buf: &mut impl DecodeBuffer, _: ()) -> Result<Self, DecodeError> {
        buf.read()
    }
}

impl Codec<Endian> for i8 {
    fn encode(self, buf: & mut impl EncodeBuffer, _: Endian) -> Result<(), EncodeError> {
        buf.push(self as u8)
    }
    fn decode(buf: &mut impl DecodeBuffer, _: Endian) -> Result<Self, DecodeError> {
        Ok(buf.read()? as i8)
    }
}

impl Codec<Endian> for u16 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;2];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for i16 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;2];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for u32 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;4];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for i32 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;4];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for u64 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;8];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for i64 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;8];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for u128 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;16];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for i128 {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;16];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for f32 {
    fn encode(self, buf: &mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;4];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl Codec<Endian> for f64 {
    fn encode(self, buf: &mut impl EncodeBuffer, ctx: Endian) -> Result<(), EncodeError> {
        match ctx {
            Endian::Big => buf.push_slice(&self.to_be_bytes()),
            Endian::Little => buf.push_slice(&self.to_le_bytes()),
            Endian::Host => buf.push_slice(&self.to_ne_bytes()),
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: Endian) -> Result<Self, DecodeError> {
        let mut slice = [0u8;8];
        buf.read_slice(&mut slice)?;
        match ctx {
            Endian::Big => Ok(Self::from_be_bytes(slice)),
            Endian::Little => Ok(Self::from_le_bytes(slice)),
            Endian::Host => Ok(Self::from_ne_bytes(slice)),
        }
    }
}

impl<A: Copy, T: Default + Copy + Codec<A>, const SIZE: usize> Codec<A> for [T; SIZE] {
    fn encode(self, buf: & mut impl EncodeBuffer, ctx: A) -> Result<(), EncodeError> {
        for i in self {
            i.encode(buf, ctx)?;
        }

        Ok(())
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: A) -> Result<Self, DecodeError> {
        let mut result = [T::default(); SIZE];
        for i in 0..SIZE {
            result[i] = T::decode(buf, ctx)?;
        }

        Ok(result)
    }
}

impl Codec<()> for bool {
    fn encode(self, buf: &mut impl EncodeBuffer, _: ()) -> Result<(), EncodeError> {
        if self {
            1u8.encode(buf, ())
        } else {
            0u8.encode(buf, ())
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, _: ()) -> Result<Self, DecodeError> {
        let is_set: u8 = u8::decode(buf, ())?;

        Ok(is_set != 0)
    }
}

pub enum SizeContext {
    Fixed(usize),
    U8Len,
    U16Len(Endian),
    U32Len(Endian),
    NullTerminated,
}


impl<const SIZE: usize> Codec<SizeContext> for String<SIZE> {
    fn encode(self, buf: &mut impl EncodeBuffer, ctx: SizeContext) -> Result<(), EncodeError> {
        match ctx {
            SizeContext::Fixed(usize) => {
                let slice = self.as_bytes();
                let length = slice.len();
                if length > usize {return Err(EncodeError::Encoding)}
                buf.push_slice(self.as_bytes())?;
                for _ in 0..usize-length {
                    buf.push(0)?;
                }
                Ok(())
            },
            SizeContext::U8Len => {
                let slice = self.as_bytes();
                let length = u8::try_from(slice.len()).or_else(|_| Err(EncodeError::Encoding))?;
                buf.push(length)?;
                buf.push_slice(self.as_bytes())
            },
            SizeContext::U16Len(end) => {
                let slice = self.as_bytes();
                let length = u16::try_from(slice.len()).or_else(|_| Err(EncodeError::Encoding))?;
                length.encode(buf, end)?;
                buf.push_slice(self.as_bytes())
            },
            SizeContext::U32Len(end) => {
                let slice = self.as_bytes();
                let length = u32::try_from(slice.len()).or_else(|_| Err(EncodeError::Encoding))?;
                length.encode(buf, end)?;
                buf.push_slice(self.as_bytes())
            },
            SizeContext::NullTerminated => {
                buf.push_slice(self.as_bytes())?;
                buf.push(0)
            },
        }
    }
    fn decode(buf: &mut impl DecodeBuffer, ctx: SizeContext) -> Result<Self, DecodeError> {
        match ctx {
            SizeContext::Fixed(size) => {
                let mut temp_buf = [0u8;SIZE];
                buf.read_slice(&mut temp_buf[0..size])?;
                let vec: Vec<_, SIZE> = Vec::from_slice(&temp_buf[0..size]).or_else(|_| Err(DecodeError::Invalid))?;
                String::<SIZE>::from_utf8(vec).or_else(|_| Err(DecodeError::Invalid))
            }
            SizeContext::U8Len => {
                let mut temp_buf = [0u8;SIZE];
                let len = u8::decode(buf, ())?;
                let len = len as usize;
                if len > SIZE {return Err(DecodeError::Invalid);}
                buf.read_slice(&mut temp_buf[0..len])?;
                let vec: Vec<_, SIZE> = Vec::from_slice(&temp_buf[0..len]).or_else(|_| Err(DecodeError::Invalid))?;
                String::<SIZE>::from_utf8(vec).or_else(|_| Err(DecodeError::Invalid))
            }
            SizeContext::U16Len(end) => {
                let mut temp_buf = [0u8;SIZE];
                let len = u16::decode(buf, end)?;
                let len = len as usize;
                if len > SIZE {return Err(DecodeError::Invalid);}
                buf.read_slice(&mut temp_buf[0..len])?;
                let vec: Vec<_, SIZE> = Vec::from_slice(&temp_buf[0..len]).or_else(|_| Err(DecodeError::Invalid))?;
                String::<SIZE>::from_utf8(vec).or_else(|_| Err(DecodeError::Invalid))
            }
            SizeContext::U32Len(end) => {
                let mut temp_buf = [0u8;SIZE];
                let len = u32::decode(buf, end)?;
                let len = len as usize;
                if len > SIZE {return Err(DecodeError::Invalid);}
                buf.read_slice(&mut temp_buf[0..len])?;
                let vec: Vec<_, SIZE> = Vec::from_slice(&temp_buf[0..len]).or_else(|_| Err(DecodeError::Invalid))?;
                String::<SIZE>::from_utf8(vec).or_else(|_| Err(DecodeError::Invalid))
            }
            SizeContext::NullTerminated => {
                let mut vec = Vec::<u8, SIZE>::new();
                loop {
                    let char = u8::decode(buf, ())?;
                    if char == 0 {break}
                    vec.push(char).or_else(|_| Err(DecodeError::Invalid))?;
                }
                String::<SIZE>::from_utf8(vec).or_else(|_| Err(DecodeError::Invalid))
            }
        }
    }
}