rasn_compiler/validator/linking/
mod.rs

1//! The `linking` module contains methods to link different tokens of the parsed AST
2//! in order to generate correct rust representations.
3
4mod constraints;
5mod information_object;
6mod types;
7mod utils;
8
9use std::{
10    borrow::{BorrowMut, Cow},
11    collections::BTreeMap,
12};
13
14use crate::{
15    common::INTERNAL_NESTED_TYPE_NAME_PREFIX,
16    intermediate::{error::*, information_object::*, types::*, utils::*, *},
17    validator::{
18        linking::utils::bit_string_to_octet_string,
19        parameterization::{Parameterization, ParameterizationArgument},
20    },
21};
22
23use self::{
24    parameterization::ParameterGovernor,
25    utils::{find_tld_or_enum_value_by_name, octet_string_to_bit_string},
26};
27
28use super::{Constraint, Parameter, TableConstraint};
29
30macro_rules! grammar_error {
31    ($kind:ident, $($arg:tt)*) => {
32        GrammarError::new(&format!($($arg)*), GrammarErrorType::$kind)
33    };
34}
35
36impl ToplevelDefinition {
37    pub(crate) fn is_parameterized(&self) -> bool {
38        match self {
39            ToplevelDefinition::Information(ToplevelInformationDefinition {
40                parameterization: Some(_),
41                ..
42            })
43            | ToplevelDefinition::Type(ToplevelTypeDefinition {
44                parameterization: Some(_),
45                ..
46            })
47            | ToplevelDefinition::Value(ToplevelValueDefinition {
48                parameterization: Some(_),
49                ..
50            }) => true,
51            ToplevelDefinition::Type(ToplevelTypeDefinition {
52                ty: ASN1Type::Sequence(s),
53                ..
54            })
55            | ToplevelDefinition::Type(ToplevelTypeDefinition {
56                ty: ASN1Type::Set(s),
57                ..
58            }) => s.members.iter().any(|m| {
59                m.constraints
60                    .iter()
61                    .any(|c| matches!(c, Constraint::Parameter(_)))
62            }),
63            ToplevelDefinition::Type(ToplevelTypeDefinition {
64                ty: ASN1Type::SequenceOf(s),
65                ..
66            })
67            | ToplevelDefinition::Type(ToplevelTypeDefinition {
68                ty: ASN1Type::SetOf(s),
69                ..
70            }) => s.element_type.constraints().map_or(false, |constraints| {
71                constraints
72                    .iter()
73                    .any(|c| matches!(c, Constraint::Parameter(_)))
74            }),
75            _ => false,
76        }
77    }
78
79    pub(crate) fn get_distinguished_or_enum_value(
80        &self,
81        type_name: Option<&String>,
82        identifier: &String,
83    ) -> Option<ASN1Value> {
84        if let ToplevelDefinition::Type(t) = self {
85            if type_name.is_some() && Some(&t.name) != type_name {
86                return None;
87            }
88            match &t.ty {
89                ASN1Type::Enumerated(e) => {
90                    return e
91                        .members
92                        .iter()
93                        .find_map(|m| (&m.name == identifier).then(|| ASN1Value::Integer(m.index)))
94                }
95                ASN1Type::Integer(i) => {
96                    return i.distinguished_values.as_ref().and_then(|dv| {
97                        dv.iter().find_map(|d| {
98                            (&d.name == identifier).then(|| ASN1Value::Integer(d.value))
99                        })
100                    })
101                }
102                _ => (),
103            }
104        }
105        None
106    }
107
108    pub fn is_class_with_name(&self, name: &String) -> Option<&InformationObjectClass> {
109        match self {
110            ToplevelDefinition::Information(info) => match &info.value {
111                ASN1Information::ObjectClass(class) => (&info.name == name).then_some(class),
112                _ => None,
113            },
114            _ => None,
115        }
116    }
117
118    /// Checks if at any depth down the arbitrarily nested `self`, an elsewhere declared type with the name `name` exists.
119    /// Sequence Ofs and Set Ofs break the recursion tree, because they use heap-based data structures.
120    pub fn recurses(&self, name: &str, tlds: &BTreeMap<String, ToplevelDefinition>) -> bool {
121        match self {
122            ToplevelDefinition::Type(ToplevelTypeDefinition { ty, .. }) => ty.recurses(name, tlds),
123            _ => false, // TODO: Check recursion for values and information objects
124        }
125    }
126
127    /// Traverses a top-level declaration to check for references to other top-level declarations
128    /// in a constraint. An example would be the constraint of the `intercontinental` field in the
129    /// following example.
130    /// ```ignore
131    /// fifteen INTEGER = 15
132    ///
133    /// Departures ::= SEQUENCE {
134    ///   local SEQUENCE (SIZE(0..999)) OF Local,
135    ///   continental SEQUENCE (SIZE(0..99)) OF Continental,
136    ///   intercontinental SEQUENCE (SIZE(0..fifteen)) OF Intercontinental
137    /// }
138    /// ```
139    pub fn has_constraint_reference(&self) -> bool {
140        match self {
141            ToplevelDefinition::Type(t) => t.ty.contains_constraint_reference(),
142            // TODO: Cover constraint references in other types of top-level declarations
143            _ => false,
144        }
145    }
146
147    /// Traverses a top-level declaration to replace references to other top-level declarations
148    /// in a constraint. An example would be the constraint of the `intercontinental` field in the
149    /// following example.
150    /// ```ignore
151    /// fifteen INTEGER = 15
152    ///
153    /// Departures ::= SEQUENCE {
154    ///   local SEQUENCE (SIZE(0..999)) OF Local,
155    ///   continental SEQUENCE (SIZE(0..99)) OF Continental,
156    ///   intercontinental SEQUENCE (SIZE(0..fifteen)) OF Intercontinental
157    /// }
158    /// ```
159    /// The method handles linking of multiple constraint references within a top-level declaration.
160    ///
161    /// ## Parameterization
162    /// This linking step also resolves implementations of parameterized types.
163    /// The compiler does not create representations of abstract parameterized types
164    /// but only of actual implementations. For example, no rust output
165    /// will be generated for
166    /// ```ignore
167    /// ParamType { INTEGER: lower, BOOLEAN: flag } ::= SEQUENCE {
168    ///     int-value INTEGER (lower..12),
169    ///     bool-value BOOLEAN DEFAULT flag
170    /// }
171    /// ```
172    /// but an implementing type such as
173    /// ```ignore
174    /// ImplType ::= ParamType { 2, TRUE }
175    /// ```
176    /// will be represented in the generated rust bindings.
177    /// ### Params
178    ///  * `tlds` - vector of other top-level declarations that will be searched as the method resolves a reference
179    /// returns `true` if the reference was resolved successfully.
180    pub fn link_constraint_reference(
181        &mut self,
182        tlds: &BTreeMap<String, ToplevelDefinition>,
183    ) -> Result<bool, GrammarError> {
184        match self {
185            ToplevelDefinition::Type(t) => {
186                if let Some(replacement) = t.ty.link_constraint_reference(&t.name, tlds)? {
187                    t.ty = replacement;
188                }
189                Ok(true)
190            }
191            // TODO: Cover constraint references in other types of top-level declarations
192            _ => Ok(false),
193        }
194    }
195
196    /// Traverses top-level declarations and marks recursive types
197    pub fn mark_recursive(
198        &mut self,
199        tlds: &BTreeMap<String, ToplevelDefinition>,
200    ) -> Result<(), GrammarError> {
201        match self {
202            ToplevelDefinition::Type(t) => {
203                let _ = t.ty.mark_recursive(&t.name, tlds)?;
204                Ok(())
205            }
206            ToplevelDefinition::Value(_v) => Ok(()), // TODO
207            ToplevelDefinition::Information(_i) => Ok(()), // TODO
208        }
209    }
210
211    /// Collects supertypes of ASN1 values.
212    pub fn collect_supertypes(
213        &mut self,
214        tlds: &BTreeMap<String, ToplevelDefinition>,
215    ) -> Result<(), GrammarError> {
216        match self {
217            ToplevelDefinition::Type(t) => t.ty.collect_supertypes(tlds),
218            ToplevelDefinition::Value(v) => v.collect_supertypes(tlds),
219            ToplevelDefinition::Information(i) => i.collect_supertypes(tlds),
220        }
221    }
222}
223
224impl ToplevelValueDefinition {
225    /// Collects supertypes and implicit supertypes of an ASN1 value
226    /// that are not straightforward to parse on first pass
227    /// ### Example
228    /// `exmpleValue`'s supertypes would be "ExampleType", "OuterExampleType", and "RootType"
229    /// ```ignore
230    /// ExampleType ::= OuterExampleType (2..8)
231    /// OuterExampleType ::= RootType
232    /// RootType ::= INTEGER
233    /// exampleValue ExampleType ::= 6
234    /// ```
235    /// The supertypes are recorded in a `LinkedASN1Value`
236    pub fn collect_supertypes(
237        &mut self,
238        tlds: &BTreeMap<String, ToplevelDefinition>,
239    ) -> Result<(), GrammarError> {
240        if let Some(ToplevelDefinition::Type(tld)) =
241            tlds.get(self.associated_type.as_str().as_ref())
242        {
243            self.value.link_with_type(tlds, &tld.ty, Some(&tld.name))
244        } else {
245            self.value.link_with_type(tlds, &self.associated_type, None)
246        }
247    }
248}
249
250impl ASN1Type {
251    /// Collects supertypes of ASN1 values.
252    /// In `ToplevelTypeDefinition`s, values will appear only as `DEFAULT`
253    /// values in `SET`s or `SEQUENCE`s.
254    pub fn collect_supertypes(
255        &mut self,
256        tlds: &BTreeMap<String, ToplevelDefinition>,
257    ) -> Result<(), GrammarError> {
258        match self {
259            ASN1Type::Set(ref mut s) | ASN1Type::Sequence(ref mut s) => {
260                s.members.iter_mut().try_for_each(|m| {
261                    m.ty.collect_supertypes(tlds)?;
262                    m.default_value
263                        .as_mut()
264                        .map(|d| d.link_with_type(tlds, &m.ty, Some(&m.ty.as_str().into_owned())))
265                        .unwrap_or(Ok(()))
266                })
267            }
268            ASN1Type::Choice(ref mut c) => c
269                .options
270                .iter_mut()
271                .try_for_each(|o| o.ty.collect_supertypes(tlds)),
272            _ => Ok(()),
273        }
274    }
275
276    pub fn has_choice_selection_type(&self) -> bool {
277        match self {
278            ASN1Type::ChoiceSelectionType(_) => true,
279            ASN1Type::Sequence(s) | ASN1Type::Set(s) => s
280                .members
281                .iter()
282                .map(|m| m.ty.has_choice_selection_type())
283                .any(|b| b),
284            ASN1Type::Choice(c) => c
285                .options
286                .iter()
287                .map(|o| o.ty.has_choice_selection_type())
288                .any(|b| b),
289            ASN1Type::SequenceOf(s) | ASN1Type::SetOf(s) => {
290                s.element_type.has_choice_selection_type()
291            }
292            _ => false,
293        }
294    }
295
296    pub fn link_choice_selection_type(
297        &mut self,
298        tlds: &BTreeMap<String, ToplevelDefinition>,
299    ) -> Result<(), GrammarError> {
300        match self {
301            ASN1Type::ChoiceSelectionType(c) => {
302                if let Some(ToplevelDefinition::Type(parent)) = tlds.get(&c.choice_name) {
303                    *self = parent.ty.clone();
304                    Ok(())
305                } else {
306                    Err(grammar_error!(
307                        LinkerError,
308                        "Could not find Choice {} of selection type.",
309                        c.choice_name
310                    ))
311                }
312            }
313            ASN1Type::Sequence(s) | ASN1Type::Set(s) => s
314                .members
315                .iter_mut()
316                .try_for_each(|m| m.ty.link_choice_selection_type(tlds)),
317            ASN1Type::Choice(c) => c
318                .options
319                .iter_mut()
320                .try_for_each(|o: &mut ChoiceOption| o.ty.link_choice_selection_type(tlds)),
321            ASN1Type::SequenceOf(s) | ASN1Type::SetOf(s) => {
322                s.element_type.link_choice_selection_type(tlds)
323            }
324            _ => Ok(()),
325        }
326    }
327
328    pub fn contains_components_of_notation(&self) -> bool {
329        match self {
330            ASN1Type::Choice(c) => c
331                .options
332                .iter()
333                .any(|o| o.ty.contains_components_of_notation()),
334            ASN1Type::Set(s) | ASN1Type::Sequence(s) => {
335                !s.components_of.is_empty()
336                    || s.members
337                        .iter()
338                        .any(|m| m.ty.contains_components_of_notation())
339            }
340            ASN1Type::SequenceOf(so) => so.element_type.contains_components_of_notation(),
341            _ => false,
342        }
343    }
344
345    pub fn link_components_of_notation(
346        &mut self,
347        tlds: &BTreeMap<String, ToplevelDefinition>,
348    ) -> bool {
349        match self {
350            ASN1Type::Choice(c) => c
351                .options
352                .iter_mut()
353                .any(|o| o.ty.link_components_of_notation(tlds)),
354            ASN1Type::Set(s) | ASN1Type::Sequence(s) => {
355                let mut member_linking = s
356                    .members
357                    .iter_mut()
358                    .any(|m| m.ty.link_components_of_notation(tlds));
359                // TODO: properly link components of in extensions
360                // TODO: link components of Class field, such as COMPONENTS OF BILATERAL.&id
361                for comp_link in &s.components_of {
362                    if let Some(ToplevelDefinition::Type(linked)) = tlds.get(comp_link) {
363                        if let ASN1Type::Sequence(linked_seq) = &linked.ty {
364                            linked_seq
365                                .members
366                                .iter()
367                                .enumerate()
368                                .for_each(|(index, member)| {
369                                    if index < linked_seq.extensible.unwrap_or(usize::MAX) {
370                                        if let Some(index_of_first_ext) = s.extensible {
371                                            s.extensible = Some(index_of_first_ext + 1)
372                                        }
373                                        s.members.push(member.clone());
374                                    }
375                                });
376                            member_linking = true;
377                        }
378                    }
379                }
380                member_linking
381            }
382            ASN1Type::SequenceOf(so) => so.element_type.link_components_of_notation(tlds),
383            _ => false,
384        }
385    }
386
387    pub fn link_constraint_reference(
388        &mut self,
389        name: &String,
390        tlds: &BTreeMap<String, ToplevelDefinition>,
391    ) -> Result<Option<ASN1Type>, GrammarError> {
392        let mut self_replacement = None;
393        match self {
394            ASN1Type::Null => (),
395            ASN1Type::Choice(c) => {
396                for b in c.constraints.iter_mut() {
397                    b.link_cross_reference(name, tlds)?;
398                }
399                for opt in c.options.iter_mut() {
400                    if let Some(replacement) = opt.ty.link_constraint_reference(name, tlds)? {
401                        opt.ty = replacement;
402                    }
403                    for c in opt.constraints.iter_mut() {
404                        c.link_cross_reference(name, tlds)?;
405                    }
406                    for c in opt.ty.constraints_mut().unwrap_or(&mut vec![]).iter_mut() {
407                        c.link_cross_reference(name, tlds)?;
408                    }
409                }
410            }
411            ASN1Type::Set(s) | ASN1Type::Sequence(s) => {
412                for b in s.constraints.iter_mut() {
413                    b.link_cross_reference(name, tlds)?;
414                }
415                for m in s.members.iter_mut() {
416                    if let Some(replacement) = m.ty.link_constraint_reference(name, tlds)? {
417                        m.ty = replacement;
418                    }
419                }
420            }
421            ASN1Type::SetOf(s) | ASN1Type::SequenceOf(s) => {
422                for b in s.constraints.iter_mut() {
423                    b.link_cross_reference(name, tlds)?;
424                }
425                if let Some(replacement) = s.element_type.link_constraint_reference(name, tlds)? {
426                    s.element_type = Box::new(replacement);
427                }
428            }
429            ASN1Type::ElsewhereDeclaredType(e) => {
430                if let Some(Constraint::Parameter(args)) = e
431                    .constraints()
432                    .iter()
433                    .find(|c| matches![c, Constraint::Parameter(_)])
434                {
435                    self_replacement = Some(Self::resolve_parameters(
436                        &e.identifier,
437                        e.parent.as_ref(),
438                        tlds,
439                        args,
440                    )?);
441                } else {
442                    let id_clone = e.identifier.clone();
443                    for c in e.constraints_mut() {
444                        c.link_cross_reference(&id_clone, tlds)?;
445                    }
446                }
447            }
448            ASN1Type::InformationObjectFieldReference(iofr) => {
449                if let Some(ToplevelDefinition::Information(ToplevelInformationDefinition {
450                    value: ASN1Information::ObjectClass(clazz),
451                    ..
452                })) = tlds.get(&iofr.class)
453                {
454                    if let Some(InformationObjectClassField { ty: Some(ty), .. }) =
455                        clazz.get_field(&iofr.field_path)
456                    {
457                        self_replacement = Some(ty.clone());
458                    }
459                }
460            }
461            ty => {
462                if let Some(c) = ty.constraints_mut() {
463                    for c in c.iter_mut() {
464                        c.link_cross_reference(name, tlds)?;
465                    }
466                }
467            }
468        }
469        Ok(self_replacement)
470    }
471
472    pub(crate) fn resolve_parameters(
473        identifier: &String,
474        _parent: Option<&String>,
475        tlds: &BTreeMap<String, ToplevelDefinition>,
476        args: &[Parameter],
477    ) -> Result<ASN1Type, GrammarError> {
478        match tlds.get(identifier) {
479            Some(ToplevelDefinition::Type(ToplevelTypeDefinition {
480                ty,
481                parameterization: Some(Parameterization { parameters }),
482                ..
483            })) => {
484                let mut impl_template = ty.clone();
485                let mut impl_tlds = tlds.clone();
486                let mut table_constraint_replacements = BTreeMap::new();
487                for (
488                    index,
489                    ParameterizationArgument {
490                        dummy_reference,
491                        param_governor,
492                    },
493                ) in parameters.iter().enumerate()
494                {
495                    let arg = args.get(index).ok_or_else(|| grammar_error!(LinkerError, "Did not find an argument for parameter {dummy_reference} of {identifier}"))?;
496                    match (arg, param_governor) {
497                        (Parameter::ValueParameter(v), ParameterGovernor::TypeOrClass(gov)) => {
498                            impl_tlds.insert(
499                                dummy_reference.clone(),
500                                ToplevelDefinition::Value(ToplevelValueDefinition::from((
501                                    dummy_reference.as_str(),
502                                    v.clone(),
503                                    gov.clone(),
504                                ))),
505                            );
506                        }
507                        (Parameter::TypeParameter(t), _) => {
508                            impl_tlds.insert(
509                                dummy_reference.clone(),
510                                ToplevelDefinition::Type(ToplevelTypeDefinition::from((
511                                    dummy_reference.as_str(),
512                                    t.clone(),
513                                ))),
514                            );
515                        }
516                        (Parameter::InformationObjectParameter(_), _) => todo!(),
517                        (Parameter::ObjectSetParameter(o), ParameterGovernor::Class(c)) => {
518                            match &o.values.first() {
519                                    Some(osv) if o.values.len() == 1 => {
520                                        #[allow(suspicious_double_ref_op)]
521                                        table_constraint_replacements.insert(dummy_reference, osv.clone());
522                                    }
523                                    _ => return Err(grammar_error!(LinkerError, "Expected object set value argument to contain single object set value!"))
524                                }
525                            let mut info = ASN1Information::ObjectSet(o.clone());
526                            info.link_object_set_reference(tlds);
527                            let mut tld = ToplevelInformationDefinition::from((
528                                dummy_reference.as_str(),
529                                info,
530                                c.as_str(),
531                            ));
532                            tld = tld.resolve_class_reference(tlds);
533                            impl_tlds.insert(
534                                dummy_reference.clone(),
535                                ToplevelDefinition::Information(tld),
536                            );
537                        }
538                        _ => {
539                            return Err(grammar_error!(
540                            LinkerError,
541                            "Mismatching argument for parameter {dummy_reference} of {identifier}"
542                        ))
543                        }
544                    }
545                }
546                impl_template.link_elsewhere_declared(&impl_tlds)?;
547                if let Some(replacement) =
548                    impl_template.link_constraint_reference(identifier, &impl_tlds)?
549                {
550                    impl_template = replacement;
551                };
552                impl_template
553                    .collect_supertypes(&impl_tlds)
554                    .or_else(|_| impl_template.collect_supertypes(tlds))?;
555                for (dummy_reference, osv) in table_constraint_replacements {
556                    impl_template.reassign_table_constraint(dummy_reference, osv)?;
557                }
558                Ok(impl_template)
559            }
560            _ => Err(grammar_error!(
561                LinkerError,
562                "Failed to resolve supertype {identifier} of parameterized implementation."
563            )),
564        }
565    }
566
567    /// Checks if at any depth down the arbitrarily nested `self`, an elsewhere declared type with the name `name` exists.
568    /// Sequence Ofs and Set Ofs break the recursion tree, because they use heap-based data structures.
569    pub fn recurses(&self, name: &str, tlds: &BTreeMap<String, ToplevelDefinition>) -> bool {
570        match self {
571            ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere { identifier, .. }) => {
572                identifier == name
573                    || tlds
574                        .get(identifier)
575                        .is_some_and(|tld| tld.recurses(name, tlds))
576            }
577            ASN1Type::Choice(c) => c.options.iter().any(|opt| opt.ty.recurses(name, tlds)),
578            ASN1Type::Sequence(s) | ASN1Type::Set(s) => {
579                s.members.iter().any(|m| m.ty.recurses(name, tlds))
580            }
581            _ => false,
582        }
583    }
584
585    /// Traverses type and marks if recursive. Returns a vector of traversed type IDs since the last recursion detection or the leaf type.
586    pub fn mark_recursive(
587        &mut self,
588        name: &str,
589        tlds: &BTreeMap<String, ToplevelDefinition>,
590    ) -> Result<Vec<Cow<str>>, GrammarError> {
591        match self {
592            ASN1Type::Choice(choice) => {
593                let mut children = Vec::new();
594                for option in &mut choice.options {
595                    option.is_recursive = option.ty.recurses(name, tlds);
596                    let opt_ty_name = option.ty.as_str().into_owned();
597                    let mut opt_children = option.ty.mark_recursive(&opt_ty_name, tlds)?;
598                    if opt_children.iter().any(|id: &Cow<'_, str>| id == name) {
599                        option.is_recursive = true;
600                    } else {
601                        children.append(&mut opt_children);
602                    }
603                }
604                Ok(children)
605            }
606            ASN1Type::Set(s) | ASN1Type::Sequence(s) => {
607                let mut children = Vec::new();
608                for member in &mut s.members {
609                    member.is_recursive = member.ty.recurses(name, tlds);
610                    let mem_ty_name = member.ty.as_str().into_owned();
611                    let mut mem_children = member.ty.mark_recursive(&mem_ty_name, tlds)?;
612                    if mem_children.iter().any(|id: &Cow<'_, str>| id == name) {
613                        member.is_recursive = true;
614                    } else {
615                        children.append(&mut mem_children);
616                    }
617                }
618                Ok(children)
619            }
620            // SequenceOf and SetOf provide the necessary indirection
621            ASN1Type::SequenceOf(_) | ASN1Type::SetOf(_) => Ok(Vec::new()),
622            ASN1Type::ChoiceSelectionType(_) => Err(grammar_error!(
623                LinkerError,
624                "Choice selection types should be resolved by now"
625            )),
626            ASN1Type::InformationObjectFieldReference(_information_object_field_reference) => {
627                Ok(Vec::new())
628            } // TODO
629            n => Ok(vec![n.as_str()]),
630        }
631    }
632
633    /// In certain parameterization cases, the constraining object set of a table constraint
634    /// has to be reassigned. Consider the following example:
635    /// ```ignore
636    /// ProtocolExtensionContainer {NGAP-PROTOCOL-EXTENSION : ExtensionSetParam} ::=
637    ///     SEQUENCE (SIZE (1..4)) OF
638    ///     ProtocolExtensionField {{ExtensionSetParam}}
639    ///
640    /// ProtocolExtensionField {NGAP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE {
641    ///     id                    NGAP-PROTOCOL-EXTENSION.&id                ({ExtensionSetParam}),
642    ///     extensionValue        NGAP-PROTOCOL-EXTENSION.&Extension        ({ExtensionSetParam}{@id})
643    /// }
644    ///
645    /// ActualExtensions ::= ProtocolExtensionContainer { {ApplicableSet} }
646    /// ApplicableSet NGAP-PROTOCOL-EXTENSION ::= { ... }
647    /// ```
648    /// Since the compiler only creates bindings for actual implementations of abstract items,
649    /// the `ExtensionSetParam` references in `ProtocolExtensionField`'s table constraints need
650    /// to be reassigned to the actual object sets that are passed in by the implementations of
651    /// the abstract classes.
652    fn reassign_table_constraint(
653        &mut self,
654        reference_id_before: &str,
655        replacement: &ObjectSetValue,
656    ) -> Result<(), GrammarError> {
657        match self {
658            ASN1Type::Sequence(s) | ASN1Type::Set(s) => {
659                for m in &mut s.members {
660                    if let Some(constraints) = m.ty.constraints_mut() {
661                        for c in constraints {
662                            if let Constraint::TableConstraint(TableConstraint {
663                                object_set: ObjectSet { values, .. },
664                                ..
665                            }) = c
666                            {
667                                for value in values {
668                                    match value {
669                                        ObjectSetValue::Reference(r)
670                                            if r == reference_id_before =>
671                                        {
672                                            *value = replacement.clone();
673                                        }
674                                        _ => (),
675                                    }
676                                }
677                            }
678                        }
679                    }
680                }
681                Ok(())
682            }
683            ASN1Type::SequenceOf(s) | ASN1Type::SetOf(s) => s
684                .element_type
685                .reassign_table_constraint(reference_id_before, replacement),
686            _ => Ok(()),
687        }
688    }
689
690    fn link_elsewhere_declared(
691        &mut self,
692        tlds: &BTreeMap<String, ToplevelDefinition>,
693    ) -> Result<(), GrammarError> {
694        match self {
695            ASN1Type::Choice(c) => c
696                .options
697                .iter_mut()
698                .try_for_each(|o| o.ty.link_elsewhere_declared(tlds)),
699            ASN1Type::Set(s) | ASN1Type::Sequence(s) => s
700                .members
701                .iter_mut()
702                .try_for_each(|o| o.ty.link_elsewhere_declared(tlds)),
703            ASN1Type::SequenceOf(s) | ASN1Type::SetOf(s) => {
704                s.element_type.link_elsewhere_declared(tlds)
705            }
706            ASN1Type::ElsewhereDeclaredType(e) => {
707                if let Some(ToplevelDefinition::Type(tld)) = tlds.get(&e.identifier) {
708                    *self = tld.ty.clone();
709                    Ok(())
710                } else {
711                    Err(grammar_error!(
712                        LinkerError,
713                        "Failed to resolve argument {} of parameterized implementation.",
714                        e.identifier
715                    ))
716                }
717            }
718            ASN1Type::InformationObjectFieldReference(iofr) => {
719                if let Some(ToplevelDefinition::Information(ToplevelInformationDefinition {
720                    value: ASN1Information::ObjectClass(c),
721                    ..
722                })) = tlds.get(&iofr.class)
723                {
724                    if let Some(field) = c.get_field(&iofr.field_path) {
725                        if let Some(ref ty) = field.ty {
726                            *self = ty.clone();
727                        }
728                        return Ok(());
729                    }
730                }
731                Err(grammar_error!(
732                    LinkerError,
733                    "Failed to resolve argument {}.{} of parameterized implementation.",
734                    iofr.class,
735                    iofr.field_path
736                        .iter()
737                        .map(|f| f.identifier().clone())
738                        .collect::<Vec<_>>()
739                        .join(".")
740                ))
741            }
742            ASN1Type::ChoiceSelectionType(_) => Err(grammar_error!(
743                LinkerError,
744                "Linking choice selection type is not yet supported!"
745            )),
746            _ => Ok(()),
747        }
748    }
749
750    pub fn contains_constraint_reference(&self) -> bool {
751        match self {
752            ASN1Type::Null => false,
753            ASN1Type::Boolean(b) => b.constraints.iter().any(|c| c.has_cross_reference()),
754            ASN1Type::ObjectIdentifier(o) => o.constraints.iter().any(|c| c.has_cross_reference()),
755            ASN1Type::Integer(i) => i.constraints.iter().any(|c| c.has_cross_reference()),
756            ASN1Type::BitString(b) => b.constraints.iter().any(|c| c.has_cross_reference()),
757            ASN1Type::OctetString(o) => o.constraints.iter().any(|c| c.has_cross_reference()),
758            ASN1Type::CharacterString(c) => c.constraints.iter().any(|c| c.has_cross_reference()),
759            ASN1Type::Enumerated(e) => e.constraints.iter().any(|c| c.has_cross_reference()),
760            ASN1Type::Choice(c) => {
761                c.constraints.iter().any(|c| c.has_cross_reference())
762                    || c.options.iter().any(|o| {
763                        o.ty.contains_constraint_reference()
764                            || o.constraints.iter().any(|c| c.has_cross_reference())
765                    })
766            }
767            ASN1Type::Set(s) | ASN1Type::Sequence(s) => {
768                s.constraints.iter().any(|c| c.has_cross_reference())
769                    || s.members.iter().any(|m| {
770                        m.ty.contains_constraint_reference()
771                            || m.default_value
772                                .as_ref()
773                                .map_or(false, |d| d.is_elsewhere_declared())
774                            || m.constraints.iter().any(|c| c.has_cross_reference())
775                    })
776            }
777            ASN1Type::SetOf(s) | ASN1Type::SequenceOf(s) => {
778                s.constraints.iter().any(|c| c.has_cross_reference())
779                    || s.element_type.contains_constraint_reference()
780            }
781            ASN1Type::ElsewhereDeclaredType(e) => {
782                e.constraints.iter().any(|c| c.has_cross_reference())
783            }
784            _ => false,
785        }
786    }
787
788    pub fn references_class_by_name(&self) -> bool {
789        match self {
790            ASN1Type::Choice(c) => c.options.iter().any(|o| o.ty.references_class_by_name()),
791            ASN1Type::Sequence(s) => s.members.iter().any(|m| m.ty.references_class_by_name()),
792            ASN1Type::SequenceOf(so) => so.element_type.references_class_by_name(),
793            ASN1Type::InformationObjectFieldReference(io_ref) => {
794                matches!(
795                    io_ref.field_path.last(),
796                    Some(ObjectFieldIdentifier::SingleValue(_))
797                )
798            }
799            _ => false,
800        }
801    }
802
803    pub fn resolve_class_reference(self, tlds: &BTreeMap<String, ToplevelDefinition>) -> Self {
804        match self {
805            ASN1Type::Choice(c) => ASN1Type::Choice(Choice {
806                extensible: c.extensible,
807                options: c
808                    .options
809                    .into_iter()
810                    .map(|option| ChoiceOption {
811                        is_recursive: false,
812                        name: option.name,
813                        tag: option.tag,
814                        ty: option.ty.resolve_class_reference(tlds),
815                        constraints: vec![],
816                    })
817                    .collect(),
818                constraints: c.constraints,
819            }),
820            ASN1Type::Sequence(s) => ASN1Type::Sequence(SequenceOrSet {
821                extensible: s.extensible,
822                constraints: s.constraints,
823                components_of: s.components_of,
824                members: s
825                    .members
826                    .into_iter()
827                    .map(|mut member| {
828                        member.constraints = vec![];
829                        member.ty = member.ty.resolve_class_reference(tlds);
830                        member
831                    })
832                    .collect(),
833            }),
834            ASN1Type::InformationObjectFieldReference(_) => self.reassign_type_for_ref(tlds),
835            _ => self,
836        }
837    }
838
839    fn reassign_type_for_ref(mut self, tlds: &BTreeMap<String, ToplevelDefinition>) -> Self {
840        if let Self::InformationObjectFieldReference(ref ior) = self {
841            if let Some(t) = tlds
842                .iter()
843                .find_map(|(_, c)| {
844                    c.is_class_with_name(&ior.class)
845                        .map(|clazz| clazz.get_field(&ior.field_path))
846                })
847                .flatten()
848                .and_then(|class_field| class_field.ty.clone())
849            {
850                self = t;
851            }
852        }
853        self
854    }
855
856    pub fn link_subtype_constraint(
857        &mut self,
858        tlds: &BTreeMap<String, ToplevelDefinition>,
859    ) -> Result<(), GrammarError> {
860        if let Self::ElsewhereDeclaredType(e) = self {
861            if let Some(ToplevelDefinition::Type(t)) = tlds.get(&e.identifier) {
862                *self = t.ty.clone();
863            }
864        }
865        Ok(())
866    }
867}
868
869impl ASN1Value {
870    pub fn link_with_type(
871        &mut self,
872        tlds: &BTreeMap<String, ToplevelDefinition>,
873        ty: &ASN1Type,
874        type_name: Option<&String>,
875    ) -> Result<(), GrammarError> {
876        #[allow(clippy::useless_asref)] // false positive
877        match (ty, self.as_mut()) {
878            (
879                ASN1Type::ElsewhereDeclaredType(e),
880                ASN1Value::LinkedNestedValue { supertypes, value },
881            ) => {
882                supertypes.push(e.identifier.clone());
883                if let ASN1Value::LinkedIntValue { integer_type, .. } = value.borrow_mut() {
884                    let int_type = e.constraints.iter().fold(IntegerType::Unbounded, |acc, c| {
885                        c.integer_constraints().max_restrictive(acc)
886                    });
887                    *integer_type = int_type;
888                }
889                if let Some(ToplevelDefinition::Type(t)) = tlds.get(&e.identifier) {
890                    self.link_with_type(tlds, &t.ty, Some(&t.name))
891                } else {
892                    Err(grammar_error!(
893                        LinkerError,
894                        "Failed to link value with '{}'",
895                        e.identifier
896                    ))
897                }
898            }
899            (
900                ASN1Type::ElsewhereDeclaredType(e),
901                ASN1Value::ElsewhereDeclaredValue { identifier, parent },
902            ) => {
903                if let Some(value) = Self::link_enum_or_distinguished(
904                    tlds,
905                    e,
906                    identifier,
907                    vec![e.identifier.clone()],
908                )? {
909                    *self = value;
910                    return Ok(());
911                } else if let Some((ToplevelDefinition::Type(ty), ToplevelDefinition::Value(val))) =
912                    tlds.get(&e.identifier).zip(tlds.get(identifier))
913                {
914                    if ty.name != val.associated_type.as_str() {
915                        // When it comes to `DEFAULT` values, the ASN.1 type system
916                        // is more lenient than Rust's. For example, the it is acceptable
917                        // to pass `int-value` as a `DEFAULT` value for `Int-Like-Type` in
918                        // the following example:
919                        // ```ignore
920                        // int-value INTEGER ::= 600
921                        // Int-Like-Type ::= INTEGER (1..605)
922                        // Sequence-With-Defaults ::= SEQUENCE {
923                        //     numeric Int-Like-Type DEFAULT int-value
924                        // }
925                        // ```
926                        // Cases like these need to be explicitly cast in the rust bindings.
927                        *self = val.clone().value;
928                        self.link_with_type(
929                            tlds,
930                            &ASN1Type::ElsewhereDeclaredType(e.clone()),
931                            None,
932                        )?;
933                        return Ok(());
934                    }
935                }
936                *self = ASN1Value::LinkedElsewhereDefinedValue {
937                    parent: parent.clone(),
938                    identifier: identifier.clone(),
939                    can_be_const: e.root(tlds)?.is_const_type(),
940                };
941                Ok(())
942            }
943            (ASN1Type::ElsewhereDeclaredType(e), val) => {
944                *self = ASN1Value::LinkedNestedValue {
945                    supertypes: vec![e.identifier.clone()],
946                    value: Box::new((*val).clone()),
947                };
948                if let Some(ToplevelDefinition::Type(t)) = tlds.get(&e.identifier) {
949                    self.link_with_type(tlds, &t.ty, Some(&t.name))
950                } else {
951                    Err(grammar_error!(
952                        LinkerError,
953                        "Failed to link value with '{}'",
954                        e.identifier
955                    ))
956                }
957            }
958            (
959                ASN1Type::Choice(c),
960                ASN1Value::Choice {
961                    type_name: tn,
962                    variant_name,
963                    inner_value,
964                },
965            ) => {
966                if let Some(option) = c.options.iter().find(|o| &o.name == variant_name) {
967                    *tn = type_name.cloned();
968                    inner_value.link_with_type(
969                        tlds,
970                        &option.ty,
971                        Some(&option.ty.as_str().into_owned()),
972                    )
973                } else {
974                    Err(grammar_error!(
975                        LinkerError,
976                        "Failed to link value with '{}'",
977                        variant_name
978                    ))
979                }
980            }
981            (ASN1Type::Choice(c), ASN1Value::LinkedNestedValue { supertypes, value })
982                if matches![**value, ASN1Value::Choice { .. }] =>
983            {
984                let enum_name = supertypes.pop();
985                if let ASN1Value::Choice {
986                    type_name,
987                    variant_name,
988                    inner_value,
989                } = &mut **value
990                {
991                    if let Some(option) = c.options.iter().find(|o| &o.name == variant_name) {
992                        *type_name = enum_name;
993                        inner_value.link_with_type(
994                            tlds,
995                            &option.ty,
996                            Some(&option.ty.as_str().into_owned()),
997                        )
998                    } else {
999                        Err(grammar_error!(
1000                            LinkerError,
1001                            "Failed to link value with '{}'",
1002                            variant_name
1003                        ))
1004                    }
1005                } else {
1006                    Ok(())
1007                }
1008            }
1009            (ASN1Type::Set(s), ASN1Value::SequenceOrSet(val))
1010            | (ASN1Type::Sequence(s), ASN1Value::SequenceOrSet(val)) => {
1011                *self = Self::link_struct_like(val, s, tlds, type_name)?;
1012                Ok(())
1013            }
1014            (ASN1Type::Set(s), ASN1Value::LinkedNestedValue { value, .. })
1015            | (ASN1Type::Sequence(s), ASN1Value::LinkedNestedValue { value, .. })
1016                if matches![**value, ASN1Value::SequenceOrSet(_)] =>
1017            {
1018                if let ASN1Value::SequenceOrSet(val) = &mut **value {
1019                    *value = Box::new(Self::link_struct_like(val, s, tlds, type_name)?);
1020                }
1021                Ok(())
1022            }
1023            (ASN1Type::SetOf(s), ASN1Value::SequenceOrSet(val))
1024            | (ASN1Type::SequenceOf(s), ASN1Value::SequenceOrSet(val)) => {
1025                *self = Self::link_array_like(val, s, tlds)?;
1026                Ok(())
1027            }
1028            (ASN1Type::SetOf(s), ASN1Value::LinkedNestedValue { value, .. })
1029            | (ASN1Type::SequenceOf(s), ASN1Value::LinkedNestedValue { value, .. })
1030                if matches![**value, ASN1Value::SequenceOrSet(_)] =>
1031            {
1032                if let ASN1Value::SequenceOrSet(val) = &mut **value {
1033                    *value = Box::new(Self::link_array_like(val, s, tlds)?);
1034                }
1035                Ok(())
1036            }
1037            (ASN1Type::Integer(i), ASN1Value::Integer(val)) => {
1038                *self = ASN1Value::LinkedIntValue {
1039                    integer_type: i.int_type(),
1040                    value: *val,
1041                };
1042                Ok(())
1043            }
1044            (ASN1Type::CharacterString(t), ASN1Value::String(s)) => {
1045                *self = ASN1Value::LinkedCharStringValue(t.ty, s.clone());
1046                Ok(())
1047            }
1048            (ASN1Type::CharacterString(t), ASN1Value::LinkedNestedValue { value, .. })
1049                if matches![**value, ASN1Value::String(_)] =>
1050            {
1051                if let ASN1Value::String(s) = &**value {
1052                    *value = Box::new(ASN1Value::LinkedCharStringValue(t.ty, s.clone()));
1053                }
1054                Ok(())
1055            }
1056            (ASN1Type::BitString(_), ASN1Value::OctetString(o)) => {
1057                *self = ASN1Value::BitString(octet_string_to_bit_string(o));
1058                Ok(())
1059            }
1060            (
1061                ASN1Type::BitString(BitString {
1062                    distinguished_values: Some(_),
1063                    ..
1064                }),
1065                ASN1Value::SequenceOrSet(o),
1066            ) => {
1067                *self = ASN1Value::BitStringNamedBits(
1068                    o.iter()
1069                        .filter_map(|(_, v)| match &**v {
1070                            ASN1Value::ElsewhereDeclaredValue { identifier, .. } => {
1071                                Some(identifier.clone())
1072                            }
1073                            ASN1Value::EnumeratedValue { enumerable, .. } => {
1074                                Some(enumerable.clone())
1075                            }
1076                            _ => None,
1077                        })
1078                        .collect(),
1079                );
1080                self.link_with_type(tlds, ty, type_name)
1081            }
1082            (
1083                ASN1Type::BitString(BitString {
1084                    distinguished_values: Some(_),
1085                    ..
1086                }),
1087                ASN1Value::LinkedNestedValue { value, .. },
1088            ) if matches![**value, ASN1Value::SequenceOrSet(_)] => {
1089                if let ASN1Value::SequenceOrSet(o) = &**value {
1090                    *value = Box::new(ASN1Value::BitStringNamedBits(
1091                        o.iter()
1092                            .filter_map(|(_, v)| match &**v {
1093                                ASN1Value::ElsewhereDeclaredValue { identifier, .. } => {
1094                                    Some(identifier.clone())
1095                                }
1096                                ASN1Value::EnumeratedValue { enumerable, .. } => {
1097                                    Some(enumerable.clone())
1098                                }
1099                                _ => None,
1100                            })
1101                            .collect(),
1102                    ));
1103                    self.link_with_type(tlds, ty, type_name)?;
1104                }
1105                Ok(())
1106            }
1107            (
1108                ASN1Type::BitString(BitString {
1109                    distinguished_values: Some(_),
1110                    ..
1111                }),
1112                ASN1Value::ObjectIdentifier(o),
1113            ) => {
1114                *self = ASN1Value::BitStringNamedBits(
1115                    o.0.iter().filter_map(|arc| arc.name.clone()).collect(),
1116                );
1117                self.link_with_type(tlds, ty, type_name)
1118            }
1119            (
1120                ASN1Type::BitString(BitString {
1121                    distinguished_values: Some(_),
1122                    ..
1123                }),
1124                ASN1Value::LinkedNestedValue { value, .. },
1125            ) if matches![**value, ASN1Value::ObjectIdentifier(_)] => {
1126                if let ASN1Value::ObjectIdentifier(o) = &**value {
1127                    *value = Box::new(ASN1Value::BitStringNamedBits(
1128                        o.0.iter().filter_map(|arc| arc.name.clone()).collect(),
1129                    ));
1130                    self.link_with_type(tlds, ty, type_name)?;
1131                }
1132                Ok(())
1133            }
1134            (
1135                ASN1Type::BitString(BitString {
1136                    distinguished_values: Some(distinguished),
1137                    ..
1138                }),
1139                ASN1Value::BitStringNamedBits(o),
1140            ) => {
1141                if let Some(highest_distinguished_bit) = distinguished.iter().map(|d| d.value).max()
1142                {
1143                    *self = ASN1Value::BitString(bit_string_value_from_named_bits(
1144                        highest_distinguished_bit,
1145                        o,
1146                        distinguished,
1147                    ));
1148                    Ok(())
1149                } else {
1150                    Err(GrammarError {
1151                        details: format!("Failed to resolve BIT STRING value {o:?}"),
1152                        kind: GrammarErrorType::LinkerError,
1153                        pdu: None,
1154                    })
1155                }
1156            }
1157            (
1158                ASN1Type::BitString(BitString {
1159                    distinguished_values: Some(distinguished),
1160                    ..
1161                }),
1162                ASN1Value::LinkedNestedValue { value, .. },
1163            ) if matches![**value, ASN1Value::BitStringNamedBits(_)] => {
1164                if let (ASN1Value::BitStringNamedBits(o), Some(highest_distinguished_bit)) =
1165                    (&**value, distinguished.iter().map(|d| d.value).max())
1166                {
1167                    *value = Box::new(ASN1Value::BitString(bit_string_value_from_named_bits(
1168                        highest_distinguished_bit,
1169                        o,
1170                        distinguished,
1171                    )));
1172                    Ok(())
1173                } else {
1174                    Err(GrammarError {
1175                        details: format!("Failed to resolve BIT STRING value {value:?}"),
1176                        kind: GrammarErrorType::LinkerError,
1177                        pdu: None,
1178                    })
1179                }
1180            }
1181            (ASN1Type::BitString(_), ASN1Value::LinkedNestedValue { value, .. })
1182                if matches![**value, ASN1Value::OctetString(_)] =>
1183            {
1184                if let ASN1Value::OctetString(o) = &**value {
1185                    *value = Box::new(ASN1Value::BitString(octet_string_to_bit_string(o)));
1186                }
1187                Ok(())
1188            }
1189            (ASN1Type::OctetString(_), ASN1Value::BitString(b)) => {
1190                *self = ASN1Value::OctetString(bit_string_to_octet_string(b)?);
1191                Ok(())
1192            }
1193            (ASN1Type::OctetString(_), ASN1Value::LinkedNestedValue { value, .. })
1194                if matches![**value, ASN1Value::BitString(_)] =>
1195            {
1196                if let ASN1Value::BitString(b) = &**value {
1197                    *value = Box::new(ASN1Value::OctetString(bit_string_to_octet_string(b)?));
1198                }
1199                Ok(())
1200            }
1201            (ASN1Type::Integer(i), ASN1Value::LinkedIntValue { integer_type, .. }) => {
1202                let int_type = i.int_type().max_restrictive(*integer_type);
1203                *integer_type = int_type;
1204                Ok(())
1205            }
1206            (ASN1Type::Integer(i), ASN1Value::LinkedNestedValue { value, .. })
1207                if matches![**value, ASN1Value::ElsewhereDeclaredValue { .. }] =>
1208            {
1209                if let ASN1Value::ElsewhereDeclaredValue { identifier, .. } = &**value {
1210                    if let Some(distinguished_value) =
1211                        i.distinguished_values.as_ref().and_then(|dist_vals| {
1212                            dist_vals
1213                                .iter()
1214                                .find_map(|d| (&d.name == identifier).then_some(d.value))
1215                        })
1216                    {
1217                        *value = Box::new(ASN1Value::LinkedIntValue {
1218                            integer_type: i.int_type(),
1219                            value: distinguished_value,
1220                        });
1221                    }
1222                }
1223                Ok(())
1224            }
1225            (ASN1Type::Integer(i), ASN1Value::LinkedNestedValue { value, .. })
1226                if matches![**value, ASN1Value::Integer(_)] =>
1227            {
1228                if let ASN1Value::Integer(v) = &**value {
1229                    let int_type = i.constraints.iter().fold(IntegerType::Unbounded, |acc, c| {
1230                        c.integer_constraints().max_restrictive(acc)
1231                    });
1232                    *value = Box::new(ASN1Value::LinkedIntValue {
1233                        integer_type: int_type,
1234                        value: *v,
1235                    });
1236                }
1237                Ok(())
1238            }
1239            (ASN1Type::Integer(i), ASN1Value::ElsewhereDeclaredValue { identifier, .. }) => {
1240                if let Some(value) = i.distinguished_values.as_ref().and_then(|dist_vals| {
1241                    dist_vals
1242                        .iter()
1243                        .find_map(|d| (&d.name == identifier).then_some(d.value))
1244                }) {
1245                    *self = ASN1Value::LinkedIntValue {
1246                        integer_type: i.int_type(),
1247                        value,
1248                    };
1249                }
1250                Ok(())
1251            }
1252            (ASN1Type::Enumerated(_), ASN1Value::LinkedNestedValue { value, .. })
1253                if matches![**value, ASN1Value::ElsewhereDeclaredValue { .. }] =>
1254            {
1255                if let ASN1Value::ElsewhereDeclaredValue { identifier, .. } = &**value {
1256                    if let Some((_, tld)) = tlds
1257                        .iter()
1258                        .find(|(_, tld)| tld.has_enum_value(None, identifier))
1259                    {
1260                        *value = Box::new(ASN1Value::EnumeratedValue {
1261                            enumerated: tld.name().clone(),
1262                            enumerable: identifier.clone(),
1263                        });
1264                    }
1265                }
1266                Ok(())
1267            }
1268            (ASN1Type::Enumerated(_), ASN1Value::ElsewhereDeclaredValue { identifier, .. }) => {
1269                if let Some((_, tld)) = tlds
1270                    .iter()
1271                    .find(|(_, tld)| tld.has_enum_value(None, identifier))
1272                {
1273                    *self = ASN1Value::EnumeratedValue {
1274                        enumerated: tld.name().clone(),
1275                        enumerable: identifier.clone(),
1276                    };
1277                }
1278                Ok(())
1279            }
1280            (
1281                _,
1282                ASN1Value::ElsewhereDeclaredValue {
1283                    parent: None,
1284                    identifier,
1285                },
1286            ) => {
1287                if let Some(ToplevelDefinition::Value(tld)) = tlds.get(identifier) {
1288                    *self = tld.value.clone();
1289                    self.link_with_type(tlds, ty, type_name)?;
1290                }
1291                Ok(())
1292            }
1293            (_, ASN1Value::ElsewhereDeclaredValue { .. }) => Err(GrammarError::todo()),
1294            _ => Ok(()),
1295        }
1296    }
1297
1298    fn link_enum_or_distinguished(
1299        tlds: &BTreeMap<String, ToplevelDefinition>,
1300        e: &DeclarationElsewhere,
1301        identifier: &mut String,
1302        mut supertypes: Vec<String>,
1303    ) -> Result<Option<ASN1Value>, GrammarError> {
1304        match tlds.get(&e.identifier) {
1305            Some(ToplevelDefinition::Type(ToplevelTypeDefinition {
1306                ty: ASN1Type::Enumerated(enumerated),
1307                ..
1308            })) => {
1309                if enumerated
1310                    .members
1311                    .iter()
1312                    .any(|enumeral| &enumeral.name == identifier)
1313                {
1314                    Ok(Some(ASN1Value::EnumeratedValue {
1315                        enumerated: e.identifier.clone(),
1316                        enumerable: identifier.clone(),
1317                    }))
1318                } else {
1319                    Ok(None)
1320                }
1321            }
1322            Some(ToplevelDefinition::Type(ToplevelTypeDefinition {
1323                ty:
1324                    ASN1Type::Integer(Integer {
1325                        distinguished_values: Some(distinguished),
1326                        constraints,
1327                    }),
1328                ..
1329            })) => {
1330                if let Some(distinguished_value) =
1331                    distinguished.iter().find(|d| &d.name == identifier)
1332                {
1333                    Ok(Some(ASN1Value::LinkedNestedValue {
1334                        supertypes,
1335                        value: Box::new(ASN1Value::LinkedIntValue {
1336                            integer_type: constraints
1337                                .iter()
1338                                .fold(IntegerType::Unbounded, |acc, c| {
1339                                    c.integer_constraints().max_restrictive(acc)
1340                                }),
1341                            value: distinguished_value.value,
1342                        }),
1343                    }))
1344                } else {
1345                    Ok(None)
1346                }
1347            }
1348            Some(ToplevelDefinition::Type(ToplevelTypeDefinition {
1349                ty: ASN1Type::ElsewhereDeclaredType(elsewhere),
1350                ..
1351            })) => {
1352                supertypes.push(elsewhere.identifier.clone());
1353                Self::link_enum_or_distinguished(tlds, elsewhere, identifier, supertypes)
1354            }
1355            _ => Ok(None),
1356        }
1357    }
1358
1359    fn link_array_like(
1360        val: &mut [(Option<String>, Box<ASN1Value>)],
1361        s: &SequenceOrSetOf,
1362        tlds: &BTreeMap<String, ToplevelDefinition>,
1363    ) -> Result<ASN1Value, GrammarError> {
1364        let _ = val.iter_mut().try_for_each(|v| {
1365            v.1.link_with_type(
1366                tlds,
1367                &s.element_type,
1368                Some(&s.element_type.as_str().into_owned()),
1369            )
1370        });
1371        Ok(ASN1Value::LinkedArrayLikeValue(
1372            val.iter().map(|v| v.1.clone()).collect(),
1373        ))
1374    }
1375
1376    fn link_struct_like(
1377        val: &mut [(Option<String>, Box<ASN1Value>)],
1378        s: &SequenceOrSet,
1379        tlds: &BTreeMap<String, ToplevelDefinition>,
1380        type_name: Option<&String>,
1381    ) -> Result<ASN1Value, GrammarError> {
1382        val.iter_mut().try_for_each(|v| {
1383            if let Some(member) = s.members.iter().find(|m| Some(&m.name) == v.0.as_ref()) {
1384                let type_name = match (member.ty.is_builtin_type(), type_name) {
1385                    (true, Some(parent)) => Some(
1386                        INTERNAL_NESTED_TYPE_NAME_PREFIX.to_owned() + &member.name + "$" + parent,
1387                    ),
1388                    (false, _) => Some(member.ty.as_str().into_owned()),
1389                    _ => {
1390                        return Err(grammar_error!(
1391                            LinkerError,
1392                            "Failed to determine parent name of field {}",
1393                            member.name
1394                        ))
1395                    }
1396                };
1397                v.1.link_with_type(tlds, &member.ty, type_name.as_ref())
1398            } else {
1399                Err(grammar_error!(
1400                    LinkerError,
1401                    "Failed to link value with '{:?}'",
1402                    v.0
1403                ))
1404            }
1405        })?;
1406
1407        s.members
1408            .iter()
1409            .map(|member| {
1410                val.iter()
1411                    .find_map(|(name, value)| {
1412                        (name.as_ref() == Some(&member.name))
1413                            .then_some(StructLikeFieldValue::Explicit(value.clone()))
1414                    })
1415                    .or(member
1416                        .default_value
1417                        .as_ref()
1418                        .map(|d| StructLikeFieldValue::Implicit(Box::new(d.clone()))))
1419                    .ok_or_else(|| {
1420                        grammar_error!(LinkerError, "No value for field {} found!", member.name)
1421                    })
1422                    .map(|field_value| (member.name.clone(), member.ty.clone(), field_value))
1423            })
1424            .collect::<Result<Vec<_>, _>>()
1425            .map(ASN1Value::LinkedStructLikeValue)
1426    }
1427
1428    pub fn is_elsewhere_declared(&self) -> bool {
1429        let is = matches!(
1430            self,
1431            Self::ElsewhereDeclaredValue { .. }
1432                | Self::EnumeratedValue {
1433                    enumerated: _,
1434                    enumerable: _,
1435                }
1436        );
1437        is
1438    }
1439
1440    /// Tries to resolve an `ElsewhereDeclaredValue` that references a
1441    /// path instead of a simple top-level declaration.
1442    /// ### Example
1443    /// From X501 LDAP System Schema
1444    /// ```ignore
1445    /// namingContexts ATTRIBUTE ::= {
1446    ///     WITH SYNTAX              DistinguishedName
1447    ///     USAGE                    dSAOperation
1448    ///     LDAP-SYNTAX              dn.&id
1449    ///     LDAP-NAME                {"namingContexts"}
1450    ///     ID                       id-lat-namingContexts
1451    /// }
1452    /// ```
1453    /// The `LDAP-SYNTAX` field refers to a field ob an information object `dn`.
1454    pub fn resolve_elsewhere_with_parent(
1455        &mut self,
1456        tlds: &BTreeMap<String, ToplevelDefinition>,
1457    ) -> Result<(), GrammarError> {
1458        if let Self::ElsewhereDeclaredValue {
1459            parent: Some(object_name),
1460            identifier,
1461        } = self
1462        {
1463            if object_name.contains('.') {
1464                return Err(grammar_error!(NotYetInplemented, "Value references of path length > 2 are not yet supported! Found reference {object_name}.{identifier}"));
1465            }
1466            let object = get_declaration![
1467                tlds,
1468                object_name,
1469                Information,
1470                ASN1Information::Object
1471            ]
1472            .ok_or_else(|| grammar_error!(LinkerError, "No information object found for identifier {object_name}, parent of {identifier}"))?;
1473            match &object.fields {
1474                InformationObjectFields::DefaultSyntax(d) => {
1475                    match d.iter().find(|elem| elem.identifier() == identifier) {
1476                        Some(InformationObjectField::FixedValueField(FixedValueField { value, .. })) => {
1477                            *self = value.clone();
1478                            return Ok(())
1479                        }
1480                        _ => return Err(grammar_error!(
1481                            LinkerError,
1482                                "No matching value field for identifier {identifier} found in object {object_name}"
1483                        ))
1484                    }
1485                }
1486                InformationObjectFields::CustomSyntax(c) => {
1487                    let class_name = &object.class_name;
1488                    let class = get_declaration![
1489                        tlds,
1490                        class_name,
1491                        Information,
1492                        ASN1Information::ObjectClass
1493                    ]
1494                    .ok_or_else(|| {
1495                        grammar_error!(
1496                            LinkerError,
1497                            "No information object class found for identifier {class_name}"
1498                        )
1499                    })?;
1500                    let syntax = class.syntax.as_ref().ok_or_else(|| {
1501                        grammar_error!(LinkerError, "No syntax info found for class {class_name}")
1502                    })?;
1503                    let tokens = syntax.flatten();
1504                    let (mut before, mut after) = (None, None);
1505                    'iter_syntax: for i in 0..tokens.len() {
1506                        let expr = tokens.get(i);
1507                        match expr {
1508                            Some((
1509                                _,
1510                                SyntaxToken::Field(ObjectFieldIdentifier::SingleValue(id)),
1511                            )) if id == identifier => {
1512                                before = tokens.get(i - 1).map(|(_, token)| token);
1513                                after = tokens.get(i + 1).map(|(_, token)| token);
1514                                break 'iter_syntax;
1515                            }
1516                            _ => {}
1517                        };
1518                    }
1519                    for i in 0..c.len() {
1520                        if let Some(SyntaxApplication::ValueReference(val)) = c.get(i) {
1521                            match (c.get(i - 1), before, c.get(i + 1), after) {
1522                                (Some(a), Some(b), _, _) if a.matches(b, &tokens, i) => {
1523                                    *self = val.clone();
1524                                    return Ok(());
1525                                }
1526                                (_, _, Some(c), Some(d)) if c.matches(d, &tokens, i) => {
1527                                    *self = val.clone();
1528                                    return Ok(());
1529                                }
1530                                _ => {}
1531                            };
1532                        }
1533                    }
1534                    return Err(grammar_error!(
1535                        LinkerError,
1536                        "Failed to match expression to syntax of class {class_name}"
1537                    ));
1538                }
1539            }
1540        }
1541        Ok(())
1542    }
1543
1544    pub fn link_elsewhere_declared(
1545        &mut self,
1546        identifier: &String,
1547        tlds: &BTreeMap<String, ToplevelDefinition>,
1548    ) -> Result<(), GrammarError> {
1549        match self {
1550            Self::ElsewhereDeclaredValue {
1551                parent: Some(_), ..
1552            } => {
1553                return self.resolve_elsewhere_with_parent(tlds);
1554            }
1555            Self::ElsewhereDeclaredValue {
1556                identifier: e,
1557                parent: _,
1558            }
1559            | Self::EnumeratedValue {
1560                enumerated: _,
1561                enumerable: e,
1562            } => {
1563                if let Some(v) = find_tld_or_enum_value_by_name(identifier, e, tlds) {
1564                    *self = v;
1565                }
1566            }
1567            _ => {}
1568        }
1569        Ok(())
1570    }
1571}
1572
1573fn bit_string_value_from_named_bits(
1574    highest_distinguished_bit: i128,
1575    named_bits: &[String],
1576    distinguished: &[DistinguishedValue],
1577) -> Vec<bool> {
1578    (0..=highest_distinguished_bit)
1579        .map(|i| {
1580            named_bits.iter().any(|bit| {
1581                Some(bit)
1582                    == distinguished
1583                        .iter()
1584                        .find_map(|d| (d.value == i).then_some(&d.name))
1585            })
1586        })
1587        .collect()
1588}
1589
1590#[cfg(test)]
1591mod tests {
1592    use std::collections::BTreeMap;
1593
1594    use crate::intermediate::{types::*, *};
1595
1596    macro_rules! tld {
1597        ($name:literal, $ty:expr) => {
1598            ToplevelTypeDefinition {
1599                comments: String::new(),
1600                tag: None,
1601                index: None,
1602                name: $name.into(),
1603                ty: $ty,
1604                parameterization: None,
1605            }
1606        };
1607    }
1608
1609    #[test]
1610    fn links_asn1_value() {
1611        let tlds: BTreeMap<String, ToplevelDefinition> = {
1612            let mut map = BTreeMap::new();
1613            map.insert(
1614                "RootBool".into(),
1615                ToplevelDefinition::Type(tld!(
1616                    "RootBool",
1617                    ASN1Type::Boolean(Boolean {
1618                        constraints: vec![]
1619                    })
1620                )),
1621            );
1622            map.insert(
1623                "IntermediateBool".into(),
1624                ToplevelDefinition::Type(tld!(
1625                    "IntermediateBool",
1626                    ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1627                        parent: None,
1628                        identifier: String::from("RootBool"),
1629                        constraints: vec![]
1630                    })
1631                )),
1632            );
1633            map.insert(
1634                "BaseChoice".into(),
1635                ToplevelDefinition::Type(tld!(
1636                    "BaseChoice",
1637                    ASN1Type::Choice(Choice {
1638                        extensible: None,
1639                        constraints: vec![],
1640                        options: vec![ChoiceOption {
1641                            is_recursive: false,
1642                            name: String::from("first"),
1643                            constraints: vec![],
1644                            tag: None,
1645                            ty: ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1646                                parent: None,
1647                                identifier: String::from("IntermediateBool"),
1648                                constraints: vec![]
1649                            })
1650                        }]
1651                    })
1652                )),
1653            );
1654            map
1655        };
1656        let mut example_value = ToplevelValueDefinition {
1657            comments: String::new(),
1658            name: "exampleValue".into(),
1659            parameterization: None,
1660            associated_type: ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1661                parent: None,
1662                identifier: "BaseChoice".into(),
1663                constraints: vec![],
1664            }),
1665            index: None,
1666            value: ASN1Value::Choice {
1667                type_name: None,
1668                variant_name: "first".into(),
1669                inner_value: Box::new(ASN1Value::Boolean(true)),
1670            },
1671        };
1672        example_value.collect_supertypes(&tlds).unwrap();
1673        assert_eq!(
1674            example_value,
1675            ToplevelValueDefinition {
1676                comments: "".into(),
1677                name: "exampleValue".into(),
1678                associated_type: ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1679                    parent: None,
1680                    identifier: "BaseChoice".into(),
1681                    constraints: vec![]
1682                }),
1683                parameterization: None,
1684                value: ASN1Value::Choice {
1685                    type_name: Some("BaseChoice".into()),
1686                    variant_name: "first".into(),
1687                    inner_value: Box::new(ASN1Value::LinkedNestedValue {
1688                        supertypes: vec!["IntermediateBool".into(), "RootBool".into()],
1689                        value: Box::new(ASN1Value::Boolean(true))
1690                    })
1691                },
1692                index: None
1693            }
1694        )
1695    }
1696}