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}