asn1_rs/asn1_types/
set.rs

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