Skip to main content

der/reader/
slice.rs

1//! Slice reader.
2
3use super::position::Position;
4use crate::{BytesRef, Decode, EncodingRules, Error, ErrorKind, Length, Reader};
5
6/// [`Reader`] which consumes an input byte slice.
7#[derive(Clone, Debug)]
8pub struct SliceReader<'a> {
9    /// Byte slice being decoded.
10    bytes: &'a BytesRef,
11
12    /// Encoding rules to apply when decoding the input.
13    encoding_rules: EncodingRules,
14
15    /// Did the decoding operation fail?
16    failed: bool,
17
18    /// Position within the decoded slice.
19    position: Position,
20}
21
22impl<'a> SliceReader<'a> {
23    /// Create a new slice reader for the given byte slice.
24    ///
25    /// # Errors
26    /// If `bytes` is too long.
27    pub fn new(bytes: &'a [u8]) -> Result<Self, Error> {
28        Self::new_with_encoding_rules(bytes, EncodingRules::default())
29    }
30
31    /// Create a new slice reader with the given encoding rules.
32    ///
33    /// # Errors
34    /// If `bytes` is too long.
35    pub fn new_with_encoding_rules(
36        bytes: &'a [u8],
37        encoding_rules: EncodingRules,
38    ) -> Result<Self, Error> {
39        Ok(Self {
40            bytes: BytesRef::new(bytes)?,
41            encoding_rules,
42            failed: false,
43            position: Position::new(bytes.len().try_into()?),
44        })
45    }
46
47    /// Return an error with the given [`ErrorKind`], annotating it with context about where the
48    /// error occurred.
49    pub fn error(&mut self, kind: ErrorKind) -> Error {
50        self.failed = true;
51        self.position.error(kind)
52    }
53
54    /// Did the decoding operation fail due to an error?
55    #[must_use]
56    pub fn is_failed(&self) -> bool {
57        self.failed
58    }
59
60    /// Obtain the remaining bytes in this slice reader from the current cursor position.
61    pub(crate) fn remaining(&self) -> Result<&'a [u8], Error> {
62        if self.is_failed() {
63            Err(ErrorKind::Failed.at(self.position.current()))
64        } else {
65            self.bytes
66                .as_slice()
67                .get(self.position.current().try_into()?..)
68                .ok_or_else(|| Error::incomplete(self.input_len()))
69        }
70    }
71}
72
73impl<'a> Reader<'a> for SliceReader<'a> {
74    const CAN_READ_SLICE: bool = true;
75
76    fn encoding_rules(&self) -> EncodingRules {
77        self.encoding_rules
78    }
79
80    fn input_len(&self) -> Length {
81        self.bytes.len()
82    }
83
84    fn position(&self) -> Length {
85        self.position.current()
86    }
87
88    /// Read nested data of the given length.
89    #[inline]
90    fn read_nested<T, F, E>(&mut self, len: Length, f: F) -> Result<T, E>
91    where
92        F: FnOnce(&mut Self) -> Result<T, E>,
93        E: From<Error>,
94    {
95        // Slice `self.bytes` as a secondary check we don't read past end-of-slice
96        let bytes = self.bytes;
97        let prefix_len = (self.position.current() + len)?;
98        self.bytes = self.bytes.prefix(prefix_len)?;
99
100        let resumption = self.position.split_nested(len)?;
101        let ret = f(self);
102        let finished = self.is_finished();
103        let decoded = self.position.current();
104        let remaining = self.remaining_len();
105
106        self.bytes = bytes;
107        self.position.resume_nested(resumption);
108
109        if ret.is_ok() && !finished {
110            self.failed = true;
111            return Err(self
112                .error(ErrorKind::TrailingData { decoded, remaining })
113                .into());
114        };
115
116        ret
117    }
118
119    fn read_slice(&mut self, len: Length) -> Result<&'a [u8], Error> {
120        if self.is_failed() {
121            return Err(self.error(ErrorKind::Failed));
122        }
123
124        match self.remaining()?.get(..len.try_into()?) {
125            Some(result) => {
126                self.position.advance(len)?;
127                Ok(result)
128            }
129            None => Err(self.error(ErrorKind::Incomplete {
130                expected_len: (self.position.current() + len)?,
131                actual_len: self.input_len(),
132            })),
133        }
134    }
135
136    fn decode<T: Decode<'a>>(&mut self) -> Result<T, T::Error> {
137        if self.is_failed() {
138            return Err(self.error(ErrorKind::Failed).into());
139        }
140
141        T::decode(self).inspect_err(|_| {
142            self.failed = true;
143        })
144    }
145
146    fn error(&mut self, kind: ErrorKind) -> Error {
147        self.error(kind)
148    }
149
150    fn finish(mut self) -> Result<(), Error> {
151        if self.is_failed() {
152            Err(ErrorKind::Failed.at(self.position.current()))
153        } else if !self.is_finished() {
154            let decoded = self.position.current();
155            let remaining = self.remaining_len();
156            Err(self.error(ErrorKind::TrailingData { decoded, remaining }))
157        } else {
158            Ok(())
159        }
160    }
161
162    fn remaining_len(&self) -> Length {
163        self.position.remaining_len()
164    }
165}
166
167#[cfg(test)]
168#[allow(clippy::unwrap_used, clippy::panic, reason = "tests")]
169mod tests {
170    use super::SliceReader;
171    use crate::{Decode, Error, ErrorKind, Length, Reader};
172    use hex_literal::hex;
173
174    // INTEGER: 42
175    const EXAMPLE_MSG: &[u8] = &hex!("02012A00");
176
177    #[test]
178    fn empty_message() {
179        let mut reader = SliceReader::new(&[]).unwrap();
180        let err = bool::decode(&mut reader).err().unwrap();
181        assert_eq!(Some(Length::ZERO), err.position());
182
183        match err.kind() {
184            ErrorKind::Incomplete {
185                expected_len,
186                actual_len,
187            } => {
188                assert_eq!(actual_len, 0u8.into());
189                assert_eq!(expected_len, 1u8.into());
190            }
191            other => panic!("unexpected error kind: {:?}", other),
192        }
193    }
194
195    #[test]
196    fn invalid_field_length() {
197        const MSG_LEN: usize = 2;
198
199        let mut reader = SliceReader::new(&EXAMPLE_MSG[..MSG_LEN]).unwrap();
200        let err = i8::decode(&mut reader).err().unwrap();
201        assert_eq!(Some(Length::from(2u8)), err.position());
202
203        match err.kind() {
204            ErrorKind::Incomplete {
205                expected_len,
206                actual_len,
207            } => {
208                assert_eq!(actual_len, MSG_LEN.try_into().unwrap());
209                assert_eq!(expected_len, (MSG_LEN + 1).try_into().unwrap());
210            }
211            other => panic!("unexpected error kind: {:?}", other),
212        }
213    }
214
215    #[test]
216    fn trailing_data() {
217        let mut reader = SliceReader::new(EXAMPLE_MSG).unwrap();
218        let x = i8::decode(&mut reader).unwrap();
219        assert_eq!(42i8, x);
220
221        let err = reader.finish().err().unwrap();
222        assert_eq!(Some(Length::from(3u8)), err.position());
223
224        assert_eq!(
225            ErrorKind::TrailingData {
226                decoded: 3u8.into(),
227                remaining: 1u8.into(),
228            },
229            err.kind()
230        );
231    }
232
233    #[test]
234    fn nested_trailing_data() {
235        let der = hex!("0102");
236        let mut reader = SliceReader::new(&der).unwrap();
237
238        let err: Error = reader
239            .read_nested(2u8.into(), |reader| {
240                reader.read_slice(1u8.into())?;
241                Ok(())
242            })
243            .expect_err("read_nested should return Err when the callback did not consume the complete contents of the nested value");
244
245        assert_eq!(Length::ONE, err.position().unwrap());
246        assert_eq!(
247            ErrorKind::TrailingData {
248                decoded: 1u8.into(),
249                remaining: 1u8.into(),
250            },
251            err.kind()
252        );
253    }
254}