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