scd30_interface/data/
forced_recalibration_value.rs1use byteorder::{BigEndian, ByteOrder};
2
3use crate::error::DataError;
4use crate::util::check_deserialization;
5
6const MIN_FRC: u16 = 400;
7const MAX_FRC: u16 = 2000;
8const FRC_VAL: &str = "Forced recalibration value";
9const PARTICLE_UNIT: &str = "ppm";
10
11#[derive(Debug, PartialEq)]
14pub struct ForcedRecalibrationValue(u16);
15
16#[cfg(feature = "defmt")]
17impl defmt::Format for ForcedRecalibrationValue {
18 fn format(&self, f: defmt::Formatter) {
19 defmt::write!(f, "{}ppm", self.0)
20 }
21}
22
23impl ForcedRecalibrationValue {
24 pub const fn to_be_bytes(&self) -> [u8; 2] {
26 self.0.to_be_bytes()
27 }
28}
29
30impl TryFrom<u16> for ForcedRecalibrationValue {
31 type Error = DataError;
32
33 fn try_from(frc: u16) -> Result<Self, Self::Error> {
39 if !(MIN_FRC..=MAX_FRC).contains(&frc) {
40 Err(DataError::ValueOutOfRange {
41 parameter: FRC_VAL,
42 min: MIN_FRC,
43 max: MAX_FRC,
44 unit: PARTICLE_UNIT,
45 })
46 } else {
47 Ok(Self(frc))
48 }
49 }
50}
51
52impl TryFrom<&[u8]> for ForcedRecalibrationValue {
53 type Error = DataError;
54
55 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
63 check_deserialization(data, 3)?;
64 Ok(Self(BigEndian::read_u16(&data[..2])))
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn deserialize_sample_works() {
74 let data = [0x01, 0xC2, 0x50];
75 let frc = ForcedRecalibrationValue::try_from(&data[..]).unwrap();
76 assert_eq!(frc, ForcedRecalibrationValue(450));
77 }
78
79 #[test]
80 fn serialize_sample_works() {
81 let frc = ForcedRecalibrationValue(450);
82 assert_eq!(frc.to_be_bytes(), [0x01, 0xC2]);
83 }
84
85 #[test]
86 fn create_allowed_value_from_u16_works() {
87 let values = [400, 1200, 2000];
88 for value in values {
89 assert_eq!(
90 ForcedRecalibrationValue::try_from(value).unwrap(),
91 ForcedRecalibrationValue(value)
92 );
93 }
94 }
95
96 #[test]
97 fn create_from_u16_non_null_out_of_spec_value_errors() {
98 let values = [300, 2100];
99 for value in values {
100 assert_eq!(
101 ForcedRecalibrationValue::try_from(value).unwrap_err(),
102 DataError::ValueOutOfRange {
103 parameter: FRC_VAL,
104 min: 400,
105 max: 2000,
106 unit: PARTICLE_UNIT
107 }
108 );
109 }
110 }
111}