rasn/
types.rs

1//! # ASN.1 Data Types
2//! The `types` modules is a collection of Rust types and data structures that
3//! are defined to represent various ASN.1 data types, and renamed to use
4//! ASN.1's terminology.
5
6mod any;
7mod instance;
8mod open;
9mod prefix;
10mod tag;
11
12pub mod constraints;
13pub mod fields;
14pub mod variants;
15
16pub(crate) mod oid;
17pub(crate) mod strings;
18
19use alloc::boxed::Box;
20use num_bigint::BigUint;
21
22pub use {
23    self::{
24        any::Any,
25        constraints::{Constraint, Constraints, Extensible},
26        instance::InstanceOf,
27        oid::{ObjectIdentifier, Oid},
28        open::Open,
29        prefix::{Explicit, Implicit},
30        strings::{
31            BitStr, BitString, BmpString, FixedBitString, FixedOctetString, GeneralString,
32            Ia5String, NumericString, OctetString, PrintableString, TeletexString, Utf8String,
33            VisibleString,
34        },
35        tag::{Class, Tag, TagTree},
36    },
37    num_bigint::BigInt as Integer,
38    rasn_derive::AsnType,
39};
40
41///  The `SET OF` type.
42pub type SetOf<T> = alloc::collections::BTreeSet<T>;
43///  The `UniversalString` type.
44pub type UniversalString = Implicit<tag::UNIVERSAL_STRING, Utf8String>;
45///  The `UTCTime` type.
46pub type UtcTime = chrono::DateTime<chrono::Utc>;
47///  The `GeneralizedTime` type.
48pub type GeneralizedTime = chrono::DateTime<chrono::FixedOffset>;
49///  The `SEQUENCE OF` type.
50/// ## Usage
51/// ASN1 declaration such as ...
52/// ```asn
53/// Test-type-a ::= SEQUENCE OF BOOLEAN
54/// Test-type-b ::= SEQUENCE OF INTEGER(1,...)
55/// ```
56/// ... can be represented using `rasn` as ...
57/// ```rust
58/// use rasn::prelude::*;
59///
60/// #[derive(AsnType, Decode, Encode)]
61/// #[rasn(delegate)]
62/// struct TestTypeA(pub SequenceOf<bool>);
63///
64/// // Constrained inner primitive types need to be wrapped in a helper newtype
65/// #[derive(AsnType, Decode, Encode)]
66/// #[rasn(delegate, value("1", extensible))]
67/// struct InnerTestTypeB(pub Integer);
68///  
69/// #[derive(AsnType, Decode, Encode)]
70/// #[rasn(delegate)]
71/// struct TestTypeB(pub SequenceOf<InnerTestTypeB>);
72/// ```
73pub type SequenceOf<T> = alloc::vec::Vec<T>;
74
75/// A trait representing any type that can represented in ASN.1.
76pub trait AsnType {
77    /// The associated tag for the type.
78    ///
79    /// **Note** When implementing CHOICE types, this should be set to
80    /// [`Tag::EOC`] and instead set the [`Self::TAG_TREE`] constant to contain
81    /// all variants.
82    const TAG: Tag;
83    /// The root of this type's tree of tag's if it a CHOICE type, otherwise its
84    /// `Leaf` that points [`Self::TAG`].
85    const TAG_TREE: TagTree = TagTree::Leaf(Self::TAG);
86
87    const CONSTRAINTS: Constraints<'static> = Constraints::NONE;
88
89    /// Identifier of an ASN.1 type as specified in the original specification
90    /// if not identical with the identifier of `Self`
91    const IDENTIFIER: Option<&'static str> = None;
92}
93
94/// A `SET` or `SEQUENCE` value.
95pub trait Constructed {
96    /// Fields contained in the "root component list".
97    const FIELDS: self::fields::Fields;
98    /// Fields contained in the list of extensions.
99    const EXTENDED_FIELDS: Option<self::fields::Fields> = None;
100}
101
102/// A `CHOICE` value.
103pub trait Choice: Sized {
104    /// Variants contained in the "root component list".
105    const VARIANTS: &'static [TagTree];
106    /// Variants contained in the list of extensions.
107    const EXTENDED_VARIANTS: Option<&'static [TagTree]> = None;
108    /// Variant identifiers for text-based encoding rules
109    const IDENTIFIERS: &'static [&'static str];
110}
111
112/// A `CHOICE` value.
113pub trait DecodeChoice: Choice + crate::Decode {
114    /// Decode the choice value based on the provided `tag`.
115    fn from_tag<D: crate::Decoder>(decoder: &mut D, tag: Tag) -> Result<Self, D::Error>;
116}
117
118/// A `ENUMERATED` value.
119pub trait Enumerated: Sized + 'static + PartialEq + Copy + core::fmt::Debug {
120    /// Variants contained in the "root component list".
121    const VARIANTS: &'static [Self];
122    /// Variants contained in the list of extensions.
123    const EXTENDED_VARIANTS: Option<&'static [Self]>;
124
125    /// Variants contained in the "root component list" mapped to their respective discriminant.
126    const DISCRIMINANTS: &'static [(Self, isize)];
127    /// Variants contained in the list of extensions mapped to their respective discriminant, if
128    /// present.
129    const EXTENDED_DISCRIMINANTS: Option<&'static [(Self, isize)]>;
130
131    /// Identifiers of enum variants
132    const IDENTIFIERS: &'static [&'static str];
133
134    /// Returns the number of "root" variants for a given type.
135    fn variance() -> usize {
136        Self::VARIANTS.len()
137    }
138
139    /// Returns the number of "extended" variants for a given type.
140    fn extended_variance() -> usize {
141        Self::EXTENDED_VARIANTS.map_or(0, |array| array.len())
142    }
143
144    /// Returns the number of "root" and "extended" variants for a given type.
145    fn complete_variance() -> usize {
146        Self::variance() + Self::extended_variance()
147    }
148
149    /// Whether `self` is a variant contained in `Self::EXTENDED_VARIANTS`.
150    fn is_extended_variant(&self) -> bool {
151        Self::EXTENDED_VARIANTS.map_or(false, |array| array.iter().any(|variant| variant == self))
152    }
153
154    /// Returns the enumeration for the variant, if it's an extended variant
155    /// then it will return it's extended enumeration index.
156    fn enumeration_index(&self) -> usize {
157        if self.is_extended_variant() {
158            Self::EXTENDED_VARIANTS
159                .unwrap()
160                .iter()
161                .position(|lhs| lhs == self)
162                .unwrap()
163        } else {
164            Self::VARIANTS
165                .iter()
166                .position(|lhs| lhs == self)
167                .expect("Variant not defined in Enumerated::VARIANTS")
168        }
169    }
170
171    /// Returns the discriminant value of `self`.
172    fn discriminant(&self) -> isize {
173        Self::DISCRIMINANTS
174            .iter()
175            .chain(
176                Self::EXTENDED_DISCRIMINANTS
177                    .iter()
178                    .flat_map(|array| array.iter()),
179            )
180            .find_map(|(lhs, value)| (lhs == self).then_some(*value))
181            .expect("variant not defined in `Enumerated`")
182    }
183
184    /// Returns a variant, if the provided discriminant matches any variant.
185    fn from_discriminant(value: isize) -> Option<Self> {
186        Self::DISCRIMINANTS
187            .iter()
188            .chain(
189                Self::EXTENDED_DISCRIMINANTS
190                    .iter()
191                    .flat_map(|array| array.iter()),
192            )
193            .find_map(|(variant, discriminant)| (value == *discriminant).then_some(*variant))
194    }
195
196    /// Returns a variant, if the index matches any "root" variant.
197    fn from_enumeration_index(index: usize) -> Option<Self> {
198        Self::VARIANTS.get(index).copied()
199    }
200
201    /// Returns a variant, if the index matches any "extended" variant.
202    fn from_extended_enumeration_index(index: usize) -> Option<Self> {
203        Self::EXTENDED_VARIANTS.and_then(|array| array.get(index).copied())
204    }
205
206    /// Returns the variant identifier
207    fn identifier(&self) -> &'static str {
208        let index = if self.is_extended_variant() {
209            Self::EXTENDED_VARIANTS
210                .unwrap()
211                .iter()
212                .position(|lhs| lhs == self)
213                .unwrap()
214                + Self::VARIANTS.len()
215        } else {
216            Self::VARIANTS
217                .iter()
218                .position(|lhs| lhs == self)
219                .expect("Variant not defined in Enumerated::VARIANTS")
220        };
221        Self::IDENTIFIERS[index]
222    }
223
224    /// Returns a variant, if the provided identifier matches any variant.
225    fn from_identifier(identifier: &str) -> Option<Self> {
226        Self::IDENTIFIERS
227            .iter()
228            .enumerate()
229            .find(|id| id.1.eq(&identifier))
230            .and_then(|(i, _)| {
231                if i < Self::VARIANTS.len() {
232                    Self::VARIANTS.get(i).copied()
233                } else {
234                    Self::EXTENDED_VARIANTS
235                        .and_then(|array| array.get(i - Self::VARIANTS.len()).copied())
236                }
237            })
238    }
239}
240
241/// A integer which has encoded constraint range between `START` and `END`.
242#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
243pub struct ConstrainedInteger<const START: i128, const END: i128>(pub(crate) Integer);
244
245impl<const START: i128, const END: i128> AsnType for ConstrainedInteger<START, END> {
246    const TAG: Tag = Tag::INTEGER;
247    const CONSTRAINTS: Constraints<'static> =
248        Constraints::new(&[constraints::Constraint::Value(Extensible::new(
249            constraints::Value::new(constraints::Bounded::const_new(START, END)),
250        ))]);
251}
252
253impl<const START: i128, const END: i128> core::ops::Deref for ConstrainedInteger<START, END> {
254    type Target = Integer;
255
256    fn deref(&self) -> &Self::Target {
257        &self.0
258    }
259}
260
261impl<T: Into<Integer>, const START: i128, const END: i128> From<T>
262    for ConstrainedInteger<START, END>
263{
264    fn from(value: T) -> Self {
265        Self(value.into())
266    }
267}
268
269macro_rules! asn_type {
270    ($($name:ty: $value:ident),+) => {
271        $(
272            impl AsnType for $name {
273                const TAG: Tag = Tag::$value;
274            }
275        )+
276    }
277}
278
279asn_type! {
280    bool: BOOL,
281    Integer: INTEGER,
282    OctetString: OCTET_STRING,
283    ObjectIdentifier: OBJECT_IDENTIFIER,
284    Oid: OBJECT_IDENTIFIER,
285    Utf8String: UTF8_STRING,
286    UtcTime: UTC_TIME,
287    GeneralizedTime: GENERALIZED_TIME,
288    (): NULL,
289    &'_ str: UTF8_STRING
290
291}
292
293macro_rules! asn_integer_type {
294    ($($int:ty),+ $(,)?) => {
295        $(
296            impl AsnType for $int {
297                const TAG: Tag = Tag::INTEGER;
298                const CONSTRAINTS: Constraints<'static> = Constraints::new(&[
299                    constraints::Constraint::Value(Extensible::new(constraints::Value::new(constraints::Bounded::const_new(<$int>::MIN as i128, <$int>::MAX as i128)))),
300                ]);
301            }
302        )+
303    }
304}
305
306asn_integer_type! {
307    i8,
308    i16,
309    i32,
310    i64,
311    i128,
312    isize,
313    u8,
314    u16,
315    u32,
316    u64,
317    u128,
318    usize,
319}
320
321pub trait IntegerType:
322    Sized
323    + Clone
324    + core::fmt::Debug
325    + TryFrom<i64>
326    + TryFrom<i128>
327    + TryInto<i128>
328    + Into<Integer>
329    + num_traits::Num
330    + num_traits::CheckedAdd
331{
332    const WIDTH: u32;
333
334    fn try_from_bytes(input: &[u8], codec: crate::Codec)
335        -> Result<Self, crate::error::DecodeError>;
336
337    fn try_from_signed_bytes(
338        input: &[u8],
339        codec: crate::Codec,
340    ) -> Result<Self, crate::error::DecodeError>;
341
342    fn try_from_unsigned_bytes(
343        input: &[u8],
344        codec: crate::Codec,
345    ) -> Result<Self, crate::error::DecodeError>;
346
347    // `num_traits::WrappingAdd` is not implemented for `BigInt`
348    #[doc(hidden)]
349    fn wrapping_add(self, other: Self) -> Self;
350}
351
352macro_rules! integer_type_decode {
353    ((signed $t1:ty, $t2:ty), $($ts:tt)*) => {
354        impl IntegerType for $t1 {
355            const WIDTH: u32 = <$t1>::BITS;
356
357            fn try_from_bytes(
358                input: &[u8],
359                codec: crate::Codec,
360            ) -> Result<Self, crate::error::DecodeError> {
361                Self::try_from_signed_bytes(input, codec)
362            }
363
364            fn try_from_signed_bytes(
365                input: &[u8],
366                codec: crate::Codec,
367            ) -> Result<Self, crate::error::DecodeError> {
368                const BYTE_SIZE: usize = (<$t1>::BITS / 8) as usize;
369                if input.is_empty() {
370                    return Err(crate::error::DecodeError::unexpected_empty_input(codec));
371                }
372
373                // in the case of superfluous leading bytes (especially zeroes),
374                // we may still want to try to decode the integer even though
375                // the length is >BYTE_SIZE ...
376                let leading_byte = if input[0] & 0x80 == 0x80 { 0xFF } else { 0x00 };
377                let input_iter = input.iter().copied().skip_while(|n| *n == leading_byte);
378                let data_length = input_iter.clone().count();
379
380                // ... but if its still too large after skipping leading bytes,
381                // there's no way to decode this without overflowing
382                if data_length > BYTE_SIZE {
383                    return Err(crate::error::DecodeError::integer_overflow(<$t1>::BITS, codec));
384                }
385
386                let mut bytes = [leading_byte; BYTE_SIZE];
387                let start = bytes.len() - data_length;
388
389                for (b, d) in bytes[start..].iter_mut().zip(input_iter) {
390                    *b = d;
391                }
392
393                Ok(Self::from_be_bytes(bytes))
394            }
395
396            fn try_from_unsigned_bytes(
397                input: &[u8],
398                codec: crate::Codec,
399            ) -> Result<Self, crate::error::DecodeError> {
400                Ok(<$t2>::try_from_bytes(input, codec)? as $t1)
401            }
402
403            fn wrapping_add(self, other: Self) -> Self {
404                self.wrapping_add(other)
405            }
406        }
407
408        integer_type_decode!($($ts)*);
409    };
410    ((unsigned $t1:ty, $t2:ty), $($ts:tt)*) => {
411        impl IntegerType for $t1 {
412            const WIDTH: u32 = <$t1>::BITS;
413
414            fn try_from_bytes(
415                input: &[u8],
416                codec: crate::Codec,
417            ) -> Result<Self, crate::error::DecodeError> {
418                Self::try_from_unsigned_bytes(input, codec)
419            }
420
421            fn try_from_signed_bytes(
422                input: &[u8],
423                codec: crate::Codec,
424            ) -> Result<Self, crate::error::DecodeError> {
425                Ok(<$t2>::try_from_bytes(input, codec)? as $t1)
426            }
427
428            fn try_from_unsigned_bytes(
429                input: &[u8],
430                codec: crate::Codec,
431            ) -> Result<Self, crate::error::DecodeError> {
432                const BYTE_SIZE: usize = (<$t1>::BITS / 8) as usize;
433                if input.is_empty() {
434                    return Err(crate::error::DecodeError::unexpected_empty_input(codec));
435                }
436
437                let input_iter = input.iter().copied().skip_while(|n| *n == 0x00);
438                let data_length = input_iter.clone().count();
439
440                if data_length > BYTE_SIZE {
441                    return Err(crate::error::DecodeError::integer_overflow(<$t1>::BITS, codec));
442                }
443
444                let mut bytes = [0x00; BYTE_SIZE];
445                let start = bytes.len() - data_length;
446
447                for (b, d) in bytes[start..].iter_mut().zip(input_iter) {
448                    *b = d;
449                }
450
451
452                Ok(Self::from_be_bytes(bytes))
453            }
454
455            fn wrapping_add(self, other: Self) -> Self {
456                self.wrapping_add(other)
457            }
458        }
459
460        integer_type_decode!($($ts)*);
461    };
462    (,) => {};
463    () => {};
464}
465
466integer_type_decode!(
467    (unsigned u8, i8),
468    (signed i8, u8),
469    (unsigned u16, i16),
470    (signed i16, u16),
471    (unsigned u32, i32),
472    (signed i32, u32),
473    (unsigned u64, i64),
474    (signed i64, u64),
475    (unsigned u128, i128),
476    (signed i128, u128),
477    (unsigned usize, isize),
478    (signed isize, usize),
479);
480
481impl IntegerType for Integer {
482    const WIDTH: u32 = u32::MAX;
483
484    fn try_from_bytes(
485        input: &[u8],
486        codec: crate::Codec,
487    ) -> Result<Self, crate::error::DecodeError> {
488        if input.is_empty() {
489            return Err(crate::error::DecodeError::unexpected_empty_input(codec));
490        }
491
492        Ok(Integer::from_signed_bytes_be(input))
493    }
494
495    fn try_from_signed_bytes(
496        input: &[u8],
497        codec: crate::Codec,
498    ) -> Result<Self, crate::error::DecodeError> {
499        Self::try_from_bytes(input, codec)
500    }
501
502    fn try_from_unsigned_bytes(
503        input: &[u8],
504        codec: crate::Codec,
505    ) -> Result<Self, crate::error::DecodeError> {
506        if input.is_empty() {
507            return Err(crate::error::DecodeError::unexpected_empty_input(codec));
508        }
509
510        Ok(BigUint::from_bytes_be(input).into())
511    }
512
513    fn wrapping_add(self, other: Self) -> Self {
514        self + other
515    }
516}
517
518impl AsnType for str {
519    const TAG: Tag = Tag::UTF8_STRING;
520}
521
522impl<T: AsnType> AsnType for &'_ T {
523    const TAG: Tag = T::TAG;
524    const TAG_TREE: TagTree = T::TAG_TREE;
525}
526
527impl<T: AsnType> AsnType for Box<T> {
528    const TAG: Tag = T::TAG;
529    const TAG_TREE: TagTree = T::TAG_TREE;
530}
531
532impl<T: AsnType> AsnType for alloc::vec::Vec<T> {
533    const TAG: Tag = Tag::SEQUENCE;
534}
535
536impl<T: AsnType> AsnType for Option<T> {
537    const TAG: Tag = T::TAG;
538    const TAG_TREE: TagTree = T::TAG_TREE;
539}
540
541impl<T> AsnType for alloc::collections::BTreeSet<T> {
542    const TAG: Tag = Tag::SET;
543}
544
545impl<T: AsnType, const N: usize> AsnType for [T; N] {
546    const TAG: Tag = Tag::SEQUENCE;
547    const CONSTRAINTS: Constraints<'static> =
548        Constraints::new(&[Constraint::Size(Extensible::new(constraints::Size::new(
549            constraints::Bounded::single_value(N),
550        )))]);
551}
552
553impl<T> AsnType for &'_ [T] {
554    const TAG: Tag = Tag::SEQUENCE;
555}
556
557impl AsnType for Any {
558    const TAG: Tag = Tag::EOC;
559    const TAG_TREE: TagTree = TagTree::Choice(&[]);
560}