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