1mod any;
7mod identifier;
8mod instance;
9mod open;
10mod prefix;
11mod tag;
12
13pub mod constraints;
14pub mod fields;
15pub mod variants;
16
17pub(crate) mod constructed;
18pub(crate) mod date;
19pub(crate) mod integer;
20pub(crate) mod oid;
21
22pub(crate) mod real;
23
24pub(crate) mod strings;
25
26use crate::macros::constraints;
27use alloc::boxed::Box;
28
29pub use {
30 self::{
31 any::Any,
32 constraints::{Constraint, Constraints, Extensible, InnerSubtypeConstraint},
33 constructed::{Constructed, SequenceOf, SetOf},
34 identifier::Identifier,
35 instance::InstanceOf,
36 integer::{ConstrainedInteger, Integer, IntegerType},
37 oid::{ObjectIdentifier, Oid},
38 open::Open,
39 prefix::{Explicit, Implicit},
40 strings::{
41 BitStr, BitString, BmpString, FixedBitString, FixedOctetString, GeneralString,
42 GraphicString, Ia5String, NumericString, OctetString, PrintableString, TeletexString,
43 Utf8String, VisibleString,
44 },
45 tag::{Class, Tag, TagTree},
46 },
47 rasn_derive::AsnType,
48};
49
50pub use self::real::RealType;
51
52pub type UniversalString = Implicit<tag::UNIVERSAL_STRING, Utf8String>;
54pub type UtcTime = chrono::DateTime<chrono::Utc>;
56pub type GeneralizedTime = chrono::DateTime<chrono::FixedOffset>;
58pub type Date = chrono::NaiveDate;
60
61pub trait AsnType {
63 const TAG: Tag;
69 const TAG_TREE: TagTree = TagTree::Leaf(Self::TAG);
72
73 const CONSTRAINTS: Constraints = Constraints::NONE;
75
76 const IDENTIFIER: Identifier = Identifier::EMPTY;
79
80 const IS_CHOICE: bool = false;
82
83 fn is_present(&self) -> bool {
87 true
88 }
89}
90
91pub trait Choice: Sized {
93 const VARIANTS: &'static [TagTree];
95 const VARIANCE_CONSTRAINT: Constraints;
97 const EXTENDED_VARIANTS: Option<&'static [TagTree]> = None;
99 const IDENTIFIERS: &'static [&'static str];
101}
102
103pub trait DecodeChoice: Choice + crate::Decode {
105 fn from_tag<D: crate::Decoder>(decoder: &mut D, tag: Tag) -> Result<Self, D::Error>;
107}
108
109pub trait Enumerated: Sized + 'static + PartialEq + Copy + core::fmt::Debug + AsnType {
111 const VARIANTS: &'static [Self];
113 const EXTENDED_VARIANTS: Option<&'static [Self]>;
115
116 const DISCRIMINANTS: &'static [(Self, isize)];
118 const EXTENDED_DISCRIMINANTS: Option<&'static [(Self, isize)]>;
121
122 const IDENTIFIERS: &'static [&'static str];
124
125 fn variance() -> usize {
127 Self::VARIANTS.len()
128 }
129
130 #[must_use]
132 fn extended_variance() -> usize {
133 Self::EXTENDED_VARIANTS.map_or(0, <[Self]>::len)
134 }
135
136 #[must_use]
138 fn complete_variance() -> usize {
139 Self::variance() + Self::extended_variance()
140 }
141
142 fn is_extended_variant(&self) -> bool {
144 Self::EXTENDED_VARIANTS.is_some_and(|array| array.iter().any(|variant| variant == self))
145 }
146
147 fn enumeration_index(&self) -> usize {
150 if self.is_extended_variant() {
151 Self::EXTENDED_VARIANTS
152 .unwrap()
153 .iter()
154 .position(|lhs| lhs == self)
155 .unwrap()
156 } else {
157 Self::VARIANTS
158 .iter()
159 .position(|lhs| lhs == self)
160 .expect("Variant not defined in Enumerated::VARIANTS")
161 }
162 }
163
164 fn discriminant(&self) -> isize {
166 Self::DISCRIMINANTS
167 .iter()
168 .chain(
169 Self::EXTENDED_DISCRIMINANTS
170 .iter()
171 .flat_map(|array| array.iter()),
172 )
173 .find_map(|(lhs, value)| (lhs == self).then_some(*value))
174 .expect("variant not defined in `Enumerated`")
175 }
176
177 fn from_discriminant(value: isize) -> Option<Self> {
179 Self::DISCRIMINANTS
180 .iter()
181 .chain(
182 Self::EXTENDED_DISCRIMINANTS
183 .iter()
184 .flat_map(|array| array.iter()),
185 )
186 .find_map(|(variant, discriminant)| (value == *discriminant).then_some(*variant))
187 }
188
189 fn from_enumeration_index(index: usize) -> Option<Self> {
191 Self::VARIANTS.get(index).copied()
192 }
193
194 #[must_use]
196 fn from_extended_enumeration_index(index: usize) -> Option<Self> {
197 Self::EXTENDED_VARIANTS.and_then(|array| array.get(index).copied())
198 }
199
200 fn identifier(&self) -> &'static str {
202 let index = if self.is_extended_variant() {
203 Self::EXTENDED_VARIANTS
204 .unwrap()
205 .iter()
206 .position(|lhs| lhs == self)
207 .unwrap()
208 + Self::VARIANTS.len()
209 } else {
210 Self::VARIANTS
211 .iter()
212 .position(|lhs| lhs == self)
213 .expect("Variant not defined in Enumerated::VARIANTS")
214 };
215 Self::IDENTIFIERS[index]
216 }
217
218 #[must_use]
220 fn from_identifier(identifier: &str) -> Option<Self> {
221 Self::IDENTIFIERS
222 .iter()
223 .enumerate()
224 .find(|id| id.1.eq(&identifier))
225 .and_then(|(i, _)| {
226 if i < Self::VARIANTS.len() {
227 Self::VARIANTS.get(i).copied()
228 } else {
229 Self::EXTENDED_VARIANTS
230 .and_then(|array| array.get(i - Self::VARIANTS.len()).copied())
231 }
232 })
233 }
234}
235
236macro_rules! asn_type {
237 ($($name:ty: $value:ident),+) => {
238 $(
239 impl AsnType for $name {
240 const TAG: Tag = Tag::$value;
241 const IDENTIFIER: Identifier = Identifier::$value;
242 }
243 )+
244 }
245}
246
247asn_type! {
248 bool: BOOL,
249 Integer: INTEGER,
250 OctetString: OCTET_STRING,
251 ObjectIdentifier: OBJECT_IDENTIFIER,
252 Oid: OBJECT_IDENTIFIER,
253 Utf8String: UTF8_STRING,
254 UtcTime: UTC_TIME,
255 GeneralizedTime: GENERALIZED_TIME,
256 (): NULL,
257 &'_ str: UTF8_STRING
258
259}
260
261macro_rules! asn_integer_type {
262 ($($int:ty),+ $(,)?) => {
263 $(
264 impl AsnType for $int {
265 const TAG: Tag = Tag::INTEGER;
266 const IDENTIFIER: Identifier = Identifier::INTEGER;
267 #[allow(clippy::cast_possible_wrap)]
268 const CONSTRAINTS: Constraints = constraints!(value_constraint!((<$int>::MIN as i128), (<$int>::MAX as i128)));
269 }
270 )+
271 }
272}
273
274asn_integer_type! {
275 i8,
276 i16,
277 i32,
278 i64,
279 i128,
280 isize,
281 u8,
282 u16,
283 u32,
284 u64,
285 u128, usize,
287}
288impl AsnType for num_bigint::BigInt {
289 const TAG: Tag = Tag::INTEGER;
290 const IDENTIFIER: Identifier = Identifier::INTEGER;
291}
292
293impl AsnType for str {
294 const TAG: Tag = Tag::UTF8_STRING;
295 const IDENTIFIER: Identifier = Identifier::UTF8_STRING;
296}
297
298impl<T: AsnType> AsnType for &'_ T {
299 const TAG: Tag = T::TAG;
300 const TAG_TREE: TagTree = T::TAG_TREE;
301 const IDENTIFIER: Identifier = T::IDENTIFIER;
302
303 fn is_present(&self) -> bool {
304 (*self).is_present()
305 }
306}
307
308impl<T: AsnType> AsnType for Box<T> {
309 const TAG: Tag = T::TAG;
310 const TAG_TREE: TagTree = T::TAG_TREE;
311 const IDENTIFIER: Identifier = T::IDENTIFIER;
312}
313
314impl<T: AsnType> AsnType for alloc::vec::Vec<T> {
315 const TAG: Tag = Tag::SEQUENCE;
316 const IDENTIFIER: Identifier = Identifier::SEQUENCE_OF;
317}
318
319impl<T: AsnType> AsnType for Option<T> {
320 const TAG: Tag = T::TAG;
321 const TAG_TREE: TagTree = T::TAG_TREE;
322 const IDENTIFIER: Identifier = T::IDENTIFIER;
323
324 fn is_present(&self) -> bool {
325 self.is_some()
326 }
327}
328
329impl<T> AsnType for SetOf<T> {
330 const TAG: Tag = Tag::SET;
331 const IDENTIFIER: Identifier = Identifier::SET_OF;
332}
333
334impl<T: AsnType, const N: usize> AsnType for [T; N] {
335 const TAG: Tag = Tag::SEQUENCE;
336 const CONSTRAINTS: Constraints = constraints!(size_constraint!(N));
337 const IDENTIFIER: Identifier = Identifier::SEQUENCE_OF;
338}
339
340impl<T> AsnType for &'_ [T] {
341 const TAG: Tag = Tag::SEQUENCE;
342 const IDENTIFIER: Identifier = Identifier::SEQUENCE_OF;
343}
344
345impl AsnType for Any {
346 const TAG: Tag = Tag::EOC;
347 const TAG_TREE: TagTree = TagTree::Choice(&[]);
348}
349
350#[cfg(feature = "f32")]
351impl AsnType for f32 {
352 const TAG: Tag = Tag::REAL;
353 const IDENTIFIER: Identifier = Identifier::REAL;
354}
355
356#[cfg(feature = "f64")]
357impl AsnType for f64 {
358 const TAG: Tag = Tag::REAL;
359 const IDENTIFIER: Identifier = Identifier::REAL;
360}
361
362impl<T> AsnType for core::marker::PhantomData<T> {
363 const TAG: Tag = Tag::NULL;
364 const TAG_TREE: TagTree = TagTree::Leaf(Tag::NULL);
365}