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