1mod any;
7mod instance;
8mod open;
9mod prefix;
10mod tag;
11
12pub mod constraints;
13pub mod fields;
14pub mod variants;
15
16pub(crate) mod oid;
17pub(crate) mod strings;
18
19use alloc::boxed::Box;
20use num_bigint::BigUint;
21
22pub use {
23 self::{
24 any::Any,
25 constraints::{Constraint, Constraints, Extensible},
26 instance::InstanceOf,
27 oid::{ObjectIdentifier, Oid},
28 open::Open,
29 prefix::{Explicit, Implicit},
30 strings::{
31 BitStr, BitString, BmpString, FixedBitString, FixedOctetString, GeneralString,
32 Ia5String, NumericString, OctetString, PrintableString, TeletexString, Utf8String,
33 VisibleString,
34 },
35 tag::{Class, Tag, TagTree},
36 },
37 num_bigint::BigInt as Integer,
38 rasn_derive::AsnType,
39};
40
41pub type SetOf<T> = alloc::collections::BTreeSet<T>;
43pub type UniversalString = Implicit<tag::UNIVERSAL_STRING, Utf8String>;
45pub type UtcTime = chrono::DateTime<chrono::Utc>;
47pub type GeneralizedTime = chrono::DateTime<chrono::FixedOffset>;
49pub type SequenceOf<T> = alloc::vec::Vec<T>;
74
75pub trait AsnType {
77 const TAG: Tag;
83 const TAG_TREE: TagTree = TagTree::Leaf(Self::TAG);
86
87 const CONSTRAINTS: Constraints<'static> = Constraints::NONE;
88
89 const IDENTIFIER: Option<&'static str> = None;
92}
93
94pub trait Constructed {
96 const FIELDS: self::fields::Fields;
98 const EXTENDED_FIELDS: Option<self::fields::Fields> = None;
100}
101
102pub trait Choice: Sized {
104 const VARIANTS: &'static [TagTree];
106 const EXTENDED_VARIANTS: Option<&'static [TagTree]> = None;
108 const IDENTIFIERS: &'static [&'static str];
110}
111
112pub trait DecodeChoice: Choice + crate::Decode {
114 fn from_tag<D: crate::Decoder>(decoder: &mut D, tag: Tag) -> Result<Self, D::Error>;
116}
117
118pub trait Enumerated: Sized + 'static + PartialEq + Copy + core::fmt::Debug {
120 const VARIANTS: &'static [Self];
122 const EXTENDED_VARIANTS: Option<&'static [Self]>;
124
125 const DISCRIMINANTS: &'static [(Self, isize)];
127 const EXTENDED_DISCRIMINANTS: Option<&'static [(Self, isize)]>;
130
131 const IDENTIFIERS: &'static [&'static str];
133
134 fn variance() -> usize {
136 Self::VARIANTS.len()
137 }
138
139 fn extended_variance() -> usize {
141 Self::EXTENDED_VARIANTS.map_or(0, |array| array.len())
142 }
143
144 fn complete_variance() -> usize {
146 Self::variance() + Self::extended_variance()
147 }
148
149 fn is_extended_variant(&self) -> bool {
151 Self::EXTENDED_VARIANTS.map_or(false, |array| array.iter().any(|variant| variant == self))
152 }
153
154 fn enumeration_index(&self) -> usize {
157 if self.is_extended_variant() {
158 Self::EXTENDED_VARIANTS
159 .unwrap()
160 .iter()
161 .position(|lhs| lhs == self)
162 .unwrap()
163 } else {
164 Self::VARIANTS
165 .iter()
166 .position(|lhs| lhs == self)
167 .expect("Variant not defined in Enumerated::VARIANTS")
168 }
169 }
170
171 fn discriminant(&self) -> isize {
173 Self::DISCRIMINANTS
174 .iter()
175 .chain(
176 Self::EXTENDED_DISCRIMINANTS
177 .iter()
178 .flat_map(|array| array.iter()),
179 )
180 .find_map(|(lhs, value)| (lhs == self).then_some(*value))
181 .expect("variant not defined in `Enumerated`")
182 }
183
184 fn from_discriminant(value: isize) -> Option<Self> {
186 Self::DISCRIMINANTS
187 .iter()
188 .chain(
189 Self::EXTENDED_DISCRIMINANTS
190 .iter()
191 .flat_map(|array| array.iter()),
192 )
193 .find_map(|(variant, discriminant)| (value == *discriminant).then_some(*variant))
194 }
195
196 fn from_enumeration_index(index: usize) -> Option<Self> {
198 Self::VARIANTS.get(index).copied()
199 }
200
201 fn from_extended_enumeration_index(index: usize) -> Option<Self> {
203 Self::EXTENDED_VARIANTS.and_then(|array| array.get(index).copied())
204 }
205
206 fn identifier(&self) -> &'static str {
208 let index = if self.is_extended_variant() {
209 Self::EXTENDED_VARIANTS
210 .unwrap()
211 .iter()
212 .position(|lhs| lhs == self)
213 .unwrap()
214 + Self::VARIANTS.len()
215 } else {
216 Self::VARIANTS
217 .iter()
218 .position(|lhs| lhs == self)
219 .expect("Variant not defined in Enumerated::VARIANTS")
220 };
221 Self::IDENTIFIERS[index]
222 }
223
224 fn from_identifier(identifier: &str) -> Option<Self> {
226 Self::IDENTIFIERS
227 .iter()
228 .enumerate()
229 .find(|id| id.1.eq(&identifier))
230 .and_then(|(i, _)| {
231 if i < Self::VARIANTS.len() {
232 Self::VARIANTS.get(i).copied()
233 } else {
234 Self::EXTENDED_VARIANTS
235 .and_then(|array| array.get(i - Self::VARIANTS.len()).copied())
236 }
237 })
238 }
239}
240
241#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
243pub struct ConstrainedInteger<const START: i128, const END: i128>(pub(crate) Integer);
244
245impl<const START: i128, const END: i128> AsnType for ConstrainedInteger<START, END> {
246 const TAG: Tag = Tag::INTEGER;
247 const CONSTRAINTS: Constraints<'static> =
248 Constraints::new(&[constraints::Constraint::Value(Extensible::new(
249 constraints::Value::new(constraints::Bounded::const_new(START, END)),
250 ))]);
251}
252
253impl<const START: i128, const END: i128> core::ops::Deref for ConstrainedInteger<START, END> {
254 type Target = Integer;
255
256 fn deref(&self) -> &Self::Target {
257 &self.0
258 }
259}
260
261impl<T: Into<Integer>, const START: i128, const END: i128> From<T>
262 for ConstrainedInteger<START, END>
263{
264 fn from(value: T) -> Self {
265 Self(value.into())
266 }
267}
268
269macro_rules! asn_type {
270 ($($name:ty: $value:ident),+) => {
271 $(
272 impl AsnType for $name {
273 const TAG: Tag = Tag::$value;
274 }
275 )+
276 }
277}
278
279asn_type! {
280 bool: BOOL,
281 Integer: INTEGER,
282 OctetString: OCTET_STRING,
283 ObjectIdentifier: OBJECT_IDENTIFIER,
284 Oid: OBJECT_IDENTIFIER,
285 Utf8String: UTF8_STRING,
286 UtcTime: UTC_TIME,
287 GeneralizedTime: GENERALIZED_TIME,
288 (): NULL,
289 &'_ str: UTF8_STRING
290
291}
292
293macro_rules! asn_integer_type {
294 ($($int:ty),+ $(,)?) => {
295 $(
296 impl AsnType for $int {
297 const TAG: Tag = Tag::INTEGER;
298 const CONSTRAINTS: Constraints<'static> = Constraints::new(&[
299 constraints::Constraint::Value(Extensible::new(constraints::Value::new(constraints::Bounded::const_new(<$int>::MIN as i128, <$int>::MAX as i128)))),
300 ]);
301 }
302 )+
303 }
304}
305
306asn_integer_type! {
307 i8,
308 i16,
309 i32,
310 i64,
311 i128,
312 isize,
313 u8,
314 u16,
315 u32,
316 u64,
317 u128,
318 usize,
319}
320
321pub trait IntegerType:
322 Sized
323 + Clone
324 + core::fmt::Debug
325 + TryFrom<i64>
326 + TryFrom<i128>
327 + TryInto<i128>
328 + Into<Integer>
329 + num_traits::Num
330 + num_traits::CheckedAdd
331{
332 const WIDTH: u32;
333
334 fn try_from_bytes(input: &[u8], codec: crate::Codec)
335 -> Result<Self, crate::error::DecodeError>;
336
337 fn try_from_signed_bytes(
338 input: &[u8],
339 codec: crate::Codec,
340 ) -> Result<Self, crate::error::DecodeError>;
341
342 fn try_from_unsigned_bytes(
343 input: &[u8],
344 codec: crate::Codec,
345 ) -> Result<Self, crate::error::DecodeError>;
346
347 #[doc(hidden)]
349 fn wrapping_add(self, other: Self) -> Self;
350}
351
352macro_rules! integer_type_decode {
353 ((signed $t1:ty, $t2:ty), $($ts:tt)*) => {
354 impl IntegerType for $t1 {
355 const WIDTH: u32 = <$t1>::BITS;
356
357 fn try_from_bytes(
358 input: &[u8],
359 codec: crate::Codec,
360 ) -> Result<Self, crate::error::DecodeError> {
361 Self::try_from_signed_bytes(input, codec)
362 }
363
364 fn try_from_signed_bytes(
365 input: &[u8],
366 codec: crate::Codec,
367 ) -> Result<Self, crate::error::DecodeError> {
368 const BYTE_SIZE: usize = (<$t1>::BITS / 8) as usize;
369 if input.is_empty() {
370 return Err(crate::error::DecodeError::unexpected_empty_input(codec));
371 }
372
373 let leading_byte = if input[0] & 0x80 == 0x80 { 0xFF } else { 0x00 };
377 let input_iter = input.iter().copied().skip_while(|n| *n == leading_byte);
378 let data_length = input_iter.clone().count();
379
380 if data_length > BYTE_SIZE {
383 return Err(crate::error::DecodeError::integer_overflow(<$t1>::BITS, codec));
384 }
385
386 let mut bytes = [leading_byte; BYTE_SIZE];
387 let start = bytes.len() - data_length;
388
389 for (b, d) in bytes[start..].iter_mut().zip(input_iter) {
390 *b = d;
391 }
392
393 Ok(Self::from_be_bytes(bytes))
394 }
395
396 fn try_from_unsigned_bytes(
397 input: &[u8],
398 codec: crate::Codec,
399 ) -> Result<Self, crate::error::DecodeError> {
400 Ok(<$t2>::try_from_bytes(input, codec)? as $t1)
401 }
402
403 fn wrapping_add(self, other: Self) -> Self {
404 self.wrapping_add(other)
405 }
406 }
407
408 integer_type_decode!($($ts)*);
409 };
410 ((unsigned $t1:ty, $t2:ty), $($ts:tt)*) => {
411 impl IntegerType for $t1 {
412 const WIDTH: u32 = <$t1>::BITS;
413
414 fn try_from_bytes(
415 input: &[u8],
416 codec: crate::Codec,
417 ) -> Result<Self, crate::error::DecodeError> {
418 Self::try_from_unsigned_bytes(input, codec)
419 }
420
421 fn try_from_signed_bytes(
422 input: &[u8],
423 codec: crate::Codec,
424 ) -> Result<Self, crate::error::DecodeError> {
425 Ok(<$t2>::try_from_bytes(input, codec)? as $t1)
426 }
427
428 fn try_from_unsigned_bytes(
429 input: &[u8],
430 codec: crate::Codec,
431 ) -> Result<Self, crate::error::DecodeError> {
432 const BYTE_SIZE: usize = (<$t1>::BITS / 8) as usize;
433 if input.is_empty() {
434 return Err(crate::error::DecodeError::unexpected_empty_input(codec));
435 }
436
437 let input_iter = input.iter().copied().skip_while(|n| *n == 0x00);
438 let data_length = input_iter.clone().count();
439
440 if data_length > BYTE_SIZE {
441 return Err(crate::error::DecodeError::integer_overflow(<$t1>::BITS, codec));
442 }
443
444 let mut bytes = [0x00; BYTE_SIZE];
445 let start = bytes.len() - data_length;
446
447 for (b, d) in bytes[start..].iter_mut().zip(input_iter) {
448 *b = d;
449 }
450
451
452 Ok(Self::from_be_bytes(bytes))
453 }
454
455 fn wrapping_add(self, other: Self) -> Self {
456 self.wrapping_add(other)
457 }
458 }
459
460 integer_type_decode!($($ts)*);
461 };
462 (,) => {};
463 () => {};
464}
465
466integer_type_decode!(
467 (unsigned u8, i8),
468 (signed i8, u8),
469 (unsigned u16, i16),
470 (signed i16, u16),
471 (unsigned u32, i32),
472 (signed i32, u32),
473 (unsigned u64, i64),
474 (signed i64, u64),
475 (unsigned u128, i128),
476 (signed i128, u128),
477 (unsigned usize, isize),
478 (signed isize, usize),
479);
480
481impl IntegerType for Integer {
482 const WIDTH: u32 = u32::MAX;
483
484 fn try_from_bytes(
485 input: &[u8],
486 codec: crate::Codec,
487 ) -> Result<Self, crate::error::DecodeError> {
488 if input.is_empty() {
489 return Err(crate::error::DecodeError::unexpected_empty_input(codec));
490 }
491
492 Ok(Integer::from_signed_bytes_be(input))
493 }
494
495 fn try_from_signed_bytes(
496 input: &[u8],
497 codec: crate::Codec,
498 ) -> Result<Self, crate::error::DecodeError> {
499 Self::try_from_bytes(input, codec)
500 }
501
502 fn try_from_unsigned_bytes(
503 input: &[u8],
504 codec: crate::Codec,
505 ) -> Result<Self, crate::error::DecodeError> {
506 if input.is_empty() {
507 return Err(crate::error::DecodeError::unexpected_empty_input(codec));
508 }
509
510 Ok(BigUint::from_bytes_be(input).into())
511 }
512
513 fn wrapping_add(self, other: Self) -> Self {
514 self + other
515 }
516}
517
518impl AsnType for str {
519 const TAG: Tag = Tag::UTF8_STRING;
520}
521
522impl<T: AsnType> AsnType for &'_ T {
523 const TAG: Tag = T::TAG;
524 const TAG_TREE: TagTree = T::TAG_TREE;
525}
526
527impl<T: AsnType> AsnType for Box<T> {
528 const TAG: Tag = T::TAG;
529 const TAG_TREE: TagTree = T::TAG_TREE;
530}
531
532impl<T: AsnType> AsnType for alloc::vec::Vec<T> {
533 const TAG: Tag = Tag::SEQUENCE;
534}
535
536impl<T: AsnType> AsnType for Option<T> {
537 const TAG: Tag = T::TAG;
538 const TAG_TREE: TagTree = T::TAG_TREE;
539}
540
541impl<T> AsnType for alloc::collections::BTreeSet<T> {
542 const TAG: Tag = Tag::SET;
543}
544
545impl<T: AsnType, const N: usize> AsnType for [T; N] {
546 const TAG: Tag = Tag::SEQUENCE;
547 const CONSTRAINTS: Constraints<'static> =
548 Constraints::new(&[Constraint::Size(Extensible::new(constraints::Size::new(
549 constraints::Bounded::single_value(N),
550 )))]);
551}
552
553impl<T> AsnType for &'_ [T] {
554 const TAG: Tag = Tag::SEQUENCE;
555}
556
557impl AsnType for Any {
558 const TAG: Tag = Tag::EOC;
559 const TAG_TREE: TagTree = TagTree::Choice(&[]);
560}