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}