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