der/reader/
nested.rs

1//! Reader type for consuming nested TLV records within a DER document.
2
3use crate::{reader::Reader, Error, ErrorKind, Header, Length, Result};
4
5/// Reader type used by [`Reader::read_nested`].
6pub struct NestedReader<'i, R> {
7    /// Inner reader type.
8    inner: &'i mut R,
9
10    /// Nested input length.
11    input_len: Length,
12
13    /// Position within the nested input.
14    position: Length,
15}
16
17impl<'i, 'r, R: Reader<'r>> NestedReader<'i, R> {
18    /// Create a new nested reader which can read the given [`Length`].
19    pub(crate) fn new(inner: &'i mut R, len: Length) -> Result<Self> {
20        if len <= inner.remaining_len() {
21            Ok(Self {
22                inner,
23                input_len: len,
24                position: Length::ZERO,
25            })
26        } else {
27            Err(ErrorKind::Incomplete {
28                expected_len: (inner.offset() + len)?,
29                actual_len: (inner.offset() + inner.remaining_len())?,
30            }
31            .at(inner.offset()))
32        }
33    }
34
35    /// Move the position cursor the given length, returning an error if there
36    /// isn't enough remaining data in the nested input.
37    fn advance_position(&mut self, len: Length) -> Result<()> {
38        let new_position = (self.position + len)?;
39
40        if new_position <= self.input_len {
41            self.position = new_position;
42            Ok(())
43        } else {
44            Err(ErrorKind::Incomplete {
45                expected_len: (self.inner.offset() + len)?,
46                actual_len: (self.inner.offset() + self.remaining_len())?,
47            }
48            .at(self.inner.offset()))
49        }
50    }
51}
52
53impl<'i, 'r, R: Reader<'r>> Reader<'r> for NestedReader<'i, R> {
54    fn input_len(&self) -> Length {
55        self.input_len
56    }
57
58    fn peek_byte(&self) -> Option<u8> {
59        if self.is_finished() {
60            None
61        } else {
62            self.inner.peek_byte()
63        }
64    }
65
66    fn peek_header(&self) -> Result<Header> {
67        if self.is_finished() {
68            Err(Error::incomplete(self.offset()))
69        } else {
70            // TODO(tarcieri): handle peeking past nested length
71            self.inner.peek_header()
72        }
73    }
74
75    fn position(&self) -> Length {
76        self.position
77    }
78
79    fn read_slice(&mut self, len: Length) -> Result<&'r [u8]> {
80        self.advance_position(len)?;
81        self.inner.read_slice(len)
82    }
83
84    fn error(&mut self, kind: ErrorKind) -> Error {
85        self.inner.error(kind)
86    }
87
88    fn offset(&self) -> Length {
89        self.inner.offset()
90    }
91
92    fn read_into<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
93        self.advance_position(Length::try_from(out.len())?)?;
94        self.inner.read_into(out)
95    }
96}