1use crate::{Decode, DerOrd, Encode, Error, ErrorKind, Reader, Result, SliceWriter, Writer};
4use core::{
5 cmp::Ordering,
6 fmt,
7 ops::{Add, Sub},
8};
9
10const MAX_DER_OCTETS: usize = 5;
13
14const MAX_U32: u32 = 0xfff_ffff;
16
17#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
21pub struct Length(u32);
22
23impl Length {
24 pub const ZERO: Self = Self(0);
26
27 pub const ONE: Self = Self(1);
29
30 pub const MAX: Self = Self(MAX_U32);
32
33 pub const fn new(value: u16) -> Self {
37 Self(value as u32)
38 }
39
40 pub fn is_zero(self) -> bool {
42 self == Self::ZERO
43 }
44
45 pub fn for_tlv(self) -> Result<Self> {
48 Self::ONE + self.encoded_len()? + self
49 }
50
51 pub fn saturating_add(self, rhs: Self) -> Self {
53 Self(self.0.saturating_add(rhs.0))
54 }
55
56 pub fn saturating_sub(self, rhs: Self) -> Self {
58 Self(self.0.saturating_sub(rhs.0))
59 }
60
61 fn initial_octet(self) -> Option<u8> {
74 match self.0 {
75 0x80..=0xFF => Some(0x81),
76 0x100..=0xFFFF => Some(0x82),
77 0x10000..=0xFFFFFF => Some(0x83),
78 0x1000000..=MAX_U32 => Some(0x84),
79 _ => None,
80 }
81 }
82}
83
84impl Add for Length {
85 type Output = Result<Self>;
86
87 fn add(self, other: Self) -> Result<Self> {
88 self.0
89 .checked_add(other.0)
90 .ok_or_else(|| ErrorKind::Overflow.into())
91 .and_then(TryInto::try_into)
92 }
93}
94
95impl Add<u8> for Length {
96 type Output = Result<Self>;
97
98 fn add(self, other: u8) -> Result<Self> {
99 self + Length::from(other)
100 }
101}
102
103impl Add<u16> for Length {
104 type Output = Result<Self>;
105
106 fn add(self, other: u16) -> Result<Self> {
107 self + Length::from(other)
108 }
109}
110
111impl Add<u32> for Length {
112 type Output = Result<Self>;
113
114 fn add(self, other: u32) -> Result<Self> {
115 self + Length::try_from(other)?
116 }
117}
118
119impl Add<usize> for Length {
120 type Output = Result<Self>;
121
122 fn add(self, other: usize) -> Result<Self> {
123 self + Length::try_from(other)?
124 }
125}
126
127impl Add<Length> for Result<Length> {
128 type Output = Self;
129
130 fn add(self, other: Length) -> Self {
131 self? + other
132 }
133}
134
135impl Sub for Length {
136 type Output = Result<Self>;
137
138 fn sub(self, other: Length) -> Result<Self> {
139 self.0
140 .checked_sub(other.0)
141 .ok_or_else(|| ErrorKind::Overflow.into())
142 .and_then(TryInto::try_into)
143 }
144}
145
146impl Sub<Length> for Result<Length> {
147 type Output = Self;
148
149 fn sub(self, other: Length) -> Self {
150 self? - other
151 }
152}
153
154impl From<u8> for Length {
155 fn from(len: u8) -> Length {
156 Length(len.into())
157 }
158}
159
160impl From<u16> for Length {
161 fn from(len: u16) -> Length {
162 Length(len.into())
163 }
164}
165
166impl From<Length> for u32 {
167 fn from(length: Length) -> u32 {
168 length.0
169 }
170}
171
172impl TryFrom<u32> for Length {
173 type Error = Error;
174
175 fn try_from(len: u32) -> Result<Length> {
176 if len <= Self::MAX.0 {
177 Ok(Length(len))
178 } else {
179 Err(ErrorKind::Overflow.into())
180 }
181 }
182}
183
184impl TryFrom<usize> for Length {
185 type Error = Error;
186
187 fn try_from(len: usize) -> Result<Length> {
188 u32::try_from(len)
189 .map_err(|_| ErrorKind::Overflow)?
190 .try_into()
191 }
192}
193
194impl TryFrom<Length> for usize {
195 type Error = Error;
196
197 fn try_from(len: Length) -> Result<usize> {
198 len.0.try_into().map_err(|_| ErrorKind::Overflow.into())
199 }
200}
201
202impl<'a> Decode<'a> for Length {
203 fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Length> {
204 match reader.read_byte()? {
205 len if len < 0x80 => Ok(len.into()),
208 tag @ 0x81..=0x84 => {
210 let nbytes = tag.checked_sub(0x80).ok_or(ErrorKind::Overlength)? as usize;
211 debug_assert!(nbytes <= 4);
212
213 let mut decoded_len = 0u32;
214 for _ in 0..nbytes {
215 decoded_len = decoded_len.checked_shl(8).ok_or(ErrorKind::Overflow)?
216 | u32::from(reader.read_byte()?);
217 }
218
219 let length = Length::try_from(decoded_len)?;
220
221 if length.initial_octet() == Some(tag) {
224 Ok(length)
225 } else {
226 Err(ErrorKind::Overlength.into())
227 }
228 }
229 _ => {
230 Err(ErrorKind::Overlength.into())
232 }
233 }
234 }
235}
236
237impl Encode for Length {
238 fn encoded_len(&self) -> Result<Length> {
239 match self.0 {
240 0..=0x7F => Ok(Length(1)),
241 0x80..=0xFF => Ok(Length(2)),
242 0x100..=0xFFFF => Ok(Length(3)),
243 0x10000..=0xFFFFFF => Ok(Length(4)),
244 0x1000000..=MAX_U32 => Ok(Length(5)),
245 _ => Err(ErrorKind::Overflow.into()),
246 }
247 }
248
249 fn encode(&self, writer: &mut dyn Writer) -> Result<()> {
250 match self.initial_octet() {
251 Some(tag_byte) => {
252 writer.write_byte(tag_byte)?;
253
254 match self.0.to_be_bytes() {
256 [0, 0, 0, byte] => writer.write_byte(byte),
257 [0, 0, bytes @ ..] => writer.write(&bytes),
258 [0, bytes @ ..] => writer.write(&bytes),
259 bytes => writer.write(&bytes),
260 }
261 }
262 #[allow(clippy::cast_possible_truncation)]
263 None => writer.write_byte(self.0 as u8),
264 }
265 }
266}
267
268impl DerOrd for Length {
269 fn der_cmp(&self, other: &Self) -> Result<Ordering> {
270 let mut buf1 = [0u8; MAX_DER_OCTETS];
271 let mut buf2 = [0u8; MAX_DER_OCTETS];
272
273 let mut encoder1 = SliceWriter::new(&mut buf1);
274 encoder1.encode(self)?;
275
276 let mut encoder2 = SliceWriter::new(&mut buf2);
277 encoder2.encode(other)?;
278
279 Ok(encoder1.finish()?.cmp(encoder2.finish()?))
280 }
281}
282
283impl fmt::Display for Length {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 self.0.fmt(f)
286 }
287}
288
289#[cfg(test)]
290mod tests {
291 use super::Length;
292 use crate::{Decode, DerOrd, Encode, ErrorKind};
293 use core::cmp::Ordering;
294
295 #[test]
296 fn decode() {
297 assert_eq!(Length::ZERO, Length::from_der(&[0x00]).unwrap());
298
299 assert_eq!(Length::from(0x7Fu8), Length::from_der(&[0x7F]).unwrap());
300
301 assert_eq!(
302 Length::from(0x80u8),
303 Length::from_der(&[0x81, 0x80]).unwrap()
304 );
305
306 assert_eq!(
307 Length::from(0xFFu8),
308 Length::from_der(&[0x81, 0xFF]).unwrap()
309 );
310
311 assert_eq!(
312 Length::from(0x100u16),
313 Length::from_der(&[0x82, 0x01, 0x00]).unwrap()
314 );
315
316 assert_eq!(
317 Length::try_from(0x10000u32).unwrap(),
318 Length::from_der(&[0x83, 0x01, 0x00, 0x00]).unwrap()
319 );
320 }
321
322 #[test]
323 fn encode() {
324 let mut buffer = [0u8; 4];
325
326 assert_eq!(&[0x00], Length::ZERO.encode_to_slice(&mut buffer).unwrap());
327
328 assert_eq!(
329 &[0x7F],
330 Length::from(0x7Fu8).encode_to_slice(&mut buffer).unwrap()
331 );
332
333 assert_eq!(
334 &[0x81, 0x80],
335 Length::from(0x80u8).encode_to_slice(&mut buffer).unwrap()
336 );
337
338 assert_eq!(
339 &[0x81, 0xFF],
340 Length::from(0xFFu8).encode_to_slice(&mut buffer).unwrap()
341 );
342
343 assert_eq!(
344 &[0x82, 0x01, 0x00],
345 Length::from(0x100u16).encode_to_slice(&mut buffer).unwrap()
346 );
347
348 assert_eq!(
349 &[0x83, 0x01, 0x00, 0x00],
350 Length::try_from(0x10000u32)
351 .unwrap()
352 .encode_to_slice(&mut buffer)
353 .unwrap()
354 );
355 }
356
357 #[test]
358 fn reject_indefinite_lengths() {
359 assert!(Length::from_der(&[0x80]).is_err());
360 }
361
362 #[test]
363 fn add_overflows_when_max_length_exceeded() {
364 let result = Length::MAX + Length::ONE;
365 assert_eq!(
366 result.err().map(|err| err.kind()),
367 Some(ErrorKind::Overflow)
368 );
369 }
370
371 #[test]
372 fn der_ord() {
373 assert_eq!(Length::ONE.der_cmp(&Length::MAX).unwrap(), Ordering::Less);
374 }
375}