1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
//! # ASN.1 Data Types
//! The `types` modules is a collection of Rust types and data structures that
//! are defined to represent various ASN.1 data types, and renamed to use
//! ASN.1's terminology.
mod any;
mod instance;
mod open;
mod prefix;
mod tag;
pub mod constraints;
pub mod fields;
pub mod variants;
pub(crate) mod date;
pub(crate) mod integer;
pub(crate) mod oid;
pub(crate) mod strings;
use alloc::boxed::Box;
pub use {
self::{
any::Any,
constraints::{Constraint, Constraints, Extensible},
instance::InstanceOf,
integer::{ConstrainedInteger, Integer, IntegerType},
oid::{ObjectIdentifier, Oid},
open::Open,
prefix::{Explicit, Implicit},
strings::{
BitStr, BitString, BmpString, FixedBitString, FixedOctetString, GeneralString,
Ia5String, NumericString, OctetString, PrintableString, TeletexString, Utf8String,
VisibleString,
},
tag::{Class, Tag, TagTree},
},
rasn_derive::AsnType,
};
/// The `SET OF` type.
pub type SetOf<T> = alloc::collections::BTreeSet<T>;
/// The `UniversalString` type.
pub type UniversalString = Implicit<tag::UNIVERSAL_STRING, Utf8String>;
/// The `UTCTime` type.
pub type UtcTime = chrono::DateTime<chrono::Utc>;
/// The `GeneralizedTime` type.
pub type GeneralizedTime = chrono::DateTime<chrono::FixedOffset>;
/// The `Date` type.
pub type Date = chrono::NaiveDate;
/// The `SEQUENCE OF` type.
/// ## Usage
/// ASN1 declaration such as ...
/// ```asn
/// Test-type-a ::= SEQUENCE OF BOOLEAN
/// Test-type-b ::= SEQUENCE OF INTEGER(1,...)
/// ```
/// ... can be represented using `rasn` as ...
/// ```rust
/// use rasn::prelude::*;
///
/// #[derive(AsnType, Decode, Encode)]
/// #[rasn(delegate)]
/// struct TestTypeA(pub SequenceOf<bool>);
///
/// // Constrained inner primitive types need to be wrapped in a helper newtype
/// #[derive(AsnType, Decode, Encode)]
/// #[rasn(delegate, value("1", extensible))]
/// struct InnerTestTypeB(pub Integer);
///
/// #[derive(AsnType, Decode, Encode)]
/// #[rasn(delegate)]
/// struct TestTypeB(pub SequenceOf<InnerTestTypeB>);
/// ```
pub type SequenceOf<T> = alloc::vec::Vec<T>;
/// A trait representing any type that can represented in ASN.1.
pub trait AsnType {
/// The associated tag for the type.
///
/// **Note** When implementing CHOICE types, this should be set to
/// [`Tag::EOC`] and instead set the [`Self::TAG_TREE`] constant to contain
/// all variants.
const TAG: Tag;
/// The root of this type's tree of tag's if it a CHOICE type, otherwise its
/// `Leaf` that points [`Self::TAG`].
const TAG_TREE: TagTree = TagTree::Leaf(Self::TAG);
const CONSTRAINTS: Constraints<'static> = Constraints::NONE;
/// Identifier of an ASN.1 type as specified in the original specification
/// if not identical with the identifier of `Self`
const IDENTIFIER: Option<&'static str> = None;
}
/// A `SET` or `SEQUENCE` value.
pub trait Constructed {
/// Fields contained in the "root component list".
const FIELDS: self::fields::Fields;
/// Fields contained in the list of extensions.
const EXTENDED_FIELDS: Option<self::fields::Fields> = None;
}
/// A `CHOICE` value.
pub trait Choice: Sized {
/// Variants contained in the "root component list".
const VARIANTS: &'static [TagTree];
/// Variants contained in the list of extensions.
const EXTENDED_VARIANTS: Option<&'static [TagTree]> = None;
/// Variant identifiers for text-based encoding rules
const IDENTIFIERS: &'static [&'static str];
}
/// A `CHOICE` value.
pub trait DecodeChoice: Choice + crate::Decode {
/// Decode the choice value based on the provided `tag`.
fn from_tag<D: crate::Decoder>(decoder: &mut D, tag: Tag) -> Result<Self, D::Error>;
}
/// A `ENUMERATED` value.
pub trait Enumerated: Sized + 'static + PartialEq + Copy + core::fmt::Debug {
/// Variants contained in the "root component list".
const VARIANTS: &'static [Self];
/// Variants contained in the list of extensions.
const EXTENDED_VARIANTS: Option<&'static [Self]>;
/// Variants contained in the "root component list" mapped to their respective discriminant.
const DISCRIMINANTS: &'static [(Self, isize)];
/// Variants contained in the list of extensions mapped to their respective discriminant, if
/// present.
const EXTENDED_DISCRIMINANTS: Option<&'static [(Self, isize)]>;
/// Identifiers of enum variants
const IDENTIFIERS: &'static [&'static str];
/// Returns the number of "root" variants for a given type.
fn variance() -> usize {
Self::VARIANTS.len()
}
/// Returns the number of "extended" variants for a given type.
fn extended_variance() -> usize {
Self::EXTENDED_VARIANTS.map_or(0, |array| array.len())
}
/// Returns the number of "root" and "extended" variants for a given type.
fn complete_variance() -> usize {
Self::variance() + Self::extended_variance()
}
/// Whether `self` is a variant contained in `Self::EXTENDED_VARIANTS`.
fn is_extended_variant(&self) -> bool {
Self::EXTENDED_VARIANTS.map_or(false, |array| array.iter().any(|variant| variant == self))
}
/// Returns the enumeration for the variant, if it's an extended variant
/// then it will return it's extended enumeration index.
fn enumeration_index(&self) -> usize {
if self.is_extended_variant() {
Self::EXTENDED_VARIANTS
.unwrap()
.iter()
.position(|lhs| lhs == self)
.unwrap()
} else {
Self::VARIANTS
.iter()
.position(|lhs| lhs == self)
.expect("Variant not defined in Enumerated::VARIANTS")
}
}
/// Returns the discriminant value of `self`.
fn discriminant(&self) -> isize {
Self::DISCRIMINANTS
.iter()
.chain(
Self::EXTENDED_DISCRIMINANTS
.iter()
.flat_map(|array| array.iter()),
)
.find_map(|(lhs, value)| (lhs == self).then_some(*value))
.expect("variant not defined in `Enumerated`")
}
/// Returns a variant, if the provided discriminant matches any variant.
fn from_discriminant(value: isize) -> Option<Self> {
Self::DISCRIMINANTS
.iter()
.chain(
Self::EXTENDED_DISCRIMINANTS
.iter()
.flat_map(|array| array.iter()),
)
.find_map(|(variant, discriminant)| (value == *discriminant).then_some(*variant))
}
/// Returns a variant, if the index matches any "root" variant.
fn from_enumeration_index(index: usize) -> Option<Self> {
Self::VARIANTS.get(index).copied()
}
/// Returns a variant, if the index matches any "extended" variant.
fn from_extended_enumeration_index(index: usize) -> Option<Self> {
Self::EXTENDED_VARIANTS.and_then(|array| array.get(index).copied())
}
/// Returns the variant identifier
fn identifier(&self) -> &'static str {
let index = if self.is_extended_variant() {
Self::EXTENDED_VARIANTS
.unwrap()
.iter()
.position(|lhs| lhs == self)
.unwrap()
+ Self::VARIANTS.len()
} else {
Self::VARIANTS
.iter()
.position(|lhs| lhs == self)
.expect("Variant not defined in Enumerated::VARIANTS")
};
Self::IDENTIFIERS[index]
}
/// Returns a variant, if the provided identifier matches any variant.
fn from_identifier(identifier: &str) -> Option<Self> {
Self::IDENTIFIERS
.iter()
.enumerate()
.find(|id| id.1.eq(&identifier))
.and_then(|(i, _)| {
if i < Self::VARIANTS.len() {
Self::VARIANTS.get(i).copied()
} else {
Self::EXTENDED_VARIANTS
.and_then(|array| array.get(i - Self::VARIANTS.len()).copied())
}
})
}
}
macro_rules! asn_type {
($($name:ty: $value:ident),+) => {
$(
impl AsnType for $name {
const TAG: Tag = Tag::$value;
}
)+
}
}
asn_type! {
bool: BOOL,
Integer: INTEGER,
OctetString: OCTET_STRING,
ObjectIdentifier: OBJECT_IDENTIFIER,
Oid: OBJECT_IDENTIFIER,
Utf8String: UTF8_STRING,
UtcTime: UTC_TIME,
GeneralizedTime: GENERALIZED_TIME,
(): NULL,
&'_ str: UTF8_STRING
}
macro_rules! asn_integer_type {
($($int:ty),+ $(,)?) => {
$(
impl AsnType for $int {
const TAG: Tag = Tag::INTEGER;
const CONSTRAINTS: Constraints<'static> = Constraints::new(&[
constraints::Constraint::Value(Extensible::new(constraints::Value::new(constraints::Bounded::const_new(<$int>::MIN as i128, <$int>::MAX as i128)))),
]);
}
)+
}
}
asn_integer_type! {
i8,
i16,
i32,
i64,
i128,
isize,
u8,
u16,
u32,
u64,
u128, // TODO upper constraint truncated
usize,
}
impl AsnType for num_bigint::BigInt {
const TAG: Tag = Tag::INTEGER;
}
impl AsnType for str {
const TAG: Tag = Tag::UTF8_STRING;
}
impl<T: AsnType> AsnType for &'_ T {
const TAG: Tag = T::TAG;
const TAG_TREE: TagTree = T::TAG_TREE;
}
impl<T: AsnType> AsnType for Box<T> {
const TAG: Tag = T::TAG;
const TAG_TREE: TagTree = T::TAG_TREE;
}
impl<T: AsnType> AsnType for alloc::vec::Vec<T> {
const TAG: Tag = Tag::SEQUENCE;
}
impl<T: AsnType> AsnType for Option<T> {
const TAG: Tag = T::TAG;
const TAG_TREE: TagTree = T::TAG_TREE;
}
impl<T> AsnType for alloc::collections::BTreeSet<T> {
const TAG: Tag = Tag::SET;
}
impl<T: AsnType, const N: usize> AsnType for [T; N] {
const TAG: Tag = Tag::SEQUENCE;
const CONSTRAINTS: Constraints<'static> =
Constraints::new(&[Constraint::Size(Extensible::new(constraints::Size::new(
constraints::Bounded::single_value(N),
)))]);
}
impl<T> AsnType for &'_ [T] {
const TAG: Tag = Tag::SEQUENCE;
}
impl AsnType for Any {
const TAG: Tag = Tag::EOC;
const TAG_TREE: TagTree = TagTree::Choice(&[]);
}