satrs_shared/
res_code.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3use spacepackets::ecss::{EcssEnumU16, EcssEnumeration};
4use spacepackets::util::UnsignedEnum;
5use spacepackets::ByteConversionError;
6
7/// Simple [u16] based result code type which also allows to group related resultcodes.
8#[derive(Debug, Copy, Clone, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub struct ResultU16 {
12    group_id: u8,
13    unique_id: u8,
14}
15
16impl ResultU16 {
17    #[inline]
18    pub const fn new(group_id: u8, unique_id: u8) -> Self {
19        Self {
20            group_id,
21            unique_id,
22        }
23    }
24
25    #[inline]
26    pub const fn raw(&self) -> u16 {
27        ((self.group_id as u16) << 8) | self.unique_id as u16
28    }
29
30    #[inline]
31    pub const fn group_id(&self) -> u8 {
32        self.group_id
33    }
34
35    #[inline]
36    pub const fn unique_id(&self) -> u8 {
37        self.unique_id
38    }
39
40    #[inline]
41    pub fn from_be_bytes(bytes: [u8; 2]) -> Self {
42        Self::from(u16::from_be_bytes(bytes))
43    }
44}
45
46impl From<u16> for ResultU16 {
47    fn from(value: u16) -> Self {
48        Self::new(((value >> 8) & 0xff) as u8, (value & 0xff) as u8)
49    }
50}
51
52impl From<ResultU16> for EcssEnumU16 {
53    fn from(v: ResultU16) -> Self {
54        EcssEnumU16::new(v.raw())
55    }
56}
57
58impl UnsignedEnum for ResultU16 {
59    #[inline]
60    fn size(&self) -> usize {
61        core::mem::size_of::<u16>()
62    }
63
64    fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
65        if buf.len() < 2 {
66            return Err(ByteConversionError::ToSliceTooSmall {
67                found: buf.len(),
68                expected: 2,
69            });
70        }
71        buf[0] = self.group_id;
72        buf[1] = self.unique_id;
73        Ok(self.size())
74    }
75
76    #[inline]
77    fn value_raw(&self) -> u64 {
78        self.raw() as u64
79    }
80}
81
82impl EcssEnumeration for ResultU16 {
83    #[inline]
84    fn pfc(&self) -> u8 {
85        16
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    const RESULT_CODE_CONST: ResultU16 = ResultU16::new(1, 1);
94
95    #[test]
96    pub fn test_basic() {
97        let result_code = ResultU16::new(1, 1);
98        assert_eq!(result_code.unique_id(), 1);
99        assert_eq!(result_code.group_id(), 1);
100        assert_eq!(result_code, RESULT_CODE_CONST);
101        assert_eq!(result_code.raw(), (1_u16 << 8) | 1);
102        assert_eq!(result_code.pfc(), 16);
103        assert_eq!(result_code.size(), 2);
104        let mut buf: [u8; 2] = [0; 2];
105        let written = result_code.write_to_be_bytes(&mut buf).unwrap();
106        assert_eq!(written, 2);
107        assert_eq!(buf[0], 1);
108        assert_eq!(buf[1], 1);
109        let read_back = ResultU16::from_be_bytes(buf);
110        assert_eq!(read_back, result_code);
111    }
112
113    #[test]
114    fn test_from_u16() {
115        let result_code = ResultU16::new(1, 1);
116        let result_code_2 = ResultU16::from(result_code.raw());
117        assert_eq!(result_code, result_code_2);
118    }
119}