/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/src/reader/nested.rs
Line | Count | Source |
1 | | //! Reader type for consuming nested TLV records within a DER document. |
2 | | |
3 | | use crate::{reader::Reader, Error, ErrorKind, Header, Length, Result}; |
4 | | |
5 | | /// Reader type used by [`Reader::read_nested`]. |
6 | | pub 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 | | |
17 | | impl<'i, 'r, R: Reader<'r>> NestedReader<'i, R> { |
18 | | /// Create a new nested reader which can read the given [`Length`]. |
19 | 0 | pub(crate) fn new(inner: &'i mut R, len: Length) -> Result<Self> { |
20 | 0 | if len <= inner.remaining_len() { |
21 | 0 | Ok(Self { |
22 | 0 | inner, |
23 | 0 | input_len: len, |
24 | 0 | position: Length::ZERO, |
25 | 0 | }) |
26 | | } else { |
27 | | Err(ErrorKind::Incomplete { |
28 | 0 | expected_len: (inner.offset() + len)?, |
29 | 0 | actual_len: (inner.offset() + inner.remaining_len())?, |
30 | | } |
31 | 0 | .at(inner.offset())) |
32 | | } |
33 | 0 | } |
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 | 0 | fn advance_position(&mut self, len: Length) -> Result<()> { |
38 | 0 | let new_position = (self.position + len)?; |
39 | | |
40 | 0 | if new_position <= self.input_len { |
41 | 0 | self.position = new_position; |
42 | 0 | Ok(()) |
43 | | } else { |
44 | | Err(ErrorKind::Incomplete { |
45 | 0 | expected_len: (self.inner.offset() + len)?, |
46 | 0 | actual_len: (self.inner.offset() + self.remaining_len())?, |
47 | | } |
48 | 0 | .at(self.inner.offset())) |
49 | | } |
50 | 0 | } |
51 | | } |
52 | | |
53 | | impl<'i, 'r, R: Reader<'r>> Reader<'r> for NestedReader<'i, R> { |
54 | 0 | fn input_len(&self) -> Length { |
55 | 0 | self.input_len |
56 | 0 | } |
57 | | |
58 | 0 | fn peek_byte(&self) -> Option<u8> { |
59 | 0 | if self.is_finished() { |
60 | 0 | None |
61 | | } else { |
62 | 0 | self.inner.peek_byte() |
63 | | } |
64 | 0 | } |
65 | | |
66 | 0 | fn peek_header(&self) -> Result<Header> { |
67 | 0 | if self.is_finished() { |
68 | 0 | Err(Error::incomplete(self.offset())) |
69 | | } else { |
70 | | // TODO(tarcieri): handle peeking past nested length |
71 | 0 | self.inner.peek_header() |
72 | | } |
73 | 0 | } |
74 | | |
75 | 0 | fn position(&self) -> Length { |
76 | 0 | self.position |
77 | 0 | } |
78 | | |
79 | 0 | fn read_slice(&mut self, len: Length) -> Result<&'r [u8]> { |
80 | 0 | self.advance_position(len)?; |
81 | 0 | self.inner.read_slice(len) |
82 | 0 | } |
83 | | |
84 | 0 | fn error(&mut self, kind: ErrorKind) -> Error { |
85 | 0 | self.inner.error(kind) |
86 | 0 | } |
87 | | |
88 | 0 | fn offset(&self) -> Length { |
89 | 0 | self.inner.offset() |
90 | 0 | } |
91 | | |
92 | 0 | fn read_into<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> { |
93 | 0 | self.advance_position(Length::try_from(out.len())?)?; |
94 | 0 | self.inner.read_into(out) |
95 | 0 | } |
96 | | } |