1pub mod constraints;
10pub mod encoding_rules;
11pub mod error;
12pub mod information_object;
13pub mod macros;
14pub mod parameterization;
15pub mod types;
16pub mod utils;
17
18use std::{borrow::Cow, cell::RefCell, collections::BTreeMap, ops::Add, rc::Rc};
19
20use crate::common::INTERNAL_IO_FIELD_REF_TYPE_NAME_PREFIX;
21use constraints::Constraint;
22use error::{GrammarError, GrammarErrorType};
23use information_object::{
24 ObjectClassAssignment, ObjectClassFieldType, ToplevelInformationDefinition,
25};
26#[cfg(test)]
27use internal_macros::EnumDebug;
28use macros::ToplevelMacroDefinition;
29use parameterization::Parameterization;
30use quote::{quote, ToTokens, TokenStreamExt};
31use types::*;
32
33#[cfg(doc)]
34use crate::Backend;
35
36pub const BLOCK_COMMENT_START: &str = "/*";
38pub const BLOCK_COMMENT_END: &str = "*/";
39pub const LINE_COMMENT: &str = "--";
40
41pub const LEFT_PARENTHESIS: char = '(';
43pub const RIGHT_PARENTHESIS: char = ')';
44pub const LEFT_BRACKET: char = '[';
45pub const RIGHT_BRACKET: char = ']';
46pub const LEFT_BRACE: char = '{';
47pub const RIGHT_BRACE: char = '}';
48pub const LEFT_CHEVRON: char = '<';
49pub const RIGHT_CHEVRON: char = '>';
50
51pub const NULL: &str = "NULL";
53pub const BOOLEAN: &str = "BOOLEAN";
54pub const INTEGER: &str = "INTEGER";
55pub const REAL: &str = "REAL";
56pub const BIT_STRING: &str = "BIT STRING";
57pub const OCTET_STRING: &str = "OCTET STRING";
58pub const IA5_STRING: &str = "IA5String";
59pub const UTF8_STRING: &str = "UTF8String";
60pub const NUMERIC_STRING: &str = "NumericString";
61pub const VISIBLE_STRING: &str = "VisibleString";
62pub const TELETEX_STRING: &str = "TeletexString";
63pub const T61_STRING: &str = "T61String";
64pub const VIDEOTEX_STRING: &str = "VideotexString";
65pub const GRAPHIC_STRING: &str = "GraphicString";
66pub const GENERAL_STRING: &str = "GeneralString";
67pub const UNIVERSAL_STRING: &str = "UniversalString";
68pub const BMP_STRING: &str = "BMPString";
69pub const PRINTABLE_STRING: &str = "PrintableString";
70pub const GENERALIZED_TIME: &str = "GeneralizedTime";
71pub const UTC_TIME: &str = "UTCTime";
72pub const ENUMERATED: &str = "ENUMERATED";
73pub const CHOICE: &str = "CHOICE";
74pub const SEQUENCE: &str = "SEQUENCE";
75pub const SEQUENCE_OF: &str = "SEQUENCE OF";
76pub const SET_OF: &str = "SET OF";
77pub const OF: &str = "OF";
78pub const ALL: &str = "ALL";
79pub const SET: &str = "SET";
80pub const OBJECT_IDENTIFIER: &str = "OBJECT IDENTIFIER";
81pub const COMPONENTS_OF: &str = "COMPONENTS OF";
82pub const ANY: &str = "ANY";
83pub const DEFINED: &str = "DEFINED";
84pub const BY: &str = "BY";
85
86pub const UNIVERSAL: &str = "UNIVERSAL";
88pub const PRIVATE: &str = "PRIVATE";
89pub const APPLICATION: &str = "APPLICATION";
90
91pub const TRUE: &str = "TRUE";
93pub const FALSE: &str = "FALSE";
94
95pub const BEGIN: &str = "BEGIN";
97pub const END: &str = "END";
98pub const DEFINITIONS: &str = "DEFINITIONS";
99pub const AUTOMATIC: &str = "AUTOMATIC";
100pub const EXPLICIT: &str = "EXPLICIT";
101pub const IMPLICIT: &str = "IMPLICIT";
102pub const IMPORTS: &str = "IMPORTS";
103pub const EXPORTS: &str = "EXPORTS";
104pub const FROM: &str = "FROM";
105pub const INSTRUCTIONS: &str = "INSTRUCTIONS";
106pub const TAGS: &str = "TAGS";
107pub const EXTENSIBILITY_IMPLIED: &str = "EXTENSIBILITY IMPLIED";
108pub const WITH_SUCCESSORS: &str = "WITH SUCCESSORS";
109pub const WITH_DESCENDANTS: &str = "WITH DESCENDANTS";
110pub const SEMICOLON: char = ';';
111
112pub const AMPERSAND: char = '&';
114pub const CLASS: &str = "CLASS";
115pub const UNIQUE: &str = "UNIQUE";
116pub const WITH_SYNTAX: &str = "WITH SYNTAX";
117pub const AT: char = '@';
118pub const DOT: char = '.';
119
120pub const SIZE: &str = "SIZE";
122pub const CONSTRAINED_BY: &str = "CONSTRAINED BY";
123pub const PATTERN: &str = "PATTERN";
124pub const DEFAULT: &str = "DEFAULT";
125pub const CONTAINING: &str = "CONTAINING";
126pub const ENCODED_BY: &str = "ENCODED BY";
127pub const OPTIONAL: &str = "OPTIONAL";
128pub const WITH_COMPONENTS: &str = "WITH COMPONENTS";
129pub const WITH_COMPONENT: &str = "WITH COMPONENT";
130pub const UNION: &str = "UNION";
131pub const EXCEPT: &str = "EXCEPT";
132pub const INTERSECTION: &str = "INTERSECTION";
133pub const ABSENT: &str = "ABSENT";
134pub const PRESENT: &str = "PRESENT";
135pub const INCLUDES: &str = "INCLUDES";
136pub const MIN: &str = "MIN";
137pub const MAX: &str = "MAX";
138pub const LESS_THAN: char = '<';
139pub const GREATER_THAN: char = '>';
140pub const PIPE: &str = "|";
141pub const CARET: &str = "^";
142
143pub const MACRO: &str = "MACRO";
145
146pub const ASSIGN: &str = "::=";
147pub const RANGE: &str = "..";
148pub const ELLIPSIS: &str = "...";
149pub const COMMA: char = ',';
150pub const COLON: char = ':';
151pub const SINGLE_QUOTE: char = '\'';
152
153pub const ABSTRACT_SYNTAX: &str = "ABSTRACT-SYNTAX";
155pub const BIT: &str = "BIT";
156pub const CHARACTER: &str = "CHARACTER";
157pub const DATE: &str = "DATE";
158pub const DATE_TIME: &str = "DATE-TIME";
159pub const DURATION: &str = "DURATION";
160pub const EMBEDDED_PDV: &str = "EMBEDDED PDV";
161pub const EXTERNAL: &str = "EXTERNAL";
162pub const INSTANCE_OF: &str = "INSTANCE OF";
163pub const MINUS_INFINITY: &str = "MINUS-INFINITY";
164pub const NOT_A_NUMBER: &str = "NOT-A-NUMBER";
165pub const OBJECT: &str = "OBJECT";
166pub const OCTET: &str = "OCTET";
167pub const OID_IRI: &str = "OID-IRI";
168pub const PLUS_INFINITY: &str = "PLUS-INFINITY";
169pub const RELATIVE_OID: &str = "RELATIVE-OID";
170pub const RELATIVE_OID_IRI: &str = "RELATIVE-OID-IRI";
171pub const TIME: &str = "TIME";
172pub const TIME_OF_DAY: &str = "TIME-OF-DAY";
173pub const TYPE_IDENTIFIER: &str = "TYPE-IDENTIFIER";
174pub const ENCODING_CONTROL: &str = "ENCODING-CONTROL";
175
176pub const ASN1_KEYWORDS: [&str; 67] = [
177 ABSTRACT_SYNTAX,
178 BIT,
179 CHARACTER,
180 CONTAINING,
181 DATE,
182 DATE_TIME,
183 DURATION,
184 EMBEDDED_PDV,
185 EXTERNAL,
186 INSTANCE_OF,
187 MINUS_INFINITY,
188 NOT_A_NUMBER,
189 OBJECT,
190 OCTET,
191 OID_IRI,
192 PLUS_INFINITY,
193 RELATIVE_OID,
194 RELATIVE_OID_IRI,
195 TIME,
196 TIME_OF_DAY,
197 TYPE_IDENTIFIER,
198 SIZE,
199 DEFAULT,
200 OPTIONAL,
201 WITH_COMPONENTS,
202 WITH_COMPONENT,
203 UNION,
204 EXCEPT,
205 INTERSECTION,
206 ABSENT,
207 PRESENT,
208 INCLUDES,
209 MIN,
210 MAX,
211 CLASS,
212 UNIQUE,
213 WITH_SYNTAX,
214 NULL,
215 BOOLEAN,
216 INTEGER,
217 REAL,
218 ENUMERATED,
219 CHOICE,
220 SEQUENCE,
221 OF,
222 ALL,
223 SET,
224 OBJECT_IDENTIFIER,
225 UNIVERSAL,
226 PRIVATE,
227 APPLICATION,
228 TRUE,
229 FALSE,
230 BEGIN,
231 END,
232 DEFINITIONS,
233 AUTOMATIC,
234 EXPLICIT,
235 IMPLICIT,
236 IMPORTS,
237 FROM,
238 INSTRUCTIONS,
239 TAGS,
240 MACRO,
241 ANY,
242 BY,
243 DEFINED,
244];
245
246macro_rules! grammar_error {
247 ($kind:ident, $($arg:tt)*) => {
248 GrammarError::new(&format!($($arg)*),GrammarErrorType::$kind)
249 };
250}
251
252#[derive(Debug, Clone, PartialEq)]
253pub struct EncodingReferenceDefault(pub String);
254
255impl From<&str> for EncodingReferenceDefault {
256 fn from(value: &str) -> Self {
257 Self(value.into())
258 }
259}
260
261#[cfg_attr(test, derive(EnumDebug))]
262#[cfg_attr(not(test), derive(Debug))]
263#[derive(Clone, Copy, PartialEq, Default)]
264pub enum TaggingEnvironment {
265 Automatic,
266 #[default]
267 Implicit,
268 Explicit,
269}
270
271impl Add<&TaggingEnvironment> for &TaggingEnvironment {
272 type Output = TaggingEnvironment;
273
274 fn add(self, rhs: &TaggingEnvironment) -> Self::Output {
275 match (self, rhs) {
276 (t, TaggingEnvironment::Automatic) => *t,
277 (_, t) => *t,
278 }
279 }
280}
281
282#[cfg_attr(test, derive(EnumDebug))]
285#[cfg_attr(not(test), derive(Debug))]
286#[derive(Clone, Copy, PartialEq, Default)]
287pub enum ExtensibilityEnvironment {
288 Implied,
289 #[default]
290 Explicit,
291}
292
293#[cfg_attr(test, derive(EnumDebug))]
296#[cfg_attr(not(test), derive(Debug))]
297#[derive(Clone, PartialEq)]
298pub enum With {
299 Successors,
300 Descendants,
301}
302
303#[derive(Debug, Clone, PartialEq)]
306pub struct ExternalValueReference {
307 pub module_reference: String,
308 pub value_reference: String,
309}
310
311#[derive(Debug, Clone, PartialEq)]
314pub struct GlobalModuleReference {
315 pub module_reference: String,
316 pub assigned_identifier: AssignedIdentifier,
317}
318
319impl From<(&str, AssignedIdentifier)> for GlobalModuleReference {
320 fn from(value: (&str, AssignedIdentifier)) -> Self {
321 Self {
322 module_reference: value.0.to_owned(),
323 assigned_identifier: value.1,
324 }
325 }
326}
327
328#[cfg_attr(test, derive(EnumDebug))]
331#[cfg_attr(not(test), derive(Debug))]
332#[derive(Clone, PartialEq)]
333pub enum AssignedIdentifier {
334 ObjectIdentifierValue(ObjectIdentifierValue),
335 ExternalValueReference(ExternalValueReference),
336 ValueReference(String),
337 ParameterizedValue {
338 value_reference: String,
339 actual_parameter_list: String,
340 },
341 Empty,
342}
343
344#[derive(Debug, Clone, PartialEq)]
347pub struct Import {
348 pub types: Vec<String>,
349 pub global_module_reference: GlobalModuleReference,
350 pub with: Option<With>,
351}
352
353impl From<(Vec<&str>, (GlobalModuleReference, Option<&str>))> for Import {
354 fn from(value: (Vec<&str>, (GlobalModuleReference, Option<&str>))) -> Self {
355 Self {
356 types: value.0.into_iter().map(String::from).collect(),
357 global_module_reference: value.1 .0,
358 with: value.1 .1.map(|with| {
359 if with == WITH_SUCCESSORS {
360 With::Successors
361 } else {
362 With::Descendants
363 }
364 }),
365 }
366 }
367}
368
369#[cfg_attr(test, derive(EnumDebug))]
372#[cfg_attr(not(test), derive(Debug))]
373#[derive(Clone, PartialEq)]
374pub enum Exports {
375 Identifier(Vec<String>),
376 All,
377}
378
379impl From<Vec<&str>> for Exports {
380 fn from(value: Vec<&str>) -> Self {
381 Self::Identifier(value.iter().map(ToString::to_string).collect())
382 }
383}
384
385#[cfg_attr(test, derive(EnumDebug))]
388#[cfg_attr(not(test), derive(Debug))]
389#[derive(Clone, PartialEq)]
390pub enum DefinitiveIdentifier {
391 DefinitiveOID(ObjectIdentifierValue),
392 DefinitiveOIDandIRI {
393 oid: ObjectIdentifierValue,
394 iri: String,
395 },
396}
397
398impl From<(ObjectIdentifierValue, Option<&str>)> for DefinitiveIdentifier {
399 fn from(value: (ObjectIdentifierValue, Option<&str>)) -> Self {
400 if let Some(iri_value) = value.1 {
401 Self::DefinitiveOIDandIRI {
402 oid: value.0,
403 iri: iri_value.to_owned(),
404 }
405 } else {
406 Self::DefinitiveOID(value.0)
407 }
408 }
409}
410
411#[derive(Debug, Clone, PartialEq)]
414pub struct ModuleHeader {
415 pub name: String,
416 pub module_identifier: Option<DefinitiveIdentifier>,
417 pub encoding_reference_default: Option<EncodingReferenceDefault>,
418 pub tagging_environment: TaggingEnvironment,
419 pub extensibility_environment: ExtensibilityEnvironment,
420 pub imports: Vec<Import>,
421 pub exports: Option<Exports>,
422}
423
424impl ModuleHeader {
425 pub fn find_import(&self, identifier: &str) -> Option<&String> {
427 self.imports
428 .iter()
429 .find_map(|i| i.types.iter().find(|id| *id == identifier))
430 }
431}
432
433impl
434 From<(
435 &str,
436 Option<DefinitiveIdentifier>,
437 Option<(
438 Option<EncodingReferenceDefault>,
439 TaggingEnvironment,
440 ExtensibilityEnvironment,
441 )>,
442 Option<Exports>,
443 Option<Vec<Import>>,
444 )> for ModuleHeader
445{
446 fn from(
447 value: (
448 &str,
449 Option<DefinitiveIdentifier>,
450 Option<(
451 Option<EncodingReferenceDefault>,
452 TaggingEnvironment,
453 ExtensibilityEnvironment,
454 )>,
455 Option<Exports>,
456 Option<Vec<Import>>,
457 ),
458 ) -> Self {
459 let (encoding_reference_default, tagging_environment, extensibility_environment) =
460 value.2.unwrap_or((
461 None,
462 TaggingEnvironment::Explicit,
463 ExtensibilityEnvironment::Explicit,
464 ));
465 Self {
466 name: value.0.into(),
467 module_identifier: value.1,
468 encoding_reference_default,
469 tagging_environment,
470 extensibility_environment,
471 exports: value.3,
472 imports: value.4.unwrap_or_default(),
473 }
474 }
475}
476
477#[derive(Debug, Clone, PartialEq)]
480pub struct ObjectIdentifierValue(pub Vec<ObjectIdentifierArc>);
481
482impl From<Vec<ObjectIdentifierArc>> for ObjectIdentifierValue {
483 fn from(value: Vec<ObjectIdentifierArc>) -> Self {
484 Self(value)
485 }
486}
487
488#[derive(Debug, Clone, PartialEq)]
491pub struct ObjectIdentifierArc {
492 pub name: Option<String>,
493 pub number: Option<u128>,
494}
495
496impl ObjectIdentifierArc {
497 const ITU_T: u128 = 0;
498 const ISO: u128 = 1;
499 const JOINT_ISO_ITU_T: u128 = 2;
500 const JOINT_ISO_CCITT: u128 = 2;
501 const RECOMMENDATION: u128 = 0;
502 const QUESTION: u128 = 1;
503 const ADMINISTRATION: u128 = 2;
504 const NETWORK_OPERATOR: u128 = 3;
505 const ITU_T_IDENTIFIED_ORGANIZATION: u128 = 4;
506 const R_RECOMMENDATION: u128 = 5;
507 const STANDARD: u128 = 0;
508 const REGISTRATION_AUTHORITY: u128 = 1;
509 const MEMBER_BODY: u128 = 2;
510 const ISO_IDENTIFIED_ORGANIZATION: u128 = 3;
511
512 pub(crate) fn well_known(name: Option<&String>, root: Option<u8>) -> Option<u128> {
513 match (root, name.map(|s| s.as_str())) {
514 (_, Some("itu-t")) => Some(Self::ITU_T),
515 (_, Some("iso")) => Some(Self::ISO),
516 (_, Some("joint-iso-itu-t")) => Some(Self::JOINT_ISO_ITU_T),
517 (_, Some("joint-iso-ccitt")) => Some(Self::JOINT_ISO_CCITT),
518 (Some(0), Some("recommendation")) => Some(Self::RECOMMENDATION),
519 (Some(0), Some("question")) => Some(Self::QUESTION),
520 (Some(0), Some("administration")) => Some(Self::ADMINISTRATION),
521 (Some(0), Some("network-operator")) => Some(Self::NETWORK_OPERATOR),
522 (Some(0), Some("identified-organization")) => Some(Self::ITU_T_IDENTIFIED_ORGANIZATION),
523 (Some(0), Some("r-recommendation")) => Some(Self::R_RECOMMENDATION),
524 (Some(1), Some("standard")) => Some(Self::STANDARD),
525 (Some(1), Some("registration-authority")) => Some(Self::REGISTRATION_AUTHORITY),
526 (Some(1), Some("member-body")) => Some(Self::MEMBER_BODY),
527 (Some(1), Some("identified-organization")) => Some(Self::ISO_IDENTIFIED_ORGANIZATION),
528 _ => None,
529 }
530 }
531}
532
533impl From<u128> for ObjectIdentifierArc {
534 fn from(value: u128) -> Self {
535 Self {
536 name: None,
537 number: Some(value),
538 }
539 }
540}
541
542impl From<&str> for ObjectIdentifierArc {
543 fn from(value: &str) -> Self {
544 Self {
545 name: Some(value.into()),
546 number: None,
547 }
548 }
549}
550
551impl From<(&str, u128)> for ObjectIdentifierArc {
552 fn from(value: (&str, u128)) -> Self {
553 Self {
554 name: Some(value.0.into()),
555 number: Some(value.1),
556 }
557 }
558}
559
560#[cfg_attr(test, derive(EnumDebug))]
566#[cfg_attr(not(test), derive(Debug))]
567#[derive(Clone, PartialEq)]
568pub enum ToplevelDefinition {
569 Type(ToplevelTypeDefinition),
571 Value(ToplevelValueDefinition),
573 Class(ObjectClassAssignment),
575 Object(ToplevelInformationDefinition),
577 Macro(ToplevelMacroDefinition),
579}
580
581impl ToplevelDefinition {
582 pub(crate) fn has_enum_value(&self, type_name: Option<&String>, identifier: &String) -> bool {
583 if let ToplevelDefinition::Type(ToplevelTypeDefinition {
584 name,
585 ty: ASN1Type::Enumerated(e),
586 ..
587 }) = self
588 {
589 if type_name.is_some() && Some(name) != type_name {
590 return false;
591 }
592 e.members.iter().any(|m| &m.name == identifier)
593 } else {
594 false
595 }
596 }
597
598 pub(crate) fn set_module_header(&mut self, module_header: Rc<RefCell<ModuleHeader>>) {
599 match self {
600 ToplevelDefinition::Type(ref mut t) => {
601 t.module_header = Some(module_header);
602 }
603 ToplevelDefinition::Value(ref mut v) => {
604 v.module_header = Some(module_header);
605 }
606 ToplevelDefinition::Class(ref mut c) => {
607 c.module_header = Some(module_header);
608 }
609 ToplevelDefinition::Object(ref mut o) => {
610 o.module_header = Some(module_header);
611 }
612 ToplevelDefinition::Macro(ref mut m) => {
613 m.module_header = Some(module_header);
614 }
615 }
616 }
617
618 pub(crate) fn get_module_header(&self) -> Option<Rc<RefCell<ModuleHeader>>> {
619 match self {
620 ToplevelDefinition::Type(ref t) => t.module_header.as_ref().cloned(),
621 ToplevelDefinition::Value(ref v) => v.module_header.as_ref().cloned(),
622 ToplevelDefinition::Class(ref c) => c.module_header.as_ref().cloned(),
623 ToplevelDefinition::Object(ref o) => o.module_header.as_ref().cloned(),
624 ToplevelDefinition::Macro(ref m) => m.module_header.as_ref().cloned(),
625 }
626 }
627
628 pub(crate) fn apply_tagging_environment(&mut self, environment: &TaggingEnvironment) {
629 if let (env, ToplevelDefinition::Type(ty)) = (environment, self) {
630 ty.tag = ty.tag.as_ref().map(|t| AsnTag {
631 environment: env + &t.environment,
632 tag_class: t.tag_class,
633 id: t.id,
634 });
635 match &mut ty.ty {
636 ASN1Type::Sequence(s) | ASN1Type::Set(s) => s.members.iter_mut().for_each(|m| {
637 m.tag = m.tag.as_ref().map(|t| AsnTag {
638 environment: env + &t.environment,
639 tag_class: t.tag_class,
640 id: t.id,
641 });
642 }),
643 ASN1Type::Choice(c) => c.options.iter_mut().for_each(|o| {
644 o.tag = o.tag.as_ref().map(|t| AsnTag {
645 environment: env + &t.environment,
646 tag_class: t.tag_class,
647 id: t.id,
648 });
649 }),
650 _ => (),
651 }
652 }
653 }
654
655 pub fn name(&self) -> &String {
677 match self {
678 ToplevelDefinition::Class(c) => &c.name,
679 ToplevelDefinition::Object(o) => &o.name,
680 ToplevelDefinition::Type(t) => &t.name,
681 ToplevelDefinition::Value(v) => &v.name,
682 ToplevelDefinition::Macro(v) => &v.name,
683 }
684 }
685}
686
687#[derive(Debug, Clone, PartialEq)]
690pub struct ToplevelValueDefinition {
691 pub comments: String,
692 pub name: String,
693 pub associated_type: ASN1Type,
694 pub parameterization: Option<Parameterization>,
695 pub value: ASN1Value,
696 pub module_header: Option<Rc<RefCell<ModuleHeader>>>,
697}
698
699impl From<(&str, ASN1Value, ASN1Type)> for ToplevelValueDefinition {
700 fn from(value: (&str, ASN1Value, ASN1Type)) -> Self {
701 Self {
702 comments: String::new(),
703 name: value.0.to_owned(),
704 associated_type: value.2.to_owned(),
705 parameterization: None,
706 value: value.1,
707 module_header: None,
708 }
709 }
710}
711
712impl
713 From<(
714 Vec<&str>,
715 &str,
716 Option<Parameterization>,
717 ASN1Type,
718 ASN1Value,
719 )> for ToplevelValueDefinition
720{
721 fn from(
722 value: (
723 Vec<&str>,
724 &str,
725 Option<Parameterization>,
726 ASN1Type,
727 ASN1Value,
728 ),
729 ) -> Self {
730 Self {
731 comments: value.0.join("\n"),
732 name: value.1.into(),
733 parameterization: value.2,
734 associated_type: value.3,
735 value: value.4,
736 module_header: None,
737 }
738 }
739}
740
741#[derive(Debug, Clone, PartialEq)]
742pub struct ToplevelTypeDefinition {
743 pub comments: String,
744 pub tag: Option<AsnTag>,
745 pub name: String,
746 pub ty: ASN1Type,
747 pub parameterization: Option<Parameterization>,
748 pub module_header: Option<Rc<RefCell<ModuleHeader>>>,
749}
750
751impl ToplevelTypeDefinition {
752 pub fn pdu(&self) -> &ASN1Type {
753 &self.ty
754 }
755}
756
757impl From<(&str, ASN1Type)> for ToplevelTypeDefinition {
758 fn from(value: (&str, ASN1Type)) -> Self {
759 Self {
760 comments: String::new(),
761 tag: None,
762 name: value.0.to_owned(),
763 ty: value.1,
764 parameterization: None,
765 module_header: None,
766 }
767 }
768}
769
770impl
771 From<(
772 Vec<&str>,
773 &str,
774 Option<Parameterization>,
775 (Option<AsnTag>, ASN1Type),
776 )> for ToplevelTypeDefinition
777{
778 fn from(
779 value: (
780 Vec<&str>,
781 &str,
782 Option<Parameterization>,
783 (Option<AsnTag>, ASN1Type),
784 ),
785 ) -> Self {
786 Self {
787 comments: value.0.join("\n"),
788 name: value.1.into(),
789 parameterization: value.2,
790 ty: value.3 .1,
791 tag: value.3 .0,
792 module_header: None,
793 }
794 }
795}
796
797#[cfg_attr(test, derive(EnumDebug))]
801#[cfg_attr(not(test), derive(Debug))]
802#[derive(Clone, PartialEq)]
803pub enum ASN1Type {
804 Null,
805 Boolean(Boolean),
806 Integer(Integer),
807 Real(Real),
808 BitString(BitString),
809 OctetString(OctetString),
810 CharacterString(CharacterString),
811 Enumerated(Enumerated),
812 Choice(Choice),
813 Sequence(SequenceOrSet),
814 SequenceOf(SequenceOrSetOf),
815 Set(SequenceOrSet),
816 SetOf(SequenceOrSetOf),
817 Time(Time),
818 GeneralizedTime(GeneralizedTime),
819 UTCTime(UTCTime),
820 Any,
821 ElsewhereDeclaredType(DeclarationElsewhere),
822 ChoiceSelectionType(ChoiceSelectionType),
823 ObjectIdentifier(ObjectIdentifier),
824 ObjectClassField(ObjectClassFieldType),
825 EmbeddedPdv,
826 External,
827}
828
829impl ASN1Type {
830 pub fn as_str(&self) -> Cow<'_, str> {
831 match self {
832 ASN1Type::Null => Cow::Borrowed(NULL),
833 ASN1Type::Boolean(_) => Cow::Borrowed(BOOLEAN),
834 ASN1Type::Integer(_) => Cow::Borrowed(INTEGER),
835 ASN1Type::Real(_) => Cow::Borrowed(REAL),
836 ASN1Type::BitString(_) => Cow::Borrowed(BIT_STRING),
837 ASN1Type::OctetString(_) => Cow::Borrowed(OCTET_STRING),
838 ASN1Type::CharacterString(CharacterString {
839 ty: CharacterStringType::BMPString,
840 ..
841 }) => Cow::Borrowed(BMP_STRING),
842 ASN1Type::CharacterString(CharacterString {
843 ty: CharacterStringType::UTF8String,
844 ..
845 }) => Cow::Borrowed(UTF8_STRING),
846 ASN1Type::CharacterString(CharacterString {
847 ty: CharacterStringType::PrintableString,
848 ..
849 }) => Cow::Borrowed(PRINTABLE_STRING),
850 ASN1Type::CharacterString(CharacterString {
851 ty: CharacterStringType::TeletexString,
852 ..
853 }) => Cow::Borrowed(TELETEX_STRING),
854 ASN1Type::CharacterString(CharacterString {
855 ty: CharacterStringType::IA5String,
856 ..
857 }) => Cow::Borrowed(IA5_STRING),
858 ASN1Type::CharacterString(CharacterString {
859 ty: CharacterStringType::UniversalString,
860 ..
861 }) => Cow::Borrowed(UNIVERSAL_STRING),
862 ASN1Type::CharacterString(CharacterString {
863 ty: CharacterStringType::VisibleString,
864 ..
865 }) => Cow::Borrowed(VISIBLE_STRING),
866 ASN1Type::CharacterString(CharacterString {
867 ty: CharacterStringType::GeneralString,
868 ..
869 }) => Cow::Borrowed(GENERAL_STRING),
870 ASN1Type::CharacterString(CharacterString {
871 ty: CharacterStringType::VideotexString,
872 ..
873 }) => Cow::Borrowed(VIDEOTEX_STRING),
874 ASN1Type::CharacterString(CharacterString {
875 ty: CharacterStringType::GraphicString,
876 ..
877 }) => Cow::Borrowed(GRAPHIC_STRING),
878 ASN1Type::CharacterString(CharacterString {
879 ty: CharacterStringType::NumericString,
880 ..
881 }) => Cow::Borrowed(NUMERIC_STRING),
882 ASN1Type::Enumerated(_) => Cow::Borrowed(ENUMERATED),
883 ASN1Type::Choice(_) => Cow::Borrowed(CHOICE),
884 ASN1Type::Sequence(_) => Cow::Borrowed(SEQUENCE),
885 ASN1Type::SequenceOf(_) => Cow::Borrowed(SEQUENCE_OF),
886 ASN1Type::Set(_) => Cow::Borrowed(SET),
887 ASN1Type::SetOf(_) => Cow::Borrowed(SET_OF),
888 ASN1Type::Time(_) => Cow::Borrowed(TIME),
889 ASN1Type::GeneralizedTime(_) => Cow::Borrowed(GENERALIZED_TIME),
890 ASN1Type::UTCTime(_) => Cow::Borrowed(UTC_TIME),
891 ASN1Type::Any => Cow::Borrowed(ANY),
892 ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere { identifier, .. }) => {
893 Cow::Borrowed(identifier)
894 }
895 ASN1Type::ChoiceSelectionType(_) => todo!(),
896 ASN1Type::ObjectIdentifier(_) => Cow::Borrowed(OBJECT_IDENTIFIER),
897 ASN1Type::ObjectClassField(ifr) => Cow::Owned(format!(
898 "{INTERNAL_IO_FIELD_REF_TYPE_NAME_PREFIX}{}${}",
899 ifr.class,
900 ifr.field_path_as_str()
901 )),
902 ASN1Type::EmbeddedPdv => Cow::Borrowed(EMBEDDED_PDV),
903 ASN1Type::External => Cow::Borrowed(EXTERNAL),
904 }
905 }
906
907 pub fn builtin_or_elsewhere(
908 parent: Option<&str>,
909 module: Option<&str>,
910 identifier: &str,
911 constraints: Vec<Constraint>,
912 ) -> ASN1Type {
913 match (parent, identifier) {
914 (None, NULL) => ASN1Type::Null,
915 (None, BOOLEAN) => ASN1Type::Boolean(Boolean { constraints }),
916 (None, REAL) => ASN1Type::Real(Real { constraints }),
917 (None, INTEGER) => ASN1Type::Integer(Integer {
918 constraints,
919 distinguished_values: None,
920 }),
921 (None, BIT_STRING) => ASN1Type::BitString(BitString {
922 constraints,
923 distinguished_values: None,
924 }),
925 (None, OCTET_STRING) => ASN1Type::OctetString(OctetString { constraints }),
926 (None, GENERALIZED_TIME) => ASN1Type::GeneralizedTime(GeneralizedTime { constraints }),
927 (None, UTC_TIME) => ASN1Type::UTCTime(UTCTime { constraints }),
928 (None, OBJECT_IDENTIFIER) => {
929 ASN1Type::ObjectIdentifier(ObjectIdentifier { constraints })
930 }
931 (None, BMP_STRING) => ASN1Type::CharacterString(CharacterString {
932 constraints,
933 ty: CharacterStringType::BMPString,
934 }),
935 (None, UTF8_STRING) => ASN1Type::CharacterString(CharacterString {
936 constraints,
937 ty: CharacterStringType::UTF8String,
938 }),
939 (None, PRINTABLE_STRING) => ASN1Type::CharacterString(CharacterString {
940 constraints,
941 ty: CharacterStringType::PrintableString,
942 }),
943 (None, TELETEX_STRING) => ASN1Type::CharacterString(CharacterString {
944 constraints,
945 ty: CharacterStringType::TeletexString,
946 }),
947 (None, T61_STRING) => ASN1Type::CharacterString(CharacterString {
948 constraints,
949 ty: CharacterStringType::TeletexString,
950 }),
951 (None, IA5_STRING) => ASN1Type::CharacterString(CharacterString {
952 constraints,
953 ty: CharacterStringType::IA5String,
954 }),
955 (None, UNIVERSAL_STRING) => ASN1Type::CharacterString(CharacterString {
956 constraints,
957 ty: CharacterStringType::UniversalString,
958 }),
959 (None, VISIBLE_STRING) => ASN1Type::CharacterString(CharacterString {
960 constraints,
961 ty: CharacterStringType::VisibleString,
962 }),
963 (None, GENERAL_STRING) => ASN1Type::CharacterString(CharacterString {
964 constraints,
965 ty: CharacterStringType::GeneralString,
966 }),
967 (None, VIDEOTEX_STRING) => ASN1Type::CharacterString(CharacterString {
968 constraints,
969 ty: CharacterStringType::VideotexString,
970 }),
971 (None, GRAPHIC_STRING) => ASN1Type::CharacterString(CharacterString {
972 constraints,
973 ty: CharacterStringType::GraphicString,
974 }),
975 (None, NUMERIC_STRING) => ASN1Type::CharacterString(CharacterString {
976 constraints,
977 ty: CharacterStringType::NumericString,
978 }),
979 _ => ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
980 parent: parent.map(str::to_string),
981 module: module.map(str::to_string),
982 identifier: identifier.to_string(),
983 constraints,
984 }),
985 }
986 }
987
988 pub fn is_builtin_type(&self) -> bool {
989 !matches!(
990 self,
991 ASN1Type::ElsewhereDeclaredType(_)
992 | ASN1Type::ChoiceSelectionType(_)
993 | ASN1Type::ObjectClassField(_)
994 )
995 }
996
997 pub fn constraints(&self) -> Option<&Vec<Constraint>> {
998 match self {
999 ASN1Type::Boolean(b) => Some(b.constraints()),
1000 ASN1Type::Real(r) => Some(r.constraints()),
1001 ASN1Type::Integer(i) => Some(i.constraints()),
1002 ASN1Type::BitString(b) => Some(b.constraints()),
1003 ASN1Type::OctetString(o) => Some(o.constraints()),
1004 ASN1Type::CharacterString(c) => Some(c.constraints()),
1005 ASN1Type::Enumerated(e) => Some(e.constraints()),
1006 ASN1Type::Time(t) => Some(t.constraints()),
1007 ASN1Type::Choice(c) => Some(c.constraints()),
1008 ASN1Type::Set(s) | ASN1Type::Sequence(s) => Some(s.constraints()),
1009 ASN1Type::SetOf(s) | ASN1Type::SequenceOf(s) => Some(s.constraints()),
1010 ASN1Type::ElsewhereDeclaredType(e) => Some(e.constraints()),
1011 ASN1Type::ObjectClassField(f) => Some(f.constraints()),
1012 _ => None,
1013 }
1014 }
1015
1016 pub fn constraints_mut(&mut self) -> Option<&mut Vec<Constraint>> {
1017 match self {
1018 ASN1Type::Boolean(b) => Some(b.constraints_mut()),
1019 ASN1Type::Real(r) => Some(r.constraints_mut()),
1020 ASN1Type::Integer(i) => Some(i.constraints_mut()),
1021 ASN1Type::BitString(b) => Some(b.constraints_mut()),
1022 ASN1Type::OctetString(o) => Some(o.constraints_mut()),
1023 ASN1Type::CharacterString(c) => Some(c.constraints_mut()),
1024 ASN1Type::Enumerated(e) => Some(e.constraints_mut()),
1025 ASN1Type::Time(t) => Some(t.constraints_mut()),
1026 ASN1Type::Choice(c) => Some(c.constraints_mut()),
1027 ASN1Type::Set(s) | ASN1Type::Sequence(s) => Some(s.constraints_mut()),
1028 ASN1Type::SetOf(s) | ASN1Type::SequenceOf(s) => Some(s.constraints_mut()),
1029 ASN1Type::ElsewhereDeclaredType(e) => Some(e.constraints_mut()),
1030 ASN1Type::ObjectClassField(f) => Some(f.constraints_mut()),
1031 _ => None,
1032 }
1033 }
1034}
1035
1036pub const NUMERIC_STRING_CHARSET: [char; 11] =
1037 [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
1038pub const PRINTABLE_STRING_CHARSET: [char; 74] = [
1039 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
1040 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
1041 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
1042 '5', '6', '7', '8', '9', ' ', '\'', '(', ')', '+', ',', '-', '.', '/', ':', '=', '?',
1043];
1044
1045#[cfg_attr(test, derive(EnumDebug))]
1047#[cfg_attr(not(test), derive(Debug))]
1048#[derive(Clone, PartialEq, Copy)]
1049pub enum CharacterStringType {
1050 NumericString,
1051 VisibleString,
1052 IA5String,
1053 TeletexString,
1054 VideotexString,
1055 GraphicString,
1056 GeneralString,
1057 UniversalString,
1058 UTF8String,
1059 BMPString,
1060 PrintableString,
1061}
1062
1063impl CharacterStringType {
1064 pub fn character_set(&self) -> BTreeMap<usize, char> {
1065 match self {
1066 CharacterStringType::NumericString => {
1067 NUMERIC_STRING_CHARSET.into_iter().enumerate().collect()
1068 }
1069 CharacterStringType::VisibleString | CharacterStringType::PrintableString => {
1070 PRINTABLE_STRING_CHARSET.into_iter().enumerate().collect()
1071 }
1072 CharacterStringType::IA5String => (0..128u32)
1073 .map(|i| char::from_u32(i).unwrap())
1074 .enumerate()
1075 .collect(),
1076 _ => (0..u16::MAX as u32)
1077 .filter_map(char::from_u32)
1078 .enumerate()
1079 .collect(),
1080 }
1081 }
1082}
1083
1084impl From<&str> for CharacterStringType {
1085 fn from(value: &str) -> Self {
1086 match value {
1087 IA5_STRING => Self::IA5String,
1088 NUMERIC_STRING => Self::NumericString,
1089 VISIBLE_STRING => Self::VisibleString,
1090 TELETEX_STRING => Self::TeletexString,
1091 T61_STRING => Self::TeletexString,
1092 VIDEOTEX_STRING => Self::VideotexString,
1093 GRAPHIC_STRING => Self::GraphicString,
1094 GENERAL_STRING => Self::GeneralString,
1095 UNIVERSAL_STRING => Self::UniversalString,
1096 BMP_STRING => Self::BMPString,
1097 PRINTABLE_STRING => Self::PrintableString,
1098 _ => Self::UTF8String,
1099 }
1100 }
1101}
1102
1103#[derive(Debug, Clone, Copy, PartialEq)]
1105pub enum IntegerType {
1106 Int8,
1107 Uint8,
1108 Int16,
1109 Uint16,
1110 Int32,
1111 Uint32,
1112 Int64,
1113 Uint64,
1114 Unbounded,
1115}
1116
1117impl ToTokens for IntegerType {
1118 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1119 match self {
1120 IntegerType::Int8 => tokens.append_all(quote!(i8)),
1121 IntegerType::Uint8 => tokens.append_all(quote!(u8)),
1122 IntegerType::Int16 => tokens.append_all(quote!(i16)),
1123 IntegerType::Uint16 => tokens.append_all(quote!(u16)),
1124 IntegerType::Int32 => tokens.append_all(quote!(i32)),
1125 IntegerType::Uint32 => tokens.append_all(quote!(u32)),
1126 IntegerType::Int64 => tokens.append_all(quote!(i64)),
1127 IntegerType::Uint64 => tokens.append_all(quote!(u64)),
1128 IntegerType::Unbounded => tokens.append_all(quote!(Integer)),
1129 }
1130 }
1131}
1132
1133impl IntegerType {
1134 pub fn is_unbounded(&self) -> bool {
1135 self == &IntegerType::Unbounded
1136 }
1137 pub fn max_restrictive(self, rhs: IntegerType) -> IntegerType {
1142 match (self, rhs) {
1143 (x, y) if x == y => x,
1144 (IntegerType::Uint8, _) | (_, IntegerType::Uint8) => IntegerType::Uint8,
1145 (IntegerType::Int8, _) | (_, IntegerType::Int8) => IntegerType::Int8,
1146 (IntegerType::Uint16, _) | (_, IntegerType::Uint16) => IntegerType::Uint16,
1147 (IntegerType::Int16, _) | (_, IntegerType::Int16) => IntegerType::Int16,
1148 (IntegerType::Uint32, _) | (_, IntegerType::Uint32) => IntegerType::Uint32,
1149 (IntegerType::Int32, _) | (_, IntegerType::Int32) => IntegerType::Int32,
1150 (IntegerType::Uint64, _) | (_, IntegerType::Uint64) => IntegerType::Uint64,
1151 (IntegerType::Int64, _) | (_, IntegerType::Int64) => IntegerType::Int64,
1152 _ => IntegerType::Unbounded,
1153 }
1154 }
1155}
1156
1157#[cfg_attr(test, derive(EnumDebug))]
1159#[cfg_attr(not(test), derive(Debug))]
1160#[derive(Clone, PartialEq)]
1161pub enum ASN1Value {
1162 All,
1163 Null,
1164 Boolean(bool),
1165 Choice {
1166 type_name: Option<String>,
1167 variant_name: String,
1168 inner_value: Box<ASN1Value>,
1169 },
1170 SequenceOrSet(Vec<(Option<String>, Box<ASN1Value>)>),
1173 Integer(i128),
1174 Real(f64),
1175 String(String),
1176 BitString(Vec<bool>),
1177 BitStringNamedBits(Vec<String>),
1178 OctetString(Vec<u8>),
1179 EnumeratedValue {
1180 enumerated: String,
1181 enumerable: String,
1182 },
1183 Time(String),
1184 ElsewhereDeclaredValue {
1185 parent: Option<String>,
1186 identifier: String,
1187 },
1188 ObjectIdentifier(ObjectIdentifierValue),
1189 LinkedNestedValue {
1202 supertypes: Vec<String>,
1204 value: Box<ASN1Value>,
1205 },
1206 LinkedIntValue {
1208 integer_type: IntegerType,
1209 value: i128,
1210 },
1211 LinkedStructLikeValue(Vec<(String, ASN1Type, StructLikeFieldValue)>),
1214 LinkedArrayLikeValue(Vec<Box<ASN1Value>>),
1216 LinkedCharStringValue(CharacterStringType, String),
1218 LinkedElsewhereDefinedValue {
1219 parent: Option<String>,
1220 identifier: String,
1221 can_be_const: bool,
1222 },
1223}
1224
1225#[cfg_attr(test, derive(EnumDebug))]
1227#[cfg_attr(not(test), derive(Debug))]
1228#[derive(Clone, PartialEq)]
1229pub enum StructLikeFieldValue {
1230 Explicit(Box<ASN1Value>),
1231 Implicit(Box<ASN1Value>),
1232}
1233
1234impl StructLikeFieldValue {
1235 pub fn into_value(self) -> ASN1Value {
1236 match self {
1237 StructLikeFieldValue::Explicit(v) | StructLikeFieldValue::Implicit(v) => *v,
1238 }
1239 }
1240
1241 pub fn value(&self) -> &ASN1Value {
1242 match self {
1243 StructLikeFieldValue::Explicit(v) | StructLikeFieldValue::Implicit(v) => v,
1244 }
1245 }
1246
1247 pub fn value_mut(&mut self) -> &mut ASN1Value {
1248 match self {
1249 StructLikeFieldValue::Explicit(ref mut v)
1250 | StructLikeFieldValue::Implicit(ref mut v) => &mut *v,
1251 }
1252 }
1253}
1254
1255impl AsMut<ASN1Value> for ASN1Value {
1256 fn as_mut(&mut self) -> &mut ASN1Value {
1257 self
1258 }
1259}
1260
1261impl ASN1Value {
1262 pub fn max(
1263 &self,
1264 other: &ASN1Value,
1265 char_set: Option<&BTreeMap<usize, char>>,
1266 ) -> Result<ASN1Value, GrammarError> {
1267 self.min_max(other, char_set, false)
1268 }
1269
1270 pub fn min(
1271 &self,
1272 other: &ASN1Value,
1273 char_set: Option<&BTreeMap<usize, char>>,
1274 ) -> Result<ASN1Value, GrammarError> {
1275 self.min_max(other, char_set, true)
1276 }
1277
1278 fn min_max(
1279 &self,
1280 other: &ASN1Value,
1281 char_set: Option<&BTreeMap<usize, char>>,
1282 getting_mininum: bool,
1283 ) -> Result<ASN1Value, GrammarError> {
1284 match (self, other, char_set) {
1285 (ASN1Value::Integer(s), ASN1Value::Integer(o), _) => {
1286 if getting_mininum {
1287 Ok(ASN1Value::Integer(*s.min(o)))
1288 } else {
1289 Ok(ASN1Value::Integer(*s.max(o)))
1290 }
1291 }
1292 (ASN1Value::String(s), ASN1Value::String(o), Some(set)) => {
1293 if s.len() != 1 || o.len() != 1 {
1294 return Err(grammar_error!(
1295 UnpackingError,
1296 "Unsupported operation for ASN1Values {self:?} and {other:?}"
1297 ));
1298 }
1299 let s_as_char = s.chars().next().unwrap();
1300 let o_as_char = o.chars().next().unwrap();
1301 match (
1302 set.iter().find(|(_, c)| s_as_char == **c),
1303 set.iter().find(|(_, c)| o_as_char == **c),
1304 ) {
1305 (Some((self_i, _)), Some((other_i, _))) => {
1306 let return_self = if getting_mininum {
1307 self_i <= other_i
1308 } else {
1309 self_i >= other_i
1310 };
1311 if return_self {
1312 Ok(self.clone())
1313 } else {
1314 Ok(other.clone())
1315 }
1316 }
1317 _ => Err(grammar_error!(
1318 UnpackingError,
1319 "Failed to find ASN1Values {self:?} and {other:?} in character set {char_set:?}",
1320 )),
1321 }
1322 }
1323 _ => Err(grammar_error!(
1324 UnpackingError,
1325 "Unsupported operation for ASN1Values {self:?} and {other:?}",
1326 )),
1327 }
1328 }
1329
1330 pub fn unwrap_as_integer(&self) -> Result<i128, GrammarError> {
1331 if let ASN1Value::Integer(i) = self {
1332 Ok(*i)
1333 } else {
1334 Err(grammar_error!(
1335 UnpackingError,
1336 "Cannot unwrap {self:?} as integer!"
1337 ))
1338 }
1339 }
1340}
1341
1342#[derive(Debug, Clone, PartialEq)]
1346pub struct DeclarationElsewhere {
1347 pub parent: Option<String>,
1349 pub module: Option<String>,
1351 pub identifier: String,
1352 pub constraints: Vec<Constraint>,
1353}
1354
1355impl From<(Option<&str>, &str, Option<Vec<Constraint>>)> for DeclarationElsewhere {
1356 fn from(value: (Option<&str>, &str, Option<Vec<Constraint>>)) -> Self {
1357 DeclarationElsewhere {
1358 parent: value.0.map(ToString::to_string),
1359 module: None,
1360 identifier: value.1.into(),
1361 constraints: value.2.unwrap_or_default(),
1362 }
1363 }
1364}
1365
1366#[derive(Debug, Clone, Copy, PartialEq)]
1368pub enum TagClass {
1369 Universal,
1370 Application,
1371 Private,
1372 ContextSpecific,
1373}
1374
1375#[derive(Debug, Clone, PartialEq)]
1377pub struct AsnTag {
1378 pub environment: TaggingEnvironment,
1379 pub tag_class: TagClass,
1380 pub id: u64,
1381}
1382
1383impl From<((Option<&str>, u64), Option<TaggingEnvironment>)> for AsnTag {
1384 fn from(value: ((Option<&str>, u64), Option<TaggingEnvironment>)) -> Self {
1385 let tag_class = match value.0 .0 {
1386 Some("APPLICATION") => TagClass::Application,
1387 Some("UNIVERSAL") => TagClass::Universal,
1388 Some("PRIVATE") => TagClass::Private,
1389 _ => TagClass::ContextSpecific,
1390 };
1391 AsnTag {
1392 tag_class,
1393 id: value.0 .1,
1394 environment: value.1.unwrap_or(TaggingEnvironment::Automatic),
1395 }
1396 }
1397}