asn1_rs/asn1_types/
sequence.rs

1use crate::*;
2use alloc::borrow::Cow;
3#[cfg(not(feature = "std"))]
4use alloc::vec::Vec;
5use core::convert::TryFrom;
6
7mod iterator;
8mod sequence_of;
9mod vec;
10
11pub use iterator::*;
12pub use sequence_of::*;
13
14/// The `SEQUENCE` object is an ordered list of heteregeneous types.
15///
16/// Sequences can usually be of 2 types:
17/// - a list of different objects (`SEQUENCE`, usually parsed as a `struct`)
18/// - a list of similar objects (`SEQUENCE OF`, usually parsed as a `Vec<T>`)
19///
20/// The current object covers the former. For the latter, see the [`SequenceOf`] documentation.
21///
22/// The `Sequence` object contains the (*unparsed*) encoded representation of its content. It provides
23/// methods to parse and iterate contained objects, or convert the sequence to other types.
24///
25/// # Building a Sequence
26///
27/// To build a DER sequence:
28/// - if the sequence is composed of objects of the same type, the [`Sequence::from_iter_to_der`] method can be used
29/// - otherwise, the [`ToDer`] trait can be used to create content incrementally
30///
31#[cfg_attr(feature = "std", doc = r#"```"#)]
32#[cfg_attr(not(feature = "std"), doc = r#"```rust,compile_fail"#)]
33/// use asn1_rs::{Integer, Sequence, SerializeResult, ToDer};
34///
35/// fn build_seq<'a>() -> SerializeResult<Sequence<'a>> {
36///     let mut v = Vec::new();
37///     // add an Integer object (construct type):
38///     let i = Integer::from_u32(4);
39///     let _ = i.write_der(&mut v)?;
40///     // some primitive objects also implement `ToDer`. A string will be mapped as `Utf8String`:
41///     let _ = "abcd".write_der(&mut v)?;
42///     // return the sequence built from the DER content
43///     Ok(Sequence::new(v.into()))
44/// }
45///
46/// let seq = build_seq().unwrap();
47///
48/// ```
49///
50/// # Examples
51///
52#[cfg_attr(feature = "std", doc = r#"```"#)]
53#[cfg_attr(not(feature = "std"), doc = r#"```rust,compile_fail"#)]
54/// use asn1_rs::{Error, Sequence};
55///
56/// // build sequence
57/// let it = [2, 3, 4].iter();
58/// let seq = Sequence::from_iter_to_der(it).unwrap();
59///
60/// // `seq` now contains the serialized DER representation of the array
61///
62/// // iterate objects
63/// let mut sum = 0;
64/// for item in seq.der_iter::<u32, Error>() {
65///     // item has type `Result<u32>`, since parsing the serialized bytes could fail
66///     sum += item.expect("parsing list item failed");
67/// }
68/// assert_eq!(sum, 9);
69///
70/// ```
71///
72/// Note: the above example encodes a `SEQUENCE OF INTEGER` object, the [`SequenceOf`] object could
73/// be used to provide a simpler API.
74///
75#[derive(Clone, Debug, PartialEq, Eq)]
76pub struct Sequence<'a> {
77    /// Serialized DER representation of the sequence content
78    pub content: Cow<'a, [u8]>,
79}
80
81impl<'a> Sequence<'a> {
82    /// Build a sequence, given the provided content
83    pub const fn new(content: Cow<'a, [u8]>) -> Self {
84        Sequence { content }
85    }
86
87    /// Consume the sequence and return the content
88    #[inline]
89    pub fn into_content(self) -> Cow<'a, [u8]> {
90        self.content
91    }
92
93    /// Apply the parsing function to the sequence content, consuming the sequence
94    ///
95    /// Note: this function expects the caller to take ownership of content.
96    /// In some cases, handling the lifetime of objects is not easy (when keeping only references on
97    /// data). Other methods are provided (depending on the use case):
98    /// - [`Sequence::parse`] takes a reference on the sequence data, but does not consume it,
99    /// - [`Sequence::from_der_and_then`] does the parsing of the sequence and applying the function
100    ///   in one step, ensuring there are only references (and dropping the temporary sequence).
101    pub fn and_then<U, F, E>(self, op: F) -> ParseResult<'a, U, E>
102    where
103        F: FnOnce(Cow<'a, [u8]>) -> ParseResult<'a, U, E>,
104    {
105        op(self.content)
106    }
107
108    /// Same as [`Sequence::from_der_and_then`], but using BER encoding (no constraints).
109    pub fn from_ber_and_then<U, F, E>(bytes: &'a [u8], op: F) -> ParseResult<'a, U, E>
110    where
111        F: FnOnce(&'a [u8]) -> ParseResult<'a, U, E>,
112        E: From<Error>,
113    {
114        let (rem, seq) = Sequence::from_ber(bytes).map_err(Err::convert)?;
115        let data = match seq.content {
116            Cow::Borrowed(b) => b,
117            // Since 'any' is built from 'bytes', it is borrowed by construction
118            Cow::Owned(_) => unreachable!(),
119        };
120        let (_, res) = op(data)?;
121        Ok((rem, res))
122    }
123
124    /// Parse a DER sequence and apply the provided parsing function to content
125    ///
126    /// After parsing, the sequence object and header are discarded.
127    ///
128    /// ```
129    /// use asn1_rs::{FromDer, ParseResult, Sequence};
130    ///
131    /// // Parse a SEQUENCE {
132    /// //      a INTEGER (0..255),
133    /// //      b INTEGER (0..4294967296)
134    /// // }
135    /// // and return only `(a,b)
136    /// fn parser(i: &[u8]) -> ParseResult<(u8, u32)> {
137    ///     Sequence::from_der_and_then(i, |i| {
138    ///             let (i, a) = u8::from_der(i)?;
139    ///             let (i, b) = u32::from_der(i)?;
140    ///             Ok((i, (a, b)))
141    ///         }
142    ///     )
143    /// }
144    /// ```
145    pub fn from_der_and_then<U, F, E>(bytes: &'a [u8], op: F) -> ParseResult<'a, U, E>
146    where
147        F: FnOnce(&'a [u8]) -> ParseResult<'a, U, E>,
148        E: From<Error>,
149    {
150        let (rem, seq) = Sequence::from_der(bytes).map_err(Err::convert)?;
151        let data = match seq.content {
152            Cow::Borrowed(b) => b,
153            // Since 'any' is built from 'bytes', it is borrowed by construction
154            Cow::Owned(_) => unreachable!(),
155        };
156        let (_, res) = op(data)?;
157        Ok((rem, res))
158    }
159
160    /// Apply the parsing function to the sequence content (non-consuming version)
161    pub fn parse<F, T, E>(&'a self, mut f: F) -> ParseResult<'a, T, E>
162    where
163        F: FnMut(&'a [u8]) -> ParseResult<'a, T, E>,
164    {
165        let input: &[u8] = &self.content;
166        f(input)
167    }
168
169    /// Apply the parsing function to the sequence content (consuming version)
170    ///
171    /// Note: to parse and apply a parsing function in one step, use the
172    /// [`Sequence::from_der_and_then`] method.
173    ///
174    /// # Limitations
175    ///
176    /// This function fails if the sequence contains `Owned` data, because the parsing function
177    /// takes a reference on data (which is dropped).
178    pub fn parse_into<F, T, E>(self, mut f: F) -> ParseResult<'a, T, E>
179    where
180        F: FnMut(&'a [u8]) -> ParseResult<'a, T, E>,
181        E: From<Error>,
182    {
183        match self.content {
184            Cow::Borrowed(b) => f(b),
185            _ => Err(Err::Error(Error::LifetimeError.into())),
186        }
187    }
188
189    /// Return an iterator over the sequence content, attempting to decode objects as BER
190    ///
191    /// This method can be used when all objects from the sequence have the same type.
192    pub fn ber_iter<T, E>(&'a self) -> SequenceIterator<'a, T, BerParser, E>
193    where
194        T: FromBer<'a, E>,
195    {
196        SequenceIterator::new(&self.content)
197    }
198
199    /// Return an iterator over the sequence content, attempting to decode objects as DER
200    ///
201    /// This method can be used when all objects from the sequence have the same type.
202    pub fn der_iter<T, E>(&'a self) -> SequenceIterator<'a, T, DerParser, E>
203    where
204        T: FromDer<'a, E>,
205    {
206        SequenceIterator::new(&self.content)
207    }
208
209    /// Attempt to parse the sequence as a `SEQUENCE OF` items (BER), and return the parsed items as a `Vec`.
210    pub fn ber_sequence_of<T, E>(&'a self) -> Result<Vec<T>, E>
211    where
212        T: FromBer<'a, E>,
213        E: From<Error>,
214    {
215        self.ber_iter().collect()
216    }
217
218    /// Attempt to parse the sequence as a `SEQUENCE OF` items (DER), and return the parsed items as a `Vec`.
219    pub fn der_sequence_of<T, E>(&'a self) -> Result<Vec<T>, E>
220    where
221        T: FromDer<'a, E>,
222        E: From<Error>,
223    {
224        self.der_iter().collect()
225    }
226
227    /// Attempt to parse the sequence as a `SEQUENCE OF` items (BER) (consuming input),
228    /// and return the parsed items as a `Vec`.
229    ///
230    /// Note: if `Self` is an `Owned` object, the data will be duplicated (causing allocations) into separate objects.
231    pub fn into_ber_sequence_of<T, U, E>(self) -> Result<Vec<T>, E>
232    where
233        for<'b> T: FromBer<'b, E>,
234        E: From<Error>,
235        T: ToStatic<Owned = T>,
236    {
237        match self.content {
238            Cow::Borrowed(bytes) => SequenceIterator::<T, BerParser, E>::new(bytes).collect(),
239            Cow::Owned(data) => {
240                let v1 = SequenceIterator::<T, BerParser, E>::new(&data)
241                    .collect::<Result<Vec<T>, E>>()?;
242                let v2 = v1.iter().map(|t| t.to_static()).collect::<Vec<_>>();
243                Ok(v2)
244            }
245        }
246    }
247
248    /// Attempt to parse the sequence as a `SEQUENCE OF` items (DER) (consuming input),
249    /// and return the parsed items as a `Vec`.
250    ///
251    /// Note: if `Self` is an `Owned` object, the data will be duplicated (causing allocations) into separate objects.
252    pub fn into_der_sequence_of<T, U, E>(self) -> Result<Vec<T>, E>
253    where
254        for<'b> T: FromDer<'b, E>,
255        E: From<Error>,
256        T: ToStatic<Owned = T>,
257    {
258        match self.content {
259            Cow::Borrowed(bytes) => SequenceIterator::<T, DerParser, E>::new(bytes).collect(),
260            Cow::Owned(data) => {
261                let v1 = SequenceIterator::<T, DerParser, E>::new(&data)
262                    .collect::<Result<Vec<T>, E>>()?;
263                let v2 = v1.iter().map(|t| t.to_static()).collect::<Vec<_>>();
264                Ok(v2)
265            }
266        }
267    }
268
269    pub fn into_der_sequence_of_ref<T, E>(self) -> Result<Vec<T>, E>
270    where
271        T: FromDer<'a, E>,
272        E: From<Error>,
273    {
274        match self.content {
275            Cow::Borrowed(bytes) => SequenceIterator::<T, DerParser, E>::new(bytes).collect(),
276            Cow::Owned(_) => Err(Error::LifetimeError.into()),
277        }
278    }
279}
280
281impl ToStatic for Sequence<'_> {
282    type Owned = Sequence<'static>;
283
284    fn to_static(&self) -> Self::Owned {
285        Sequence {
286            content: Cow::Owned(self.content.to_vec()),
287        }
288    }
289}
290
291impl<T, U> ToStatic for Vec<T>
292where
293    T: ToStatic<Owned = U>,
294    U: 'static,
295{
296    type Owned = Vec<U>;
297
298    fn to_static(&self) -> Self::Owned {
299        self.iter().map(|t| t.to_static()).collect()
300    }
301}
302
303impl AsRef<[u8]> for Sequence<'_> {
304    fn as_ref(&self) -> &[u8] {
305        &self.content
306    }
307}
308
309impl<'a> TryFrom<Any<'a>> for Sequence<'a> {
310    type Error = Error;
311
312    fn try_from(any: Any<'a>) -> Result<Sequence<'a>> {
313        TryFrom::try_from(&any)
314    }
315}
316
317impl<'a, 'b> TryFrom<&'b Any<'a>> for Sequence<'a> {
318    type Error = Error;
319
320    fn try_from(any: &'b Any<'a>) -> Result<Sequence<'a>> {
321        any.tag().assert_eq(Self::TAG)?;
322        any.header.assert_constructed()?;
323        Ok(Sequence {
324            content: Cow::Borrowed(any.data),
325        })
326    }
327}
328
329impl CheckDerConstraints for Sequence<'_> {
330    fn check_constraints(_any: &Any) -> Result<()> {
331        // TODO: iterate on ANY objects and check constraints? -> this will not be exhaustive
332        // test, for ex INTEGER encoding will not be checked
333        Ok(())
334    }
335}
336
337impl DerAutoDerive for Sequence<'_> {}
338
339impl Tagged for Sequence<'_> {
340    const TAG: Tag = Tag::Sequence;
341}
342
343#[cfg(feature = "std")]
344impl ToDer for Sequence<'_> {
345    fn to_der_len(&self) -> Result<usize> {
346        let sz = self.content.len();
347        if sz < 127 {
348            // 1 (class+tag) + 1 (length) + len
349            Ok(2 + sz)
350        } else {
351            // 1 (class+tag) + n (length) + len
352            let n = Length::Definite(sz).to_der_len()?;
353            Ok(1 + n + sz)
354        }
355    }
356
357    fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
358        let header = Header::new(
359            Class::Universal,
360            true,
361            Self::TAG,
362            Length::Definite(self.content.len()),
363        );
364        header.write_der_header(writer)
365    }
366
367    fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
368        writer.write(&self.content).map_err(Into::into)
369    }
370}
371
372#[cfg(feature = "std")]
373impl Sequence<'_> {
374    /// Attempt to create a `Sequence` from an iterator over serializable objects (to DER)
375    ///
376    /// # Examples
377    ///
378    /// ```
379    /// use asn1_rs::Sequence;
380    ///
381    /// // build sequence
382    /// let it = [2, 3, 4].iter();
383    /// let seq = Sequence::from_iter_to_der(it).unwrap();
384    /// ```
385    pub fn from_iter_to_der<T, IT>(it: IT) -> SerializeResult<Self>
386    where
387        IT: Iterator<Item = T>,
388        T: ToDer,
389        T: Tagged,
390    {
391        let mut v = Vec::new();
392        for item in it {
393            let item_v = <T as ToDer>::to_der_vec(&item)?;
394            v.extend_from_slice(&item_v);
395        }
396        Ok(Sequence {
397            content: Cow::Owned(v),
398        })
399    }
400}