sen66_interface/data/
product_data.rs

1use crate::{error::DataError, util::check_deserialization};
2
3/// Name of the sensor in ASCII
4#[derive(Clone, Copy)]
5pub struct ProductName(SmallString);
6
7impl TryFrom<&[u8]> for ProductName {
8    type Error = DataError;
9
10    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
11        Ok(ProductName(value.try_into()?))
12    }
13}
14
15impl ProductName {
16    /// Provides access the underlying buffer
17    pub fn get_name_buffer(&self) -> &[u8] {
18        self.0.get_buffer()
19    }
20}
21
22#[cfg(feature = "defmt")]
23impl defmt::Format for ProductName {
24    /// Writes the defmt representation to the Formatter.
25    fn format(&self, f: defmt::Formatter) {
26        defmt::write!(f, "{}", self.0)
27    }
28}
29
30/// Name of the sensor in ASCII
31#[derive(Clone, Copy)]
32pub struct SerialNumber(SmallString);
33
34impl SerialNumber {
35    /// Provides access the underlying buffer
36    pub fn get_serial_buffer(&self) -> &[u8] {
37        self.0.get_buffer()
38    }
39}
40
41impl TryFrom<&[u8]> for SerialNumber {
42    type Error = DataError;
43
44    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
45        Ok(SerialNumber(value.try_into()?))
46    }
47}
48
49#[cfg(feature = "defmt")]
50impl defmt::Format for SerialNumber {
51    /// Writes the defmt representation to the Formatter.
52    fn format(&self, f: defmt::Formatter) {
53        defmt::write!(f, "{}", self.0)
54    }
55}
56
57#[derive(Clone, Copy)]
58struct SmallString {
59    name: [u8; 32],
60    len: usize,
61}
62
63impl SmallString {
64    fn get_buffer(&self) -> &[u8] {
65        &self.name[0..self.len]
66    }
67}
68
69impl TryFrom<&[u8]> for SmallString {
70    type Error = DataError;
71
72    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
73        check_deserialization(data, 48)?;
74        let mut name = [0; 32];
75        let mut len = 0;
76        for (i, &c) in data.iter().enumerate() {
77            // Skip CRC bytes
78            if (i + 1) % 3 == 0 {
79                continue;
80            }
81            if !c.is_ascii() {
82                return Err(Self::Error::NotASCIIString);
83            }
84            name[len] = c;
85            len += 1;
86            if c == 0x00 {
87                break;
88            }
89        }
90
91        Ok(Self { name, len })
92    }
93}
94
95#[cfg(feature = "defmt")]
96impl defmt::Format for SmallString {
97    /// Writes the defmt representation to the Formatter.
98    fn format(&self, f: defmt::Formatter) {
99        // ProductName::TryFrom ensures that the data contained is ASCII and not longer than the
100        // first null-terminator
101        let output = unsafe { core::str::from_utf8_unchecked(&self.name[0..self.len]) };
102        defmt::write!(f, "{}", output)
103    }
104}