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 {
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}