1use crate::error::{BerError, Result};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Length {
8 Definite(usize),
10 Indefinite,
12}
13
14impl Length {
15 pub const fn definite(len: usize) -> Self {
17 Length::Definite(len)
18 }
19
20 pub const fn indefinite() -> Self {
22 Length::Indefinite
23 }
24
25 pub fn is_definite(&self) -> bool {
27 matches!(self, Length::Definite(_))
28 }
29
30 pub fn is_indefinite(&self) -> bool {
32 matches!(self, Length::Indefinite)
33 }
34
35 pub fn value(&self) -> Option<usize> {
37 match self {
38 Length::Definite(len) => Some(*len),
39 Length::Indefinite => None,
40 }
41 }
42
43 pub fn encode(&self) -> Vec<u8> {
45 match self {
46 Length::Indefinite => vec![0x80],
47 Length::Definite(len) => {
48 if *len < 128 {
49 vec![*len as u8]
51 } else {
52 let mut bytes = Vec::new();
54 let mut remaining = *len;
55
56 while remaining > 0 {
57 bytes.push((remaining & 0xFF) as u8);
58 remaining >>= 8;
59 }
60
61 bytes.reverse();
62
63 let mut result = vec![0x80 | (bytes.len() as u8)];
64 result.extend(bytes);
65 result
66 }
67 }
68 }
69 }
70
71 pub fn decode(data: &[u8]) -> Result<(Self, usize)> {
73 if data.is_empty() {
74 return Err(BerError::UnexpectedEof.into());
75 }
76
77 let first_byte = data[0];
78
79 if first_byte == 0x80 {
80 Ok((Length::Indefinite, 1))
82 } else if (first_byte & 0x80) == 0 {
83 Ok((Length::Definite(first_byte as usize), 1))
85 } else {
86 let num_bytes = (first_byte & 0x7F) as usize;
88
89 if num_bytes == 0 {
90 return Err(BerError::InvalidLength.into());
91 }
92
93 if num_bytes > 8 {
94 return Err(BerError::LengthOverflow.into());
95 }
96
97 if data.len() < 1 + num_bytes {
98 return Err(BerError::UnexpectedEof.into());
99 }
100
101 let mut length: usize = 0;
102 for i in 0..num_bytes {
103 length = length
104 .checked_shl(8)
105 .ok_or(BerError::LengthOverflow)?
106 .checked_add(data[1 + i] as usize)
107 .ok_or(BerError::LengthOverflow)?;
108 }
109
110 Ok((Length::Definite(length), 1 + num_bytes))
111 }
112 }
113
114 pub fn encoded_size(len: usize) -> usize {
116 if len < 128 {
117 1
118 } else {
119 let mut size = 1; let mut remaining = len;
121 while remaining > 0 {
122 size += 1;
123 remaining >>= 8;
124 }
125 size
126 }
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_short_length_roundtrip() {
136 for len in 0..128usize {
137 let length = Length::Definite(len);
138 let encoded = length.encode();
139 assert_eq!(encoded.len(), 1);
140 let (decoded, size) = Length::decode(&encoded).unwrap();
141 assert_eq!(size, 1);
142 assert_eq!(length, decoded);
143 }
144 }
145
146 #[test]
147 fn test_long_length_roundtrip() {
148 for len in [128usize, 255, 256, 65535, 65536, 0xFFFFFF, 0x1000000] {
149 let length = Length::Definite(len);
150 let encoded = length.encode();
151 let (decoded, size) = Length::decode(&encoded).unwrap();
152 assert_eq!(size, encoded.len());
153 assert_eq!(length, decoded);
154 }
155 }
156
157 #[test]
158 fn test_indefinite_length() {
159 let length = Length::Indefinite;
160 let encoded = length.encode();
161 assert_eq!(encoded, vec![0x80]);
162 let (decoded, size) = Length::decode(&encoded).unwrap();
163 assert_eq!(size, 1);
164 assert_eq!(length, decoded);
165 }
166}