simple_tlv/
length.rs

1//! Length calculations for encoded ASN.1 DER values
2
3use crate::{Decodable, Decoder, Encodable, Encoder, Error, ErrorKind, Result};
4use core::{convert::{TryFrom, TryInto}, fmt, ops::Add};
5
6/// SIMPLE-TLV-encoded length.
7///
8/// By definition, in the range `0..=65535`
9///
10/// The length field consists of one or three consecutive bytes.
11/// - If the first byte is not `0xFF`, then the length field consists of a single byte encoding a number from
12///   zero to 254.
13/// - If the first byte is `0xFF`, then the length field consists of the subsequent two bytes interpreted as
14///   big-endian integer, with any value from zero to 65,535.
15#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
16pub struct Length(u16);
17
18impl Length {
19    /// Return a length of `0`.
20    pub const fn zero() -> Self {
21        Length(0)
22    }
23
24    /// Get the maximum length supported by SIMPLE-TLV: 65,535.
25    pub const fn max() -> usize {
26        u16::MAX as usize
27    }
28
29    /// Convert length to `usize`.
30    pub fn to_usize(self) -> usize {
31        self.0.into()
32    }
33}
34
35/// Calculate the sum of the encoded lengths of the encodables.
36impl<'a> TryFrom<&'a [&'a dyn Encodable]> for Length {
37    type Error = Error;
38    fn try_from(encodables: &[&dyn Encodable]) -> Result<Length> {
39        encodables
40            .iter()
41            .fold(Ok(Length::zero()), |sum, encodable| {
42                sum + encodable.encoded_length()?
43            })
44    }
45}
46
47impl Add for Length {
48    type Output = Result<Self>;
49
50    fn add(self, other: Self) -> Result<Self> {
51        self.0
52            .checked_add(other.0)
53            .map(Length)
54            .ok_or_else(|| ErrorKind::Overflow.into())
55    }
56}
57
58impl Add<u8> for Length {
59    type Output = Result<Self>;
60
61    fn add(self, other: u8) -> Result<Self> {
62        self + Length::from(other)
63    }
64}
65
66impl Add<u16> for Length {
67    type Output = Result<Self>;
68
69    fn add(self, other: u16) -> Result<Self> {
70        self + Length::from(other)
71    }
72}
73
74impl Add<usize> for Length {
75    type Output = Result<Self>;
76
77    fn add(self, other: usize) -> Result<Self> {
78        self + Length::try_from(other)?
79    }
80}
81
82impl Add<Length> for Result<Length> {
83    type Output = Self;
84
85    fn add(self, other: Length) -> Self {
86        self? + other
87    }
88}
89
90impl From<u8> for Length {
91    fn from(len: u8) -> Length {
92        Length(len as u16)
93    }
94}
95
96impl From<u16> for Length {
97    fn from(len: u16) -> Length {
98        Length(len)
99    }
100}
101
102impl From<Length> for u16 {
103    fn from(len: Length) -> u16 {
104        len.0
105    }
106}
107
108impl From<Length> for usize {
109    fn from(len: Length) -> usize {
110        len.0 as usize
111    }
112}
113
114impl TryFrom<usize> for Length {
115    type Error = Error;
116
117    fn try_from(len: usize) -> Result<Length> {
118        u16::try_from(len)
119            .map(Length)
120            .map_err(|_| ErrorKind::Overflow.into())
121    }
122}
123
124impl Decodable<'_> for Length {
125    fn decode(decoder: &mut Decoder<'_>) -> Result<Length> {
126        match decoder.byte()? {
127            0xFF => {
128                let be_len = decoder.bytes(2u8)?;
129                Ok(Length::from(u16::from_be_bytes(be_len.try_into().unwrap())))
130            }
131            len => Ok(len.into()),
132        }
133    }
134}
135
136impl Encodable for Length {
137    fn encoded_length(&self) -> Result<Length> {
138        match self.0 {
139            0..=0xFE => Ok(Length(1)),
140            _ => Ok(Length(3)),
141        }
142    }
143
144    fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
145        match self.0 {
146            0..=0xFE => encoder.byte(self.0 as u8),
147            _ => {
148                encoder.byte(0xFF)?;
149                encoder.bytes(&self.0.to_be_bytes())
150            }
151        }
152    }
153}
154
155impl fmt::Display for Length {
156    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157        self.0.fmt(f)
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::Length;
164    use crate::{Decodable, Encodable, Error, ErrorKind};
165
166    #[test]
167    fn decode() {
168        assert_eq!(Length::zero(), Length::from_bytes(&[0x00]).unwrap());
169
170        assert_eq!(Length::from(0x7Fu8), Length::from_bytes(&[0x7F]).unwrap());
171        assert_eq!(Length::from(0x7Fu8), Length::from_bytes(&[0xFF, 0x00, 0x7F]).unwrap());
172        assert_eq!(Length::from(0xFEu8), Length::from_bytes(&[0xFE]).unwrap());
173        assert_eq!(Length::from(0xFEu8), Length::from_bytes(&[0xFF, 0x00, 0xFE]).unwrap());
174
175        // these are the current errors, do we want them?
176        assert_eq!(Length::from_bytes(&[0xFF]).unwrap_err(), Error::from(ErrorKind::Truncated));
177        assert_eq!(Length::from_bytes(&[0xFF, 0x12]).unwrap_err(), Error::from(ErrorKind::Truncated));
178        // this is a bit clumsy to express
179        assert!(Length::from_bytes(&[0xFF, 0x12, 0x34, 0x56]).is_err());
180
181
182        assert_eq!(
183            Length::from(0xFFu8),
184            Length::from_bytes(&[0xFF, 0x00, 0xFF]).unwrap()
185        );
186
187        assert_eq!(
188            Length::from(0x100u16),
189            Length::from_bytes(&[0xFF, 0x01, 0x00]).unwrap()
190        );
191
192        assert_eq!(
193            Length::from(0xFFFFu16),
194            Length::from_bytes(&[0xFF, 0xFF, 0xFF]).unwrap()
195        );
196    }
197
198    #[test]
199    fn encode() {
200        let mut buffer = [0u8; 3];
201
202        assert_eq!(
203            &[0x00],
204            Length::zero().encode_to_slice(&mut buffer).unwrap()
205        );
206
207        assert_eq!(
208            &[0x7F],
209            Length::from(0x7Fu8).encode_to_slice(&mut buffer).unwrap()
210        );
211
212        assert_eq!(
213            &[0xFE],
214            Length::from(0xFEu8).encode_to_slice(&mut buffer).unwrap()
215        );
216
217        assert_eq!(
218            &[0xFF, 0x00, 0xFF],
219            Length::from(0xFFu8).encode_to_slice(&mut buffer).unwrap()
220        );
221
222        assert_eq!(
223            &[0xFF, 0x01, 0x00],
224            Length::from(0x100u16).encode_to_slice(&mut buffer).unwrap()
225        );
226
227        assert_eq!(
228            &[0xFF, 0xFF, 0xFF],
229            Length::from(0xFFFFu16).encode_to_slice(&mut buffer).unwrap()
230        );
231    }
232}