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::{Decodable, Encodable, EncodeValue, Encoder, FixedTag, Length, Result, Tag};
5
6/// ASN.1 `SEQUENCE` trait.
7///
8/// Types which impl this trait receive blanket impls for the [`Decodable`],
9/// [`Encodable`], and [`FixedTag`] traits.
10pub trait Sequence<'a>: Decodable<'a> {
11    /// Call the provided function with a slice of [`Encodable`] trait objects
12    /// representing the fields of this `SEQUENCE`.
13    ///
14    /// This method uses a callback because structs with fields which aren't
15    /// directly [`Encodable`] may need to construct temporary values from
16    /// their fields prior to encoding.
17    fn fields<F, T>(&self, f: F) -> Result<T>
18    where
19        F: FnOnce(&[&dyn Encodable]) -> Result<T>;
20}
21
22impl<'a, M> EncodeValue for M
23where
24    M: Sequence<'a>,
25{
26    fn value_len(&self) -> Result<Length> {
27        self.fields(|fields| {
28            fields
29                .iter()
30                .fold(Ok(Length::ZERO), |len, field| len + field.encoded_len()?)
31        })
32    }
33
34    fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
35        self.fields(|fields| {
36            for &field in fields {
37                field.encode(encoder)?;
38            }
39
40            Ok(())
41        })
42    }
43}
44
45impl<'a, M> FixedTag for M
46where
47    M: Sequence<'a>,
48{
49    const TAG: Tag = Tag::Sequence;
50}