rasn_compiler/intermediate/
mod.rs

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