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 {
66                actual: buf.len(),
67                expected: size,
68            });
69        }
70
71        match self {
72            Length::Standard(length) => {
73                let bytes = length.to_be_bytes();
74                buf[0] |= bytes[0];
75                buf[1] = bytes[1];
76            }
77            Length::Extended { upper, lower } => {
78                buf[0] |= *upper;
79
80                let bytes = lower.to_be_bytes();
81                buf[1] = bytes[0];
82                buf[2] = bytes[1];
83            }
84        }
85
86        Ok(size)
87    }
88
89    pub fn decode(buf: &[u8]) -> Result<Self, AcnError> {
90        if buf.len() < 2 {
91            return Err(AcnError::InvalidBufferLength {
92                actual: buf.len(),
93                expected: 2,
94            });
95        }
96
97        let flags = Flags::decode(buf)?;
98
99        let length = if flags.is_extended_length() {
100            if buf.len() < 3 {
101                return Err(AcnError::InvalidBufferLength {
102                    actual: buf.len(),
103                    expected: 3,
104                });
105            }
106
107            Length::Extended {
108                upper: buf[0],
109                lower: u16::from_be_bytes([buf[1], buf[2]]),
110            }
111        } else {
112            Length::Standard(u16::from_be_bytes([buf[0] & 0xf, buf[1]]))
113        };
114
115        Ok(length)
116    }
117}
118
119impl From<Length> for u32 {
120    fn from(length: Length) -> u32 {
121        length.as_u32()
122    }
123}
124
125impl From<Length> for usize {
126    fn from(length: Length) -> usize {
127        length.as_usize()
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134    use crate::flags::Flags;
135
136    #[test]
137    fn test_length_standard() {
138        let length = Length::new(100, Flags::empty());
139        assert_eq!(length, Length::Standard(102));
140        assert_eq!(length.size(), 2);
141        assert_eq!(length.as_usize(), 102);
142    }
143
144    #[test]
145    fn test_length_extended_from_extended_length() {
146        let length = Length::new(65536, Flags::empty());
147        assert_eq!(length, Length::Extended { upper: 1, lower: 3 });
148        assert_eq!(length.size(), 3);
149        assert_eq!(length.as_usize(), 65539);
150    }
151
152    #[test]
153    fn test_length_extended_from_flags() {
154        let length = Length::new(1024, Flags::EXTENDED_LENGTH);
155        assert_eq!(
156            length,
157            Length::Extended {
158                upper: 0,
159                lower: 1027
160            }
161        );
162        assert_eq!(length.size(), 3);
163        assert_eq!(length.as_usize(), 1027);
164    }
165
166    #[test]
167    fn test_length_encode_standard() {
168        let length = Length::Standard(102);
169        let mut buf = [0; 2];
170        length.encode(&mut buf).unwrap();
171        assert_eq!(buf, [0, 102]);
172    }
173
174    #[test]
175    fn test_length_encode_extended() {
176        let length = Length::Extended { upper: 1, lower: 3 };
177        let mut buf = [0; 3];
178        length.encode(&mut buf).unwrap();
179        assert_eq!(buf, [1, 0, 3]);
180    }
181}