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, size_constraint, value_constraint};
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 fn extended_variance() -> usize {
132 Self::EXTENDED_VARIANTS.map_or(0, |array| array.len())
133 }
134
135 fn complete_variance() -> usize {
137 Self::variance() + Self::extended_variance()
138 }
139
140 fn is_extended_variant(&self) -> bool {
142 Self::EXTENDED_VARIANTS.is_some_and(|array| array.iter().any(|variant| variant == self))
143 }
144
145 fn enumeration_index(&self) -> usize {
148 if self.is_extended_variant() {
149 Self::EXTENDED_VARIANTS
150 .unwrap()
151 .iter()
152 .position(|lhs| lhs == self)
153 .unwrap()
154 } else {
155 Self::VARIANTS
156 .iter()
157 .position(|lhs| lhs == self)
158 .expect("Variant not defined in Enumerated::VARIANTS")
159 }
160 }
161
162 fn discriminant(&self) -> isize {
164 Self::DISCRIMINANTS
165 .iter()
166 .chain(
167 Self::EXTENDED_DISCRIMINANTS
168 .iter()
169 .flat_map(|array| array.iter()),
170 )
171 .find_map(|(lhs, value)| (lhs == self).then_some(*value))
172 .expect("variant not defined in `Enumerated`")
173 }
174
175 fn from_discriminant(value: isize) -> Option<Self> {
177 Self::DISCRIMINANTS
178 .iter()
179 .chain(
180 Self::EXTENDED_DISCRIMINANTS
181 .iter()
182 .flat_map(|array| array.iter()),
183 )
184 .find_map(|(variant, discriminant)| (value == *discriminant).then_some(*variant))
185 }
186
187 fn from_enumeration_index(index: usize) -> Option<Self> {
189 Self::VARIANTS.get(index).copied()
190 }
191
192 fn from_extended_enumeration_index(index: usize) -> Option<Self> {
194 Self::EXTENDED_VARIANTS.and_then(|array| array.get(index).copied())
195 }
196
197 fn identifier(&self) -> &'static str {
199 let index = if self.is_extended_variant() {
200 Self::EXTENDED_VARIANTS
201 .unwrap()
202 .iter()
203 .position(|lhs| lhs == self)
204 .unwrap()
205 + Self::VARIANTS.len()
206 } else {
207 Self::VARIANTS
208 .iter()
209 .position(|lhs| lhs == self)
210 .expect("Variant not defined in Enumerated::VARIANTS")
211 };
212 Self::IDENTIFIERS[index]
213 }
214
215 fn from_identifier(identifier: &str) -> Option<Self> {
217 Self::IDENTIFIERS
218 .iter()
219 .enumerate()
220 .find(|id| id.1.eq(&identifier))
221 .and_then(|(i, _)| {
222 if i < Self::VARIANTS.len() {
223 Self::VARIANTS.get(i).copied()
224 } else {
225 Self::EXTENDED_VARIANTS
226 .and_then(|array| array.get(i - Self::VARIANTS.len()).copied())
227 }
228 })
229 }
230}
231
232macro_rules! asn_type {
233 ($($name:ty: $value:ident),+) => {
234 $(
235 impl AsnType for $name {
236 const TAG: Tag = Tag::$value;
237 const IDENTIFIER: Identifier = Identifier::$value;
238 }
239 )+
240 }
241}
242
243asn_type! {
244 bool: BOOL,
245 Integer: INTEGER,
246 OctetString: OCTET_STRING,
247 ObjectIdentifier: OBJECT_IDENTIFIER,
248 Oid: OBJECT_IDENTIFIER,
249 Utf8String: UTF8_STRING,
250 UtcTime: UTC_TIME,
251 GeneralizedTime: GENERALIZED_TIME,
252 (): NULL,
253 &'_ str: UTF8_STRING
254
255}
256
257macro_rules! asn_integer_type {
258 ($($int:ty),+ $(,)?) => {
259 $(
260 impl AsnType for $int {
261 const TAG: Tag = Tag::INTEGER;
262 const IDENTIFIER: Identifier = Identifier::INTEGER;
263 const CONSTRAINTS: Constraints = constraints!(value_constraint!((<$int>::MIN as i128), (<$int>::MAX as i128)));
264 }
265 )+
266 }
267}
268
269asn_integer_type! {
270 i8,
271 i16,
272 i32,
273 i64,
274 i128,
275 isize,
276 u8,
277 u16,
278 u32,
279 u64,
280 u128, usize,
282}
283impl AsnType for num_bigint::BigInt {
284 const TAG: Tag = Tag::INTEGER;
285 const IDENTIFIER: Identifier = Identifier::INTEGER;
286}
287
288impl AsnType for str {
289 const TAG: Tag = Tag::UTF8_STRING;
290 const IDENTIFIER: Identifier = Identifier::UTF8_STRING;
291}
292
293impl<T: AsnType> AsnType for &'_ T {
294 const TAG: Tag = T::TAG;
295 const TAG_TREE: TagTree = T::TAG_TREE;
296 const IDENTIFIER: Identifier = T::IDENTIFIER;
297
298 fn is_present(&self) -> bool {
299 (*self).is_present()
300 }
301}
302
303impl<T: AsnType> AsnType for Box<T> {
304 const TAG: Tag = T::TAG;
305 const TAG_TREE: TagTree = T::TAG_TREE;
306 const IDENTIFIER: Identifier = T::IDENTIFIER;
307}
308
309impl<T: AsnType> AsnType for alloc::vec::Vec<T> {
310 const TAG: Tag = Tag::SEQUENCE;
311 const IDENTIFIER: Identifier = Identifier::SEQUENCE_OF;
312}
313
314impl<T: AsnType> AsnType for Option<T> {
315 const TAG: Tag = T::TAG;
316 const TAG_TREE: TagTree = T::TAG_TREE;
317 const IDENTIFIER: Identifier = T::IDENTIFIER;
318
319 fn is_present(&self) -> bool {
320 self.is_some()
321 }
322}
323
324impl<T> AsnType for SetOf<T> {
325 const TAG: Tag = Tag::SET;
326 const IDENTIFIER: Identifier = Identifier::SET_OF;
327}
328
329impl<T: AsnType, const N: usize> AsnType for [T; N] {
330 const TAG: Tag = Tag::SEQUENCE;
331 const CONSTRAINTS: Constraints = constraints!(size_constraint!(N));
332 const IDENTIFIER: Identifier = Identifier::SEQUENCE_OF;
333}
334
335impl<T> AsnType for &'_ [T] {
336 const TAG: Tag = Tag::SEQUENCE;
337 const IDENTIFIER: Identifier = Identifier::SEQUENCE_OF;
338}
339
340impl AsnType for Any {
341 const TAG: Tag = Tag::EOC;
342 const TAG_TREE: TagTree = TagTree::Choice(&[]);
343}
344
345#[cfg(feature = "f32")]
346impl AsnType for f32 {
347 const TAG: Tag = Tag::REAL;
348 const IDENTIFIER: Identifier = Identifier::REAL;
349}
350
351#[cfg(feature = "f64")]
352impl AsnType for f64 {
353 const TAG: Tag = Tag::REAL;
354 const IDENTIFIER: Identifier = Identifier::REAL;
355}
356
357impl<T> AsnType for core::marker::PhantomData<T> {
358 const TAG: Tag = Tag::NULL;
359 const TAG_TREE: TagTree = TagTree::Leaf(Tag::NULL);
360}