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