der/asn1/
sequence.rs

1//! The [`Sequence`] trait simplifies writing decoders/encoders which map ASN.1
2//! `SEQUENCE`s to Rust structs.
3
4use crate::{
5    ByteSlice, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Result,
6    Tag, Writer,
7};
8
9/// ASN.1 `SEQUENCE` trait.
10///
11/// Types which impl this trait receive blanket impls for the [`Decode`],
12/// [`Encode`], and [`FixedTag`] traits.
13pub trait Sequence<'a>: Decode<'a> {
14    /// Call the provided function with a slice of [`Encode`] trait objects
15    /// representing the fields of this `SEQUENCE`.
16    ///
17    /// This method uses a callback because structs with fields which aren't
18    /// directly [`Encode`] may need to construct temporary values from
19    /// their fields prior to encoding.
20    fn fields<F, T>(&self, f: F) -> Result<T>
21    where
22        F: FnOnce(&[&dyn Encode]) -> Result<T>;
23}
24
25impl<'a, M> EncodeValue for M
26where
27    M: Sequence<'a>,
28{
29    fn value_len(&self) -> Result<Length> {
30        self.fields(|fields| {
31            fields
32                .iter()
33                .try_fold(Length::ZERO, |acc, field| acc + field.encoded_len()?)
34        })
35    }
36
37    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
38        self.fields(|fields| {
39            for &field in fields {
40                field.encode(writer)?;
41            }
42
43            Ok(())
44        })
45    }
46}
47
48impl<'a, M> FixedTag for M
49where
50    M: Sequence<'a>,
51{
52    const TAG: Tag = Tag::Sequence;
53}
54
55/// The [`SequenceRef`] type provides raw access to the octets which comprise a
56/// DER-encoded `SEQUENCE`.
57///
58/// This is a zero-copy reference type which borrows from the input data.
59pub struct SequenceRef<'a> {
60    /// Body of the `SEQUENCE`.
61    body: ByteSlice<'a>,
62}
63
64impl<'a> DecodeValue<'a> for SequenceRef<'a> {
65    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
66        Ok(Self {
67            body: ByteSlice::decode_value(reader, header)?,
68        })
69    }
70}
71
72impl EncodeValue for SequenceRef<'_> {
73    fn value_len(&self) -> Result<Length> {
74        Ok(self.body.len())
75    }
76
77    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
78        self.body.encode_value(writer)
79    }
80}
81
82impl<'a> FixedTag for SequenceRef<'a> {
83    const TAG: Tag = Tag::Sequence;
84}