nimbi-protocol 0.1.0

A crate for defining the nimbi-protocol used to communicate with microcontrollers
Documentation
pub mod check_update;

use check_update::{CheckUpdateRequest, CheckUpdateResponse};
use microdot::{
    helpers::{Header, HEADER_SIZE},
    Deserialize, MicrodotError, Serialize,
};

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug)]
pub enum Message<'a> {
    CheckUpdateRequest(CheckUpdateRequest<'a>),
    CheckUpdateResponse(CheckUpdateResponse),
}

impl Serialize for Message<'_> {
    fn serialize(&self, buf: &mut [u8]) -> Result<usize, MicrodotError> {
        use Message::*;

        let (header_buf, payload_buf) = buf.split_at_mut(HEADER_SIZE);

        let (id, msg) = match self {
            CheckUpdateRequest(msg) => (1, msg as &dyn Serialize),
            CheckUpdateResponse(msg) => (2, msg as &dyn Serialize),
        };

        let mut bytes_written = 0;

        bytes_written += msg.serialize(payload_buf)?;

        let header = Header {
            id,
            size: bytes_written,
        };

        bytes_written += header.serialize(header_buf)?;

        Ok(bytes_written)
    }
}

impl<'a> Deserialize<'a> for Message<'a> {
    fn deserialize(buf: &'a [u8]) -> Result<Self, MicrodotError> {
        let header = Header::deserialize(&buf[..HEADER_SIZE])?;

        let buf = &buf[HEADER_SIZE..header.size + HEADER_SIZE];

        Ok(match header.id {
            1 => Message::CheckUpdateRequest(CheckUpdateRequest::deserialize(buf)?),
            2 => Message::CheckUpdateResponse(CheckUpdateResponse::deserialize(buf)?),
            _ => return Err(MicrodotError::invalid_payload()),
        })
    }
}

#[cfg(test)]
mod tests {
    use crate::types::{Id, Version};

    use super::*;

    #[test]
    fn message_should_serialize() {
        // let msg = Message::CheckUpdateResponse()
    }

    #[test]
    fn message_should_deserialize() {
        let buf = [
            1, 0, 27, 1, 0, 6, 97, 49, 49, 49, 49, 49, 2, 0, 6, 97, 49, 49, 49, 49, 49, 3, 0, 6, 0,
            1, 0, 1, 0, 1,
        ];

        match Message::deserialize(&buf) {
            Ok(Message::CheckUpdateRequest(msg)) => {
                assert_eq!(msg.program_id, Id::from_str_unchecked("a11111"));
                assert_eq!(msg.release_channel_id, Id::from_str_unchecked("a11111"));
                assert_eq!(msg.current_version, Version::new(1, 1, 1));
            }
            Err(err) => {
                dbg!(err);

                unreachable!();
            }
            _ => unreachable!(),
        }
    }
}