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