| //! The [`Sequence`] trait simplifies writing decoders/encoders which map ASN.1 | |
| //! `SEQUENCE`s to Rust structs. | |
| use crate::{ | |
| ByteSlice, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Result, | |
| Tag, Writer, | |
| }; | |
| /// ASN.1 `SEQUENCE` trait. | |
| /// | |
| /// Types which impl this trait receive blanket impls for the [`Decode`], | |
| /// [`Encode`], and [`FixedTag`] traits. | |
| pub trait Sequence<'a>: Decode<'a> { | |
| /// Call the provided function with a slice of [`Encode`] trait objects | |
| /// representing the fields of this `SEQUENCE`. | |
| /// | |
| /// This method uses a callback because structs with fields which aren't | |
| /// directly [`Encode`] may need to construct temporary values from | |
| /// their fields prior to encoding. | |
| fn fields<F, T>(&self, f: F) -> Result<T> | |
| where | |
| F: FnOnce(&[&dyn Encode]) -> Result<T>; | |
| } | |
| impl<'a, M> EncodeValue for M | |
| where | |
| M: Sequence<'a>, | |
| { | |
| fn value_len(&self) -> Result<Length> { | |
| self.fields(|fields| { | |
| fields | |
| .iter() | |
| .try_fold(Length::ZERO, |acc, field| acc + field.encoded_len()?) | |
| }) | |
| } | |
| fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { | |
| self.fields(|fields| { | |
| for &field in fields { | |
| field.encode(writer)?; | |
| } | |
| Ok(()) | |
| }) | |
| } | |
| } | |
| impl<'a, M> FixedTag for M | |
| where | |
| M: Sequence<'a>, | |
| { | |
| const TAG: Tag = Tag::Sequence; | |
| } | |
| /// The [`SequenceRef`] type provides raw access to the octets which comprise a | |
| /// DER-encoded `SEQUENCE`. | |
| /// | |
| /// This is a zero-copy reference type which borrows from the input data. | |
| pub struct SequenceRef<'a> { | |
| /// Body of the `SEQUENCE`. | |
| body: ByteSlice<'a>, | |
| } | |
| impl<'a> DecodeValue<'a> for SequenceRef<'a> { | |
| fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { | |
| Ok(Self { | |
| body: ByteSlice::decode_value(reader, header)?, | |
| }) | |
| } | |
| } | |
| impl EncodeValue for SequenceRef<'_> { | |
| fn value_len(&self) -> Result<Length> { | |
| Ok(self.body.len()) | |
| } | |
| fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { | |
| self.body.encode_value(writer) | |
| } | |
| } | |
| impl<'a> FixedTag for SequenceRef<'a> { | |
| const TAG: Tag = Tag::Sequence; | |
| } |