diff options
Diffstat (limited to 'src/asn1_types/tagged.rs')
-rw-r--r-- | src/asn1_types/tagged.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/asn1_types/tagged.rs b/src/asn1_types/tagged.rs new file mode 100644 index 0000000..c1652d4 --- /dev/null +++ b/src/asn1_types/tagged.rs @@ -0,0 +1,128 @@ +use crate::{Class, Error, Tag, Tagged}; +use core::marker::PhantomData; + +mod application; +mod builder; +mod explicit; +mod helpers; +mod implicit; +mod optional; +mod parser; +mod private; + +pub use application::*; +pub use builder::*; +pub use explicit::*; +pub use helpers::*; +pub use implicit::*; +pub use optional::*; +pub use parser::*; +pub use private::*; + +pub(crate) const CONTEXT_SPECIFIC: u8 = Class::ContextSpecific as u8; + +/// A type parameter for `IMPLICIT` tagged values. +#[derive(Debug, PartialEq, Eq)] +pub enum Implicit {} + +/// A type parameter for `EXPLICIT` tagged values. +#[derive(Debug, PartialEq, Eq)] +pub enum Explicit {} + +/// A type parameter for tagged values either [`Explicit`] or [`Implicit`]. +pub trait TagKind {} + +impl TagKind for Implicit {} +impl TagKind for Explicit {} + +/// Helper object for creating `FromBer`/`FromDer` types for TAGGED OPTIONAL types +/// +/// When parsing `ContextSpecific` (the most common class), see [`TaggedExplicit`] and +/// [`TaggedImplicit`] alias types. +/// +/// # Notes +/// +/// `CLASS` must be between 0 and 4. See [`Class`] for possible values for the `CLASS` parameter. +/// Constants from this class can be used, but they must be wrapped in braces due to +/// [Rust syntax for generics](https://doc.rust-lang.org/reference/items/generics.html) +/// (see example below). +/// +/// # Examples +/// +/// To parse a `[APPLICATION 0] EXPLICIT INTEGER` object: +/// +/// ```rust +/// use asn1_rs::{Class, Error, Explicit, FromBer, Integer, TaggedValue}; +/// +/// let bytes = &[0x60, 0x03, 0x2, 0x1, 0x2]; +/// +/// // If tagged object is present (and has expected tag), parsing succeeds: +/// let (_, tagged) = +/// TaggedValue::<Integer, Error, Explicit, {Class::APPLICATION}, 0>::from_ber(bytes) +/// .unwrap(); +/// assert_eq!(tagged, TaggedValue::explicit(Integer::from(2))); +/// ``` +#[derive(Debug, PartialEq, Eq)] +pub struct TaggedValue<T, E, TagKind, const CLASS: u8, const TAG: u32> { + pub(crate) inner: T, + + tag_kind: PhantomData<TagKind>, + _e: PhantomData<E>, +} + +impl<T, E, TagKind, const CLASS: u8, const TAG: u32> TaggedValue<T, E, TagKind, CLASS, TAG> { + /// Consumes the `TaggedParser`, returning the wrapped value. + #[inline] + pub fn into_inner(self) -> T { + self.inner + } + + /// Return the (outer) tag of this object + pub const fn tag(&self) -> Tag { + Self::TAG + } + + /// Return the (outer) class of this object + #[inline] + pub const fn class(&self) -> u8 { + CLASS + } +} + +impl<T, E, const CLASS: u8, const TAG: u32> TaggedValue<T, E, Explicit, CLASS, TAG> { + /// Constructs a new `EXPLICIT TaggedParser` with the provided value + #[inline] + pub const fn explicit(inner: T) -> Self { + TaggedValue { + inner, + tag_kind: PhantomData, + _e: PhantomData, + } + } +} + +impl<T, E, const CLASS: u8, const TAG: u32> TaggedValue<T, E, Implicit, CLASS, TAG> { + /// Constructs a new `IMPLICIT TaggedParser` with the provided value + #[inline] + pub const fn implicit(inner: T) -> Self { + TaggedValue { + inner, + tag_kind: PhantomData, + _e: PhantomData, + } + } +} + +impl<T, E, TagKind, const CLASS: u8, const TAG: u32> AsRef<T> + for TaggedValue<T, E, TagKind, CLASS, TAG> +{ + fn as_ref(&self) -> &T { + &self.inner + } +} + +impl<T, E, TagKind, const CLASS: u8, const TAG: u32> Tagged + for TaggedValue<T, E, TagKind, CLASS, TAG> +{ + const TAG: Tag = Tag(TAG); +} |