rasn_compiler/validator/linking/
mod.rs

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