| //! Reader type for consuming nested TLV records within a DER document. |
| |
| use crate::{reader::Reader, Error, ErrorKind, Header, Length, Result}; |
| |
| /// Reader type used by [`Reader::read_nested`]. |
| pub struct NestedReader<'i, R> { |
| /// Inner reader type. |
| inner: &'i mut R, |
| |
| /// Nested input length. |
| input_len: Length, |
| |
| /// Position within the nested input. |
| position: Length, |
| } |
| |
| impl<'i, 'r, R: Reader<'r>> NestedReader<'i, R> { |
| /// Create a new nested reader which can read the given [`Length`]. |
| pub(crate) fn new(inner: &'i mut R, len: Length) -> Result<Self> { |
| if len <= inner.remaining_len() { |
| Ok(Self { |
| inner, |
| input_len: len, |
| position: Length::ZERO, |
| }) |
| } else { |
| Err(ErrorKind::Incomplete { |
| expected_len: (inner.offset() + len)?, |
| actual_len: (inner.offset() + inner.remaining_len())?, |
| } |
| .at(inner.offset())) |
| } |
| } |
| |
| /// Move the position cursor the given length, returning an error if there |
| /// isn't enough remaining data in the nested input. |
| fn advance_position(&mut self, len: Length) -> Result<()> { |
| let new_position = (self.position + len)?; |
| |
| if new_position <= self.input_len { |
| self.position = new_position; |
| Ok(()) |
| } else { |
| Err(ErrorKind::Incomplete { |
| expected_len: (self.inner.offset() + len)?, |
| actual_len: (self.inner.offset() + self.remaining_len())?, |
| } |
| .at(self.inner.offset())) |
| } |
| } |
| } |
| |
| impl<'i, 'r, R: Reader<'r>> Reader<'r> for NestedReader<'i, R> { |
| fn input_len(&self) -> Length { |
| self.input_len |
| } |
| |
| fn peek_byte(&self) -> Option<u8> { |
| if self.is_finished() { |
| None |
| } else { |
| self.inner.peek_byte() |
| } |
| } |
| |
| fn peek_header(&self) -> Result<Header> { |
| if self.is_finished() { |
| Err(Error::incomplete(self.offset())) |
| } else { |
| // TODO(tarcieri): handle peeking past nested length |
| self.inner.peek_header() |
| } |
| } |
| |
| fn position(&self) -> Length { |
| self.position |
| } |
| |
| fn read_slice(&mut self, len: Length) -> Result<&'r [u8]> { |
| self.advance_position(len)?; |
| self.inner.read_slice(len) |
| } |
| |
| fn error(&mut self, kind: ErrorKind) -> Error { |
| self.inner.error(kind) |
| } |
| |
| fn offset(&self) -> Length { |
| self.inner.offset() |
| } |
| |
| fn read_into<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> { |
| self.advance_position(Length::try_from(out.len())?)?; |
| self.inner.read_into(out) |
| } |
| } |