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