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}