acn_protocol/
length.rs

1use crate::{error::AcnError, flags::Flags};
2
3#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4pub enum Length {
5    Standard(u16),                      // Value is first 12 bits
6    Extended { upper: u8, lower: u16 }, // Value is first 20 bits
7}
8
9impl Length {
10    pub const EXTENDED_LENGTH_THRESHOLD: usize = 4096;
11
12    pub fn new(length: usize, flags: Flags) -> Self {
13        // Add the byte length of Length::Standard to the lengths of each segment
14        let mut pdu_length = length + 2;
15
16        if pdu_length >= Self::EXTENDED_LENGTH_THRESHOLD || flags.is_extended_length() {
17            // Length::Extended requires an extra byte
18            pdu_length += 1;
19
20            Length::Extended {
21                upper: (pdu_length >> 16 & 0xf) as u8,
22                lower: pdu_length as u16,
23            }
24        } else {
25            Length::Standard(pdu_length as u16 & 0xfff)
26        }
27    }
28
29    pub fn new_standard_from_u16(length: u16) -> Self {
30        let pdu_length = length + 2;
31        Length::Standard(pdu_length & 0xfff)
32    }
33
34    pub fn new_extended_from_u32(length: u32) -> Self {
35        let pdu_length = length + 3;
36
37        Length::Extended {
38            upper: (pdu_length >> 16 & 0xf) as u8,
39            lower: pdu_length as u16,
40        }
41    }
42
43    pub fn size(&self) -> usize {
44        match self {
45            Length::Standard(_) => 2,
46            Length::Extended { .. } => 3,
47        }
48    }
49
50    pub fn as_u32(&self) -> u32 {
51        match self {
52            Length::Standard(length) => *length as u32,
53            Length::Extended { upper, lower } => ((upper & 0xf) as u32) << 16 | *lower as u32,
54        }
55    }
56
57    pub fn as_usize(&self) -> usize {
58        self.as_u32() as usize
59    }
60
61    pub fn encode(&self, buf: &mut [u8]) -> Result<usize, AcnError> {
62        let size = self.size();
63
64        if buf.len() < size {
65            return Err(AcnError::InvalidBufferLength(buf.len()));
66        }
67
68        match self {
69            Length::Standard(length) => {
70                let bytes = length.to_be_bytes();
71                buf[0] |= bytes[0];
72                buf[1] = bytes[1];
73            }
74            Length::Extended { upper, lower } => {
75                buf[0] |= *upper;
76
77                let bytes = lower.to_be_bytes();
78                buf[1] = bytes[0];
79                buf[2] = bytes[1];
80            }
81        }
82
83        Ok(size)
84    }
85
86    pub fn decode(buf: &[u8]) -> Result<Self, AcnError> {
87        if buf.len() < 2 {
88            return Err(AcnError::InvalidBufferLength(buf.len()));
89        }
90
91        let flags = Flags::decode(buf)?;
92
93        let length = if flags.is_extended_length() {
94            if buf.len() < 3 {
95                return Err(AcnError::InvalidBufferLength(buf.len()));
96            }
97
98            Length::Extended {
99                upper: buf[0],
100                lower: u16::from_be_bytes([buf[1], buf[2]]),
101            }
102        } else {
103            Length::Standard(u16::from_be_bytes([buf[0] & 0xf, buf[1]]))
104        };
105
106        Ok(length)
107    }
108}
109
110impl From<Length> for u32 {
111    fn from(length: Length) -> u32 {
112        length.as_u32()
113    }
114}
115
116impl From<Length> for usize {
117    fn from(length: Length) -> usize {
118        length.as_usize()
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125    use crate::flags::Flags;
126
127    #[test]
128    fn test_length_standard() {
129        let length = Length::new(100, Flags::empty());
130        assert_eq!(length, Length::Standard(102));
131        assert_eq!(length.size(), 2);
132        assert_eq!(length.as_usize(), 102);
133    }
134
135    #[test]
136    fn test_length_extended_from_extended_length() {
137        let length = Length::new(65536, Flags::empty());
138        assert_eq!(length, Length::Extended { upper: 1, lower: 3 });
139        assert_eq!(length.size(), 3);
140        assert_eq!(length.as_usize(), 65539);
141    }
142
143    #[test]
144    fn test_length_extended_from_flags() {
145        let length = Length::new(1024, Flags::EXTENDED_LENGTH);
146        assert_eq!(
147            length,
148            Length::Extended {
149                upper: 0,
150                lower: 1027
151            }
152        );
153        assert_eq!(length.size(), 3);
154        assert_eq!(length.as_usize(), 1027);
155    }
156
157    #[test]
158    fn test_length_encode_standard() {
159        let length = Length::Standard(102);
160        let mut buf = [0; 2];
161        length.encode(&mut buf).unwrap();
162        assert_eq!(buf, [0, 102]);
163    }
164
165    #[test]
166    fn test_length_encode_extended() {
167        let length = Length::Extended { upper: 1, lower: 3 };
168        let mut buf = [0; 3];
169        length.encode(&mut buf).unwrap();
170        assert_eq!(buf, [1, 0, 3]);
171    }
172}