nimbi-protocol 0.1.0

A crate for defining the nimbi-protocol used to communicate with microcontrollers
Documentation
use microdot::{deserialize::Deserialize, serialize::Serialize, MicrodotError};

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, PartialEq, Eq)]
pub struct Version {
    pub major: u16,
    pub minor: u16,
    pub patch: u16,
}

impl Version {
    pub fn new(major: u16, minor: u16, patch: u16) -> Self {
        Self {
            major,
            minor,
            patch,
        }
    }
}

impl Serialize for Version {
    fn serialize(&self, buf: &mut [u8]) -> Result<usize, MicrodotError> {
        if buf.len() < 6 {
            return Err(MicrodotError::invalid_length());
        }

        let mut bytes_written = 0;

        bytes_written += self.major.serialize(&mut buf[bytes_written..])?;
        bytes_written += self.minor.serialize(&mut buf[bytes_written..])?;
        bytes_written += self.patch.serialize(&mut buf[bytes_written..])?;

        Ok(bytes_written)
    }
}

impl<'a> Deserialize<'a> for Version {
    fn deserialize(buf: &'a [u8]) -> Result<Self, MicrodotError> {
        if buf.len() < 6 {
            return Err(MicrodotError::invalid_length());
        }

        let major = u16::deserialize(&buf[..2])?;
        let minor = u16::deserialize(&buf[2..4])?;
        let patch = u16::deserialize(&buf[4..])?;

        Ok(Self::new(major, minor, patch))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn version_should_serialize() {
        let version = Version::new(1, 2, 3);

        let mut buf = [0u8; 6];

        match version.serialize(&mut buf) {
            Ok(bytes_written) => {
                assert_eq!(bytes_written, 6);
                assert_eq!(&buf[..], &[0, 1, 0, 2, 0, 3]);
            }
            Err(err) => {
                dbg!(err);

                unreachable!();
            }
        }
    }

    #[test]
    fn version_should_deserialize() {
        let buf = &[0, 1, 0, 2, 0, 3];

        match Version::deserialize(buf) {
            Ok(version) => {
                assert_eq!(version, Version::new(1, 2, 3));
            }
            Err(err) => {
                dbg!(err);

                unreachable!();
            }
        }
    }
}