| //! Reader trait. | |
| mod nested; | |
| #[cfg(feature = "pem")] | |
| pub(crate) mod pem; | |
| pub(crate) mod slice; | |
| pub(crate) use nested::NestedReader; | |
| use crate::{ | |
| asn1::ContextSpecific, Decode, DecodeValue, Encode, Error, ErrorKind, FixedTag, Header, Length, | |
| Result, Tag, TagMode, TagNumber, | |
| }; | |
| #[cfg(feature = "alloc")] | |
| use alloc::vec::Vec; | |
| /// Reader trait which reads DER-encoded input. | |
| pub trait Reader<'r>: Sized { | |
| /// Get the length of the input. | |
| fn input_len(&self) -> Length; | |
| /// Peek at the next byte of input without modifying the cursor. | |
| fn peek_byte(&self) -> Option<u8>; | |
| /// Peek forward in the input data, attempting to decode a [`Header`] from | |
| /// the data at the current position in the decoder. | |
| /// | |
| /// Does not modify the decoder's state. | |
| fn peek_header(&self) -> Result<Header>; | |
| /// Get the position within the buffer. | |
| fn position(&self) -> Length; | |
| /// Attempt to read data borrowed directly from the input as a slice, | |
| /// updating the internal cursor position. | |
| /// | |
| /// # Returns | |
| /// - `Ok(slice)` on success | |
| /// - `Err(ErrorKind::Incomplete)` if there is not enough data | |
| /// - `Err(ErrorKind::Reader)` if the reader can't borrow from the input | |
| fn read_slice(&mut self, len: Length) -> Result<&'r [u8]>; | |
| /// Attempt to decode an ASN.1 `CONTEXT-SPECIFIC` field with the | |
| /// provided [`TagNumber`]. | |
| fn context_specific<T>(&mut self, tag_number: TagNumber, tag_mode: TagMode) -> Result<Option<T>> | |
| where | |
| T: DecodeValue<'r> + FixedTag, | |
| { | |
| Ok(match tag_mode { | |
| TagMode::Explicit => ContextSpecific::<T>::decode_explicit(self, tag_number)?, | |
| TagMode::Implicit => ContextSpecific::<T>::decode_implicit(self, tag_number)?, | |
| } | |
| .map(|field| field.value)) | |
| } | |
| /// Decode a value which impls the [`Decode`] trait. | |
| fn decode<T: Decode<'r>>(&mut self) -> Result<T> { | |
| T::decode(self).map_err(|e| e.nested(self.position())) | |
| } | |
| /// Return an error with the given [`ErrorKind`], annotating it with | |
| /// context about where the error occurred. | |
| fn error(&mut self, kind: ErrorKind) -> Error { | |
| kind.at(self.position()) | |
| } | |
| /// Finish decoding, returning the given value if there is no | |
| /// remaining data, or an error otherwise | |
| fn finish<T>(self, value: T) -> Result<T> { | |
| if !self.is_finished() { | |
| Err(ErrorKind::TrailingData { | |
| decoded: self.position(), | |
| remaining: self.remaining_len(), | |
| } | |
| .at(self.position())) | |
| } else { | |
| Ok(value) | |
| } | |
| } | |
| /// Have we read all of the input data? | |
| fn is_finished(&self) -> bool { | |
| self.remaining_len().is_zero() | |
| } | |
| /// Offset within the original input stream. | |
| /// | |
| /// This is used for error reporting, and doesn't need to be overridden | |
| /// by any reader implementations (except for the built-in `NestedReader`, | |
| /// which consumes nested input messages) | |
| fn offset(&self) -> Length { | |
| self.position() | |
| } | |
| /// Peek at the next byte in the decoder and attempt to decode it as a | |
| /// [`Tag`] value. | |
| /// | |
| /// Does not modify the decoder's state. | |
| fn peek_tag(&self) -> Result<Tag> { | |
| match self.peek_byte() { | |
| Some(byte) => byte.try_into(), | |
| None => Err(Error::incomplete(self.input_len())), | |
| } | |
| } | |
| /// Read a single byte. | |
| fn read_byte(&mut self) -> Result<u8> { | |
| let mut buf = [0]; | |
| self.read_into(&mut buf)?; | |
| Ok(buf[0]) | |
| } | |
| /// Attempt to read input data, writing it into the provided buffer, and | |
| /// returning a slice on success. | |
| /// | |
| /// # Returns | |
| /// - `Ok(slice)` if there is sufficient data | |
| /// - `Err(ErrorKind::Incomplete)` if there is not enough data | |
| fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> { | |
| let input = self.read_slice(buf.len().try_into()?)?; | |
| buf.copy_from_slice(input); | |
| Ok(buf) | |
| } | |
| /// Read nested data of the given length. | |
| fn read_nested<'n, T, F>(&'n mut self, len: Length, f: F) -> Result<T> | |
| where | |
| F: FnOnce(&mut NestedReader<'n, Self>) -> Result<T>, | |
| { | |
| let mut reader = NestedReader::new(self, len)?; | |
| let ret = f(&mut reader)?; | |
| reader.finish(ret) | |
| } | |
| /// Read a byte vector of the given length. | |
| #[cfg(feature = "alloc")] | |
| #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] | |
| fn read_vec(&mut self, len: Length) -> Result<Vec<u8>> { | |
| let mut bytes = vec![0u8; usize::try_from(len)?]; | |
| self.read_into(&mut bytes)?; | |
| Ok(bytes) | |
| } | |
| /// Get the number of bytes still remaining in the buffer. | |
| fn remaining_len(&self) -> Length { | |
| debug_assert!(self.position() <= self.input_len()); | |
| self.input_len().saturating_sub(self.position()) | |
| } | |
| /// Read an ASN.1 `SEQUENCE`, creating a nested [`Reader`] for the body and | |
| /// calling the provided closure with it. | |
| fn sequence<'n, F, T>(&'n mut self, f: F) -> Result<T> | |
| where | |
| F: FnOnce(&mut NestedReader<'n, Self>) -> Result<T>, | |
| { | |
| let header = Header::decode(self)?; | |
| header.tag.assert_eq(Tag::Sequence)?; | |
| self.read_nested(header.length, f) | |
| } | |
| /// Obtain a slice of bytes contain a complete TLV production suitable for parsing later. | |
| fn tlv_bytes(&mut self) -> Result<&'r [u8]> { | |
| let header = self.peek_header()?; | |
| let header_len = header.encoded_len()?; | |
| self.read_slice((header_len + header.length)?) | |
| } | |
| } |