1use crate::{error::AcnError, flags::Flags};
2
3#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4pub enum Length {
5 Standard(u16), Extended { upper: u8, lower: u16 }, }
8
9impl Length {
10 pub const EXTENDED_LENGTH_THRESHOLD: usize = 4096;
11
12 pub fn new(length: usize, flags: Flags) -> Self {
13 let mut pdu_length = length + 2;
15
16 if pdu_length >= Self::EXTENDED_LENGTH_THRESHOLD || flags.is_extended_length() {
17 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}