Skip to main content

nimbi_protocol/types/
id.rs

1use microdot::{deserialize::Deserialize, serialize::Serialize, MicrodotError};
2
3pub const ID_SIZE: usize = 6;
4
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6#[derive(Debug, PartialEq, Eq)]
7pub struct Id<'a>(&'a [u8; ID_SIZE]);
8
9impl<'a> Id<'a> {
10    pub fn from_str_unchecked(s: &'a str) -> Self {
11        let id = s.as_bytes()[..6].try_into().unwrap();
12
13        Id(id)
14    }
15}
16
17impl<'a> TryFrom<&'a str> for Id<'a> {
18    type Error = ParseIdError;
19
20    fn try_from(s: &'a str) -> Result<Id<'a>, Self::Error> {
21        let bytes = s.as_bytes();
22
23        if bytes.len() != 6 {
24            return Err(ParseIdError::IvalidLength);
25        }
26
27        let id = bytes.try_into().map_err(|_| ParseIdError::TryFromSlice)?;
28
29        Ok(Id(id))
30    }
31}
32
33#[derive(Debug)]
34pub enum ParseIdError {
35    IvalidLength,
36    TryFromSlice,
37}
38
39impl Serialize for Id<'_> {
40    fn serialize(&self, buf: &mut [u8]) -> Result<usize, MicrodotError> {
41        let bytes = &self.0[..];
42
43        bytes.serialize(buf)
44    }
45}
46
47impl<'a> Deserialize<'a> for Id<'a> {
48    fn deserialize(buf: &'a [u8]) -> Result<Id<'a>, MicrodotError> {
49        if buf.len() < ID_SIZE {
50            return Err(microdot::error::Error::invalid_length());
51        }
52
53        let id = buf[..6].try_into()?;
54
55        Ok(Self(id))
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn id_should_serialize() {
65        let id = Id(&[1, 1, 1, 1, 1, 1]);
66
67        let mut buf = [0u8; 6];
68
69        match id.serialize(&mut buf) {
70            Ok(bytes_written) => {
71                assert_eq!(bytes_written, 6);
72                assert_eq!(&buf[..], &[1, 1, 1, 1, 1, 1]);
73            }
74            Err(err) => {
75                dbg!(err);
76
77                unreachable!();
78            }
79        }
80    }
81}