use microdot::{deserialize::Deserialize, serialize::Serialize, MicrodotError};
pub const ID_SIZE: usize = 6;
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, PartialEq, Eq)]
pub struct Id<'a>(&'a [u8; ID_SIZE]);
impl<'a> Id<'a> {
pub fn from_str_unchecked(s: &'a str) -> Self {
let id = s.as_bytes()[..6].try_into().unwrap();
Id(id)
}
}
impl<'a> TryFrom<&'a str> for Id<'a> {
type Error = ParseIdError;
fn try_from(s: &'a str) -> Result<Id<'a>, Self::Error> {
let bytes = s.as_bytes();
if bytes.len() != 6 {
return Err(ParseIdError::IvalidLength);
}
let id = bytes.try_into().map_err(|_| ParseIdError::TryFromSlice)?;
Ok(Id(id))
}
}
#[derive(Debug)]
pub enum ParseIdError {
IvalidLength,
TryFromSlice,
}
impl Serialize for Id<'_> {
fn serialize(&self, buf: &mut [u8]) -> Result<usize, MicrodotError> {
let bytes = &self.0[..];
bytes.serialize(buf)
}
}
impl<'a> Deserialize<'a> for Id<'a> {
fn deserialize(buf: &'a [u8]) -> Result<Id<'a>, MicrodotError> {
if buf.len() < ID_SIZE {
return Err(microdot::error::Error::invalid_length());
}
let id = buf[..6].try_into()?;
Ok(Self(id))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn id_should_serialize() {
let id = Id(&[1, 1, 1, 1, 1, 1]);
let mut buf = [0u8; 6];
match id.serialize(&mut buf) {
Ok(bytes_written) => {
assert_eq!(bytes_written, 6);
assert_eq!(&buf[..], &[1, 1, 1, 1, 1, 1]);
}
Err(err) => {
dbg!(err);
unreachable!();
}
}
}
}