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