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 = Box::new(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 { identifier, parent },
907            ) => {
908                if let Some(value) = Self::link_enum_or_distinguished(
909                    tlds,
910                    e,
911                    identifier,
912                    vec![e.identifier.clone()],
913                )? {
914                    *self = value;
915                    return Ok(());
916                } else if let Some((ToplevelDefinition::Type(ty), ToplevelDefinition::Value(val))) =
917                    tlds.get(&e.identifier).zip(tlds.get(identifier))
918                {
919                    if ty.name != val.associated_type.as_str() {
920                        // When it comes to `DEFAULT` values, the ASN.1 type system
921                        // is more lenient than Rust's. For example, the it is acceptable
922                        // to pass `int-value` as a `DEFAULT` value for `Int-Like-Type` in
923                        // the following example:
924                        // ```ignore
925                        // int-value INTEGER ::= 600
926                        // Int-Like-Type ::= INTEGER (1..605)
927                        // Sequence-With-Defaults ::= SEQUENCE {
928                        //     numeric Int-Like-Type DEFAULT int-value
929                        // }
930                        // ```
931                        // Cases like these need to be explicitly cast in the rust bindings.
932                        *self = val.clone().value;
933                        self.link_with_type(
934                            tlds,
935                            &ASN1Type::ElsewhereDeclaredType(e.clone()),
936                            None,
937                        )?;
938                        return Ok(());
939                    }
940                }
941                *self = ASN1Value::LinkedElsewhereDefinedValue {
942                    parent: parent.clone(),
943                    identifier: identifier.clone(),
944                    can_be_const: e.root(tlds)?.is_const_type(),
945                };
946                Ok(())
947            }
948            (ASN1Type::ElsewhereDeclaredType(e), val) => {
949                *self = ASN1Value::LinkedNestedValue {
950                    supertypes: vec![e.identifier.clone()],
951                    value: Box::new((*val).clone()),
952                };
953                if let Some(ToplevelDefinition::Type(t)) = tlds.get(&e.identifier) {
954                    self.link_with_type(tlds, &t.ty, Some(&t.name))
955                } else {
956                    Err(grammar_error!(
957                        LinkerError,
958                        "Failed to link value with '{}'",
959                        e.identifier
960                    ))
961                }
962            }
963            (
964                ASN1Type::Choice(c),
965                ASN1Value::Choice {
966                    type_name: tn,
967                    variant_name,
968                    inner_value,
969                },
970            ) => {
971                if let Some(option) = c.options.iter().find(|o| &o.name == variant_name) {
972                    *tn = type_name.cloned();
973                    inner_value.link_with_type(
974                        tlds,
975                        &option.ty,
976                        Some(&option.ty.as_str().into_owned()),
977                    )
978                } else {
979                    Err(grammar_error!(
980                        LinkerError,
981                        "Failed to link value with '{}'",
982                        variant_name
983                    ))
984                }
985            }
986            (ASN1Type::Choice(c), ASN1Value::LinkedNestedValue { supertypes, value })
987                if matches![**value, ASN1Value::Choice { .. }] =>
988            {
989                let enum_name = supertypes.pop();
990                if let ASN1Value::Choice {
991                    type_name,
992                    variant_name,
993                    inner_value,
994                } = &mut **value
995                {
996                    if let Some(option) = c.options.iter().find(|o| &o.name == variant_name) {
997                        *type_name = enum_name;
998                        inner_value.link_with_type(
999                            tlds,
1000                            &option.ty,
1001                            Some(&option.ty.as_str().into_owned()),
1002                        )
1003                    } else {
1004                        Err(grammar_error!(
1005                            LinkerError,
1006                            "Failed to link value with '{}'",
1007                            variant_name
1008                        ))
1009                    }
1010                } else {
1011                    Ok(())
1012                }
1013            }
1014            (ASN1Type::SetOf(_), ASN1Value::ObjectIdentifier(val))
1015            | (ASN1Type::SequenceOf(_), ASN1Value::ObjectIdentifier(val))
1016            | (ASN1Type::Set(_), ASN1Value::ObjectIdentifier(val))
1017            | (ASN1Type::Sequence(_), ASN1Value::ObjectIdentifier(val)) => {
1018                // Object identifier values and sequence-like values cannot be properly distinguished
1019                let mut pseudo_arcs = std::mem::take(&mut val.0);
1020                let struct_value = pseudo_arcs
1021                    .chunks_mut(2)
1022                    .map(|chunk| {
1023                        let err = || GrammarError {
1024                            pdu: None,
1025                            details:
1026                                "Failed to interpret object identifier value as sequence value!"
1027                                    .into(),
1028                            kind: GrammarErrorType::LinkerError,
1029                        };
1030                        if let [id, val] = chunk {
1031                            val.number
1032                                .and_then(|n| <u128 as TryInto<i128>>::try_into(n).ok())
1033                                .ok_or_else(err)
1034                                .map(|number| {
1035                                    (id.name.take(), Box::new(ASN1Value::Integer(number)))
1036                                })
1037                        } else {
1038                            Err(err())
1039                        }
1040                    })
1041                    .collect::<Result<Vec<_>, _>>()?;
1042                *self = ASN1Value::SequenceOrSet(struct_value);
1043                self.link_with_type(tlds, ty, type_name)
1044            }
1045            (ASN1Type::Set(s), ASN1Value::SequenceOrSet(val))
1046            | (ASN1Type::Sequence(s), ASN1Value::SequenceOrSet(val)) => {
1047                *self = Self::link_struct_like(val, s, tlds, type_name)?;
1048                Ok(())
1049            }
1050            (ASN1Type::Set(s), ASN1Value::LinkedNestedValue { value, .. })
1051            | (ASN1Type::Sequence(s), ASN1Value::LinkedNestedValue { value, .. })
1052                if matches![**value, ASN1Value::SequenceOrSet(_)] =>
1053            {
1054                if let ASN1Value::SequenceOrSet(val) = &mut **value {
1055                    *value = Box::new(Self::link_struct_like(val, s, tlds, type_name)?);
1056                }
1057                Ok(())
1058            }
1059            (ASN1Type::SetOf(s), ASN1Value::SequenceOrSet(val))
1060            | (ASN1Type::SequenceOf(s), ASN1Value::SequenceOrSet(val)) => {
1061                *self = Self::link_array_like(val, s, tlds)?;
1062                Ok(())
1063            }
1064            (ASN1Type::SetOf(s), ASN1Value::LinkedNestedValue { value, .. })
1065            | (ASN1Type::SequenceOf(s), ASN1Value::LinkedNestedValue { value, .. })
1066                if matches![**value, ASN1Value::SequenceOrSet(_)] =>
1067            {
1068                if let ASN1Value::SequenceOrSet(val) = &mut **value {
1069                    *value = Box::new(Self::link_array_like(val, s, tlds)?);
1070                }
1071                Ok(())
1072            }
1073            (ASN1Type::Integer(i), ASN1Value::Integer(val)) => {
1074                *self = ASN1Value::LinkedIntValue {
1075                    integer_type: i.int_type(),
1076                    value: *val,
1077                };
1078                Ok(())
1079            }
1080            (ASN1Type::CharacterString(t), ASN1Value::String(s)) => {
1081                *self = ASN1Value::LinkedCharStringValue(t.ty, s.clone());
1082                Ok(())
1083            }
1084            (ASN1Type::CharacterString(t), ASN1Value::LinkedNestedValue { value, .. })
1085                if matches![**value, ASN1Value::String(_)] =>
1086            {
1087                if let ASN1Value::String(s) = &**value {
1088                    *value = Box::new(ASN1Value::LinkedCharStringValue(t.ty, s.clone()));
1089                }
1090                Ok(())
1091            }
1092            (ASN1Type::BitString(_), ASN1Value::OctetString(o)) => {
1093                *self = ASN1Value::BitString(octet_string_to_bit_string(o));
1094                Ok(())
1095            }
1096            (
1097                ASN1Type::BitString(BitString {
1098                    distinguished_values: Some(_),
1099                    ..
1100                }),
1101                ASN1Value::SequenceOrSet(o),
1102            ) => {
1103                *self = ASN1Value::BitStringNamedBits(
1104                    o.iter()
1105                        .filter_map(|(_, v)| match &**v {
1106                            ASN1Value::ElsewhereDeclaredValue { identifier, .. } => {
1107                                Some(identifier.clone())
1108                            }
1109                            ASN1Value::EnumeratedValue { enumerable, .. } => {
1110                                Some(enumerable.clone())
1111                            }
1112                            _ => None,
1113                        })
1114                        .collect(),
1115                );
1116                self.link_with_type(tlds, ty, type_name)
1117            }
1118            (
1119                ASN1Type::BitString(BitString {
1120                    distinguished_values: Some(_),
1121                    ..
1122                }),
1123                ASN1Value::LinkedNestedValue { value, .. },
1124            ) if matches![**value, ASN1Value::SequenceOrSet(_)] => {
1125                if let ASN1Value::SequenceOrSet(o) = &**value {
1126                    *value = Box::new(ASN1Value::BitStringNamedBits(
1127                        o.iter()
1128                            .filter_map(|(_, v)| match &**v {
1129                                ASN1Value::ElsewhereDeclaredValue { identifier, .. } => {
1130                                    Some(identifier.clone())
1131                                }
1132                                ASN1Value::EnumeratedValue { enumerable, .. } => {
1133                                    Some(enumerable.clone())
1134                                }
1135                                _ => None,
1136                            })
1137                            .collect(),
1138                    ));
1139                    self.link_with_type(tlds, ty, type_name)?;
1140                }
1141                Ok(())
1142            }
1143            (
1144                ASN1Type::BitString(BitString {
1145                    distinguished_values: Some(_),
1146                    ..
1147                }),
1148                ASN1Value::ObjectIdentifier(o),
1149            ) => {
1150                *self = ASN1Value::BitStringNamedBits(
1151                    o.0.iter().filter_map(|arc| arc.name.clone()).collect(),
1152                );
1153                self.link_with_type(tlds, ty, type_name)
1154            }
1155            (
1156                ASN1Type::BitString(BitString {
1157                    distinguished_values: Some(_),
1158                    ..
1159                }),
1160                ASN1Value::LinkedNestedValue { value, .. },
1161            ) if matches![**value, ASN1Value::ObjectIdentifier(_)] => {
1162                if let ASN1Value::ObjectIdentifier(o) = &**value {
1163                    *value = Box::new(ASN1Value::BitStringNamedBits(
1164                        o.0.iter().filter_map(|arc| arc.name.clone()).collect(),
1165                    ));
1166                    self.link_with_type(tlds, ty, type_name)?;
1167                }
1168                Ok(())
1169            }
1170            (
1171                ASN1Type::BitString(BitString {
1172                    distinguished_values: Some(distinguished),
1173                    ..
1174                }),
1175                ASN1Value::BitStringNamedBits(o),
1176            ) => {
1177                if let Some(highest_distinguished_bit) = distinguished.iter().map(|d| d.value).max()
1178                {
1179                    *self = ASN1Value::BitString(bit_string_value_from_named_bits(
1180                        highest_distinguished_bit,
1181                        o,
1182                        distinguished,
1183                    ));
1184                    Ok(())
1185                } else {
1186                    Err(GrammarError {
1187                        details: format!("Failed to resolve BIT STRING value {o:?}"),
1188                        kind: GrammarErrorType::LinkerError,
1189                        pdu: None,
1190                    })
1191                }
1192            }
1193            (
1194                ASN1Type::BitString(BitString {
1195                    distinguished_values: Some(distinguished),
1196                    ..
1197                }),
1198                ASN1Value::LinkedNestedValue { value, .. },
1199            ) if matches![**value, ASN1Value::BitStringNamedBits(_)] => {
1200                if let (ASN1Value::BitStringNamedBits(o), Some(highest_distinguished_bit)) =
1201                    (&**value, distinguished.iter().map(|d| d.value).max())
1202                {
1203                    *value = Box::new(ASN1Value::BitString(bit_string_value_from_named_bits(
1204                        highest_distinguished_bit,
1205                        o,
1206                        distinguished,
1207                    )));
1208                    Ok(())
1209                } else {
1210                    Err(GrammarError {
1211                        details: format!("Failed to resolve BIT STRING value {value:?}"),
1212                        kind: GrammarErrorType::LinkerError,
1213                        pdu: None,
1214                    })
1215                }
1216            }
1217            (ASN1Type::BitString(_), ASN1Value::LinkedNestedValue { value, .. })
1218                if matches![**value, ASN1Value::OctetString(_)] =>
1219            {
1220                if let ASN1Value::OctetString(o) = &**value {
1221                    *value = Box::new(ASN1Value::BitString(octet_string_to_bit_string(o)));
1222                }
1223                Ok(())
1224            }
1225            (ASN1Type::OctetString(_), ASN1Value::BitString(b)) => {
1226                *self = ASN1Value::OctetString(bit_string_to_octet_string(b)?);
1227                Ok(())
1228            }
1229            (ASN1Type::OctetString(_), ASN1Value::LinkedNestedValue { value, .. })
1230                if matches![**value, ASN1Value::BitString(_)] =>
1231            {
1232                if let ASN1Value::BitString(b) = &**value {
1233                    *value = Box::new(ASN1Value::OctetString(bit_string_to_octet_string(b)?));
1234                }
1235                Ok(())
1236            }
1237            (ASN1Type::Integer(i), ASN1Value::LinkedIntValue { integer_type, .. }) => {
1238                let int_type = i.int_type().max_restrictive(*integer_type);
1239                *integer_type = int_type;
1240                Ok(())
1241            }
1242            (ASN1Type::Integer(i), ASN1Value::LinkedNestedValue { value, .. })
1243                if matches![**value, ASN1Value::ElsewhereDeclaredValue { .. }] =>
1244            {
1245                if let ASN1Value::ElsewhereDeclaredValue { identifier, .. } = &**value {
1246                    if let Some(distinguished_value) =
1247                        i.distinguished_values.as_ref().and_then(|dist_vals| {
1248                            dist_vals
1249                                .iter()
1250                                .find_map(|d| (&d.name == identifier).then_some(d.value))
1251                        })
1252                    {
1253                        *value = Box::new(ASN1Value::LinkedIntValue {
1254                            integer_type: i.int_type(),
1255                            value: distinguished_value,
1256                        });
1257                    }
1258                }
1259                Ok(())
1260            }
1261            (ASN1Type::Integer(i), ASN1Value::LinkedNestedValue { value, .. })
1262                if matches![**value, ASN1Value::Integer(_)] =>
1263            {
1264                if let ASN1Value::Integer(v) = &**value {
1265                    let int_type = i.constraints.iter().fold(IntegerType::Unbounded, |acc, c| {
1266                        c.integer_constraints().max_restrictive(acc)
1267                    });
1268                    *value = Box::new(ASN1Value::LinkedIntValue {
1269                        integer_type: int_type,
1270                        value: *v,
1271                    });
1272                }
1273                Ok(())
1274            }
1275            (ASN1Type::Integer(i), ASN1Value::ElsewhereDeclaredValue { identifier, .. }) => {
1276                if let Some(value) = i.distinguished_values.as_ref().and_then(|dist_vals| {
1277                    dist_vals
1278                        .iter()
1279                        .find_map(|d| (&d.name == identifier).then_some(d.value))
1280                }) {
1281                    *self = ASN1Value::LinkedIntValue {
1282                        integer_type: i.int_type(),
1283                        value,
1284                    };
1285                }
1286                Ok(())
1287            }
1288            (ASN1Type::Enumerated(_), ASN1Value::LinkedNestedValue { value, .. })
1289                if matches![**value, ASN1Value::ElsewhereDeclaredValue { .. }] =>
1290            {
1291                if let ASN1Value::ElsewhereDeclaredValue { identifier, .. } = &**value {
1292                    if let Some((_, tld)) = tlds
1293                        .iter()
1294                        .find(|(_, tld)| tld.has_enum_value(None, identifier))
1295                    {
1296                        *value = Box::new(ASN1Value::EnumeratedValue {
1297                            enumerated: tld.name().clone(),
1298                            enumerable: identifier.clone(),
1299                        });
1300                    }
1301                }
1302                Ok(())
1303            }
1304            (ASN1Type::Enumerated(_), ASN1Value::ElsewhereDeclaredValue { identifier, .. }) => {
1305                if let Some((_, tld)) = tlds
1306                    .iter()
1307                    .find(|(_, tld)| tld.has_enum_value(None, identifier))
1308                {
1309                    *self = ASN1Value::EnumeratedValue {
1310                        enumerated: tld.name().clone(),
1311                        enumerable: identifier.clone(),
1312                    };
1313                }
1314                Ok(())
1315            }
1316            (
1317                _,
1318                ASN1Value::ElsewhereDeclaredValue {
1319                    parent: None,
1320                    identifier,
1321                },
1322            ) => {
1323                if let Some(ToplevelDefinition::Value(tld)) = tlds.get(identifier) {
1324                    *self = tld.value.clone();
1325                    self.link_with_type(tlds, ty, type_name)?;
1326                }
1327                Ok(())
1328            }
1329            (_, ASN1Value::ElsewhereDeclaredValue { .. }) => Err(GrammarError::todo()),
1330            _ => Ok(()),
1331        }
1332    }
1333
1334    fn link_enum_or_distinguished(
1335        tlds: &BTreeMap<String, ToplevelDefinition>,
1336        e: &DeclarationElsewhere,
1337        identifier: &mut String,
1338        mut supertypes: Vec<String>,
1339    ) -> Result<Option<ASN1Value>, GrammarError> {
1340        match tlds.get(&e.identifier) {
1341            Some(ToplevelDefinition::Type(ToplevelTypeDefinition {
1342                ty: ASN1Type::Enumerated(enumerated),
1343                ..
1344            })) => {
1345                if enumerated
1346                    .members
1347                    .iter()
1348                    .any(|enumeral| &enumeral.name == identifier)
1349                {
1350                    Ok(Some(ASN1Value::EnumeratedValue {
1351                        enumerated: e.identifier.clone(),
1352                        enumerable: identifier.clone(),
1353                    }))
1354                } else {
1355                    Ok(None)
1356                }
1357            }
1358            Some(ToplevelDefinition::Type(ToplevelTypeDefinition {
1359                ty:
1360                    ASN1Type::Integer(Integer {
1361                        distinguished_values: Some(distinguished),
1362                        constraints,
1363                    }),
1364                ..
1365            })) => {
1366                if let Some(distinguished_value) =
1367                    distinguished.iter().find(|d| &d.name == identifier)
1368                {
1369                    Ok(Some(ASN1Value::LinkedNestedValue {
1370                        supertypes,
1371                        value: Box::new(ASN1Value::LinkedIntValue {
1372                            integer_type: constraints
1373                                .iter()
1374                                .fold(IntegerType::Unbounded, |acc, c| {
1375                                    c.integer_constraints().max_restrictive(acc)
1376                                }),
1377                            value: distinguished_value.value,
1378                        }),
1379                    }))
1380                } else {
1381                    Ok(None)
1382                }
1383            }
1384            Some(ToplevelDefinition::Type(ToplevelTypeDefinition {
1385                ty: ASN1Type::ElsewhereDeclaredType(elsewhere),
1386                ..
1387            })) => {
1388                supertypes.push(elsewhere.identifier.clone());
1389                Self::link_enum_or_distinguished(tlds, elsewhere, identifier, supertypes)
1390            }
1391            _ => Ok(None),
1392        }
1393    }
1394
1395    fn link_array_like(
1396        val: &mut [(Option<String>, Box<ASN1Value>)],
1397        s: &SequenceOrSetOf,
1398        tlds: &BTreeMap<String, ToplevelDefinition>,
1399    ) -> Result<ASN1Value, GrammarError> {
1400        let _ = val.iter_mut().try_for_each(|v| {
1401            v.1.link_with_type(
1402                tlds,
1403                &s.element_type,
1404                Some(&s.element_type.as_str().into_owned()),
1405            )
1406        });
1407        Ok(ASN1Value::LinkedArrayLikeValue(
1408            val.iter().map(|v| v.1.clone()).collect(),
1409        ))
1410    }
1411
1412    fn link_struct_like(
1413        val: &mut [(Option<String>, Box<ASN1Value>)],
1414        s: &SequenceOrSet,
1415        tlds: &BTreeMap<String, ToplevelDefinition>,
1416        type_name: Option<&String>,
1417    ) -> Result<ASN1Value, GrammarError> {
1418        val.iter_mut().try_for_each(|v| {
1419            if let Some(member) = s.members.iter().find(|m| Some(&m.name) == v.0.as_ref()) {
1420                let type_name = match (member.ty.is_builtin_type(), type_name) {
1421                    (true, Some(parent)) => Some(
1422                        INTERNAL_NESTED_TYPE_NAME_PREFIX.to_owned() + &member.name + "$" + parent,
1423                    ),
1424                    (false, _) => Some(member.ty.as_str().into_owned()),
1425                    _ => {
1426                        return Err(grammar_error!(
1427                            LinkerError,
1428                            "Failed to determine parent name of field {}",
1429                            member.name
1430                        ))
1431                    }
1432                };
1433                v.1.link_with_type(tlds, &member.ty, type_name.as_ref())
1434            } else {
1435                Err(grammar_error!(
1436                    LinkerError,
1437                    "Failed to link value with '{:?}'",
1438                    v.0
1439                ))
1440            }
1441        })?;
1442
1443        s.members
1444            .iter()
1445            .map(|member| {
1446                val.iter()
1447                    .find_map(|(name, value)| {
1448                        (name.as_ref() == Some(&member.name))
1449                            .then_some(StructLikeFieldValue::Explicit(value.clone()))
1450                    })
1451                    .or(member
1452                        .optionality
1453                        .default()
1454                        .map(|d| StructLikeFieldValue::Implicit(Box::new(d.clone()))))
1455                    .ok_or_else(|| {
1456                        grammar_error!(LinkerError, "No value for field {} found!", member.name)
1457                    })
1458                    .map(|field_value| (member.name.clone(), member.ty.clone(), field_value))
1459            })
1460            .collect::<Result<Vec<_>, _>>()
1461            .map(ASN1Value::LinkedStructLikeValue)
1462    }
1463
1464    pub fn is_elsewhere_declared(&self) -> bool {
1465        let is = matches!(
1466            self,
1467            Self::ElsewhereDeclaredValue { .. }
1468                | Self::EnumeratedValue {
1469                    enumerated: _,
1470                    enumerable: _,
1471                }
1472        );
1473        is
1474    }
1475
1476    /// Tries to resolve an `ElsewhereDeclaredValue` that references a
1477    /// path instead of a simple top-level declaration.
1478    /// ### Example
1479    /// From X501 LDAP System Schema
1480    /// ```ignore
1481    /// namingContexts ATTRIBUTE ::= {
1482    ///     WITH SYNTAX              DistinguishedName
1483    ///     USAGE                    dSAOperation
1484    ///     LDAP-SYNTAX              dn.&id
1485    ///     LDAP-NAME                {"namingContexts"}
1486    ///     ID                       id-lat-namingContexts
1487    /// }
1488    /// ```
1489    /// The `LDAP-SYNTAX` field refers to a field ob an information object `dn`.
1490    pub fn resolve_elsewhere_with_parent(
1491        &mut self,
1492        tlds: &BTreeMap<String, ToplevelDefinition>,
1493    ) -> Result<(), GrammarError> {
1494        if let Self::ElsewhereDeclaredValue {
1495            parent: Some(object_name),
1496            identifier,
1497        } = self
1498        {
1499            if object_name.contains('.') {
1500                return Err(grammar_error!(NotYetInplemented, "Value references of path length > 2 are not yet supported! Found reference {object_name}.{identifier}"));
1501            }
1502            let object = get_declaration![
1503                tlds,
1504                object_name,
1505                Object,
1506                ASN1Information::Object
1507            ]
1508            .ok_or_else(|| grammar_error!(LinkerError, "No information object found for identifier {object_name}, parent of {identifier}"))?;
1509            match &object.fields {
1510                InformationObjectFields::DefaultSyntax(d) => {
1511                    match d.iter().find(|elem| elem.identifier() == identifier) {
1512                        Some(InformationObjectField::FixedValueField(FixedValueField { value, .. })) => {
1513                            *self = value.clone();
1514                            return Ok(())
1515                        }
1516                        _ => return Err(grammar_error!(
1517                            LinkerError,
1518                                "No matching value field for identifier {identifier} found in object {object_name}"
1519                        ))
1520                    }
1521                }
1522                InformationObjectFields::CustomSyntax(c) => {
1523                    let class_name = &object.class_name;
1524                    let Some(tld) = tlds.get(class_name) else {
1525                        return Err(grammar_error!(
1526                            LinkerError,
1527                            "No top level definition found for identifier {class_name}"
1528                        ));
1529                    };
1530                    let ToplevelDefinition::Class(class) = tld else {
1531                        return Err(grammar_error!(
1532                            LinkerError,
1533                            "Identifier {class_name} is not a CLASS definition"
1534                        ));
1535                    };
1536                    let syntax = class.definition.syntax.as_ref().ok_or_else(|| {
1537                        grammar_error!(LinkerError, "No syntax info found for class {class_name}")
1538                    })?;
1539                    let tokens = syntax.flatten();
1540                    let (mut before, mut after) = (None, None);
1541                    'iter_syntax: for i in 0..tokens.len() {
1542                        let expr = tokens.get(i);
1543                        match expr {
1544                            Some((
1545                                _,
1546                                SyntaxToken::Field(ObjectFieldIdentifier::SingleValue(id)),
1547                            )) if id == identifier => {
1548                                before = tokens.get(i - 1).map(|(_, token)| token);
1549                                after = tokens.get(i + 1).map(|(_, token)| token);
1550                                break 'iter_syntax;
1551                            }
1552                            _ => {}
1553                        };
1554                    }
1555                    for i in 0..c.len() {
1556                        if let Some(SyntaxApplication::ValueReference(val)) = c.get(i) {
1557                            match (c.get(i - 1), before, c.get(i + 1), after) {
1558                                (Some(a), Some(b), _, _) if a.matches(b, &tokens, i) => {
1559                                    *self = val.clone();
1560                                    return Ok(());
1561                                }
1562                                (_, _, Some(c), Some(d)) if c.matches(d, &tokens, i) => {
1563                                    *self = val.clone();
1564                                    return Ok(());
1565                                }
1566                                _ => {}
1567                            };
1568                        }
1569                    }
1570                    return Err(grammar_error!(
1571                        LinkerError,
1572                        "Failed to match expression to syntax of class {class_name}"
1573                    ));
1574                }
1575            }
1576        }
1577        Ok(())
1578    }
1579
1580    pub fn link_elsewhere_declared(
1581        &mut self,
1582        identifier: &String,
1583        tlds: &BTreeMap<String, ToplevelDefinition>,
1584    ) -> Result<(), GrammarError> {
1585        match self {
1586            Self::ElsewhereDeclaredValue {
1587                parent: Some(_), ..
1588            } => {
1589                return self.resolve_elsewhere_with_parent(tlds);
1590            }
1591            Self::ElsewhereDeclaredValue {
1592                identifier: e,
1593                parent: _,
1594            }
1595            | Self::EnumeratedValue {
1596                enumerated: _,
1597                enumerable: e,
1598            } => {
1599                if let Some(v) = find_tld_or_enum_value_by_name(identifier, e, tlds) {
1600                    *self = v;
1601                }
1602            }
1603            _ => {}
1604        }
1605        Ok(())
1606    }
1607}
1608
1609fn bit_string_value_from_named_bits(
1610    highest_distinguished_bit: i128,
1611    named_bits: &[String],
1612    distinguished: &[DistinguishedValue],
1613) -> Vec<bool> {
1614    (0..=highest_distinguished_bit)
1615        .map(|i| {
1616            named_bits.iter().any(|bit| {
1617                Some(bit)
1618                    == distinguished
1619                        .iter()
1620                        .find_map(|d| (d.value == i).then_some(&d.name))
1621            })
1622        })
1623        .collect()
1624}
1625
1626#[cfg(test)]
1627mod tests {
1628    use std::collections::BTreeMap;
1629
1630    use crate::intermediate::{types::*, *};
1631
1632    macro_rules! tld {
1633        ($name:literal, $ty:expr) => {
1634            ToplevelTypeDefinition {
1635                comments: String::new(),
1636                tag: None,
1637                module_header: None,
1638                name: $name.into(),
1639                ty: $ty,
1640                parameterization: None,
1641            }
1642        };
1643    }
1644
1645    #[test]
1646    fn links_asn1_value() {
1647        let tlds: BTreeMap<String, ToplevelDefinition> = {
1648            let mut map = BTreeMap::new();
1649            map.insert(
1650                "RootBool".into(),
1651                ToplevelDefinition::Type(tld!(
1652                    "RootBool",
1653                    ASN1Type::Boolean(Boolean {
1654                        constraints: vec![]
1655                    })
1656                )),
1657            );
1658            map.insert(
1659                "IntermediateBool".into(),
1660                ToplevelDefinition::Type(tld!(
1661                    "IntermediateBool",
1662                    ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1663                        parent: None,
1664                        module: None,
1665                        identifier: String::from("RootBool"),
1666                        constraints: vec![]
1667                    })
1668                )),
1669            );
1670            map.insert(
1671                "BaseChoice".into(),
1672                ToplevelDefinition::Type(tld!(
1673                    "BaseChoice",
1674                    ASN1Type::Choice(Choice {
1675                        extensible: None,
1676                        constraints: vec![],
1677                        options: vec![ChoiceOption {
1678                            is_recursive: false,
1679                            name: String::from("first"),
1680                            constraints: vec![],
1681                            tag: None,
1682                            ty: ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1683                                parent: None,
1684                                module: None,
1685                                identifier: String::from("IntermediateBool"),
1686                                constraints: vec![]
1687                            })
1688                        }]
1689                    })
1690                )),
1691            );
1692            map
1693        };
1694        let mut example_value = ToplevelValueDefinition {
1695            comments: String::new(),
1696            name: "exampleValue".into(),
1697            parameterization: None,
1698            associated_type: ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1699                parent: None,
1700                module: None,
1701                identifier: "BaseChoice".into(),
1702                constraints: vec![],
1703            }),
1704            module_header: None,
1705            value: ASN1Value::Choice {
1706                type_name: None,
1707                variant_name: "first".into(),
1708                inner_value: Box::new(ASN1Value::Boolean(true)),
1709            },
1710        };
1711        example_value.collect_supertypes(&tlds).unwrap();
1712        assert_eq!(
1713            example_value,
1714            ToplevelValueDefinition {
1715                comments: "".into(),
1716                name: "exampleValue".into(),
1717                associated_type: ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere {
1718                    parent: None,
1719                    module: None,
1720                    identifier: "BaseChoice".into(),
1721                    constraints: vec![]
1722                }),
1723                parameterization: None,
1724                value: ASN1Value::Choice {
1725                    type_name: Some("BaseChoice".into()),
1726                    variant_name: "first".into(),
1727                    inner_value: Box::new(ASN1Value::LinkedNestedValue {
1728                        supertypes: vec!["IntermediateBool".into(), "RootBool".into()],
1729                        value: Box::new(ASN1Value::Boolean(true))
1730                    })
1731                },
1732                module_header: None
1733            }
1734        )
1735    }
1736}