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 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
36// Comment tokens
37pub const BLOCK_COMMENT_START: &str = "/*";
38pub const BLOCK_COMMENT_END: &str = "*/";
39pub const LINE_COMMENT: &str = "--";
40
41// Bracket tokens
42pub 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
51// Type tokens
52pub 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
86// Tagging tokens
87pub const UNIVERSAL: &str = "UNIVERSAL";
88pub const PRIVATE: &str = "PRIVATE";
89pub const APPLICATION: &str = "APPLICATION";
90
91// Value tokens
92pub const TRUE: &str = "TRUE";
93pub const FALSE: &str = "FALSE";
94
95// Header tokens
96pub 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
112// Information Object Class tokens
113pub 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
120// Subtyping tokens
121pub 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
143// Macro tokens
144pub 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
153// invalid syntax word tokens
154pub 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/// Represents the extensibility environment as specified in
283/// Rec. ITU-T X.680 (02/2021) § 13.4
284#[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/// Represents compatibility selectors as specified in
294/// Rec. ITU-T X.680 (02/2021) § 13.16 (f)
295#[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/// Represents a global module reference as specified in
304/// Rec. ITU-T X.680 (02/2021)
305#[derive(Debug, Clone, PartialEq)]
306pub struct ExternalValueReference {
307    pub module_reference: String,
308    pub value_reference: String,
309}
310
311/// Represents a global module reference as specified in
312/// Rec. ITU-T X.680 (02/2021)
313#[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/// Represents an assigned identifier as specified in
329/// Rec. ITU-T X.680 (02/2021)
330#[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/// Represents a module import as specified in
345/// Rec. ITU-T X.680 (02/2021) § 13.16
346#[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/// Represents a module export as specified in
370/// Rec. ITU-T X.680 (02/2021) § 13.13
371#[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/// Represents a module header's definitive identifier as specified in
386/// Rec. ITU-T X.680 (02/2021) § 13.8
387#[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/// Represents a module header as specified in
412/// Rec. ITU-T X.680 (02/2021) § 13
413#[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    /// Returns an import that matches a given identifier, if present.
426    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/// Represents an object identifier value as specified in
478/// Rec. ITU-T X.680 (02/2021) §32
479#[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/// Represents a single arc of an object identifier value
489/// as specified in Rec. ITU-T X.680 (02/2021) §32
490#[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/// Represents a top-level ASN.1 definition.
561/// The compiler distinguished three different variants of top-level definitions.
562///
563/// The linker and any [Backend] for this compiler consumes top-level definitions in
564/// order to generate bindings.
565#[cfg_attr(test, derive(EnumDebug))]
566#[cfg_attr(not(test), derive(Debug))]
567#[derive(Clone, PartialEq)]
568pub enum ToplevelDefinition {
569    /// Definition for a custom type based on ASN.1's built-in type.
570    Type(ToplevelTypeDefinition),
571    /// Definition for a value using custom or built-in type.
572    Value(ToplevelValueDefinition),
573    /// Definition for a object class as introduced in ITU-T X.681 9.
574    Class(ObjectClassAssignment),
575    /// Definition for an object or object set, as introduced in ITU-T X.681 11.
576    Object(ToplevelInformationDefinition),
577    /// Definition for a macro.
578    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    /// Returns the name of a top-level definition.
656    /// ### Example
657    /// ```
658    /// # use rasn_compiler::prelude::ir::*;
659    /// assert_eq!(
660    ///     ToplevelDefinition::Value(
661    ///         ToplevelValueDefinition {
662    ///             comments: String::from("Comments from the ASN.1 spec"),
663    ///             parameterization: None,
664    ///             name: String::from("the-answer"),
665    ///             associated_type: ASN1Type::Integer(Integer {
666    ///                 constraints: vec![],
667    ///                 distinguished_values: None,
668    ///             }),
669    ///             value: ASN1Value::Integer(42),
670    ///             module_header: None,
671    ///         }
672    ///     ).name(),
673    ///     &String::from("the-answer")
674    /// );
675    /// ```
676    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/// Represents a top-level definition of a value
688/// using a custom or built-in ASN.1 type.
689#[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/// The possible types of an ASN1 data element.
798/// In addition, the `ElsewhereDeclaredType` enumeral denotes an type
799/// specified in the same or an imported ASN1 specification.
800#[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/// The types of an ASN1 character strings.
1046#[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/// Representation of common integer types
1104#[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    /// Returns the Integer type with more restrictions
1138    /// - an IntegerType with a smaller set of values is considered more restrictive
1139    /// - an unsigned IntegerType is considered more restrictive if the size of the set of values is equal
1140    ///   if equal, `self` is returned
1141    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/// The possible types of an ASN1 value.
1158#[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    /// In ASN.1, value definitions are ambiguous between SEQUENCE, SET, SEQUENCE OF, and SET OF
1171    /// For example, `{ my-elem FALSE }` could be a value of all four types
1172    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    /// In ASN1 value declarations, the value type is not straighforward to parse.
1190    /// For example, in the following ASN1
1191    /// ```ignore
1192    /// ExampleInt ::= INTEGER
1193    /// ExampleSubset ::= ExampleInt (1..500)
1194    /// AnotherSubset ::= ExampleSubset (2..200)
1195    /// ExampleSet ::= SET {
1196    ///     int AnotherSubset DEFAULT 3
1197    /// }
1198    /// ```
1199    /// the relation of the default value to `ExampleSubset` will not be picked up by the lexer.
1200    /// However, in some representations, this relation is critical information.
1201    LinkedNestedValue {
1202        /// typereferences of supertypes
1203        supertypes: Vec<String>,
1204        value: Box<ASN1Value>,
1205    },
1206    /// Integer values need type information that will not always be picked up by the lexer on first pass.
1207    LinkedIntValue {
1208        integer_type: IntegerType,
1209        value: i128,
1210    },
1211    /// Struct-like values such as SEQUENCE values need type information that will not always be picked up by the lexer on first pass.
1212    /// Contains a vector of the struct-like's fields, with the field name, the field type, and the field value as a tuple
1213    LinkedStructLikeValue(Vec<(String, ASN1Type, StructLikeFieldValue)>),
1214    /// Array-like values such as SEQUENCE OF values need type information that will not always be picked up by the lexer on first pass.
1215    LinkedArrayLikeValue(Vec<Box<ASN1Value>>),
1216    /// Character string values such as UTF8String values need type information that will not always be picked up by the lexer on first pass.
1217    LinkedCharStringValue(CharacterStringType, String),
1218    LinkedElsewhereDefinedValue {
1219        parent: Option<String>,
1220        identifier: String,
1221        can_be_const: bool,
1222    },
1223}
1224
1225/// Representation of a field value of a struct-like ASN1 value
1226#[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/// Intermediate placeholder for a type declared in
1343/// some other part of the ASN1 specification that is
1344/// being parsed or in one of its imports.
1345#[derive(Debug, Clone, PartialEq)]
1346pub struct DeclarationElsewhere {
1347    /// Chain of parent declaration leading back to a basic ASN1 type
1348    pub parent: Option<String>,
1349    /// Name of the module where the identifier should be found.
1350    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/// Tag classes
1367#[derive(Debug, Clone, Copy, PartialEq)]
1368pub enum TagClass {
1369    Universal,
1370    Application,
1371    Private,
1372    ContextSpecific,
1373}
1374
1375/// Representation of a tag
1376#[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}