blob: ea52f7bded921ae7539241da4c1363b8f74ef8f8 [file] [log] [blame] [edit]
//! Reader trait.
pub(crate) 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")]
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)?)
}
}