rasn_compiler/validator/linking/
mod.rs

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