rasn_compiler/intermediate/
information_object.rs

1use crate::lexer::asn1_value;
2
3use super::{constraints::*, *};
4
5/// This is either a X.681 ObjectClassAssignment or a X.683 ParameterizedObjectClassAssignment.
6///
7/// **X.681 9.1** _The construct "ObjectClassAssignment" is used to assign an information object
8/// class to a reference name ("objectclassreference"). This construct is one of the alternatives
9/// for "Assignment" in Rec. ITU-T X.680 | ISO/IEC 8824-1, clause 13._
10///
11/// **X.683 9.2** _Referencing parameterized definitions: ParameterizedObjectClassAssignment._
12#[derive(Debug, Clone, PartialEq)]
13pub struct ObjectClassAssignment {
14    pub comments: String,
15    /// A objectclassreference.
16    pub name: String,
17    pub parameterization: Parameterization,
18    pub definition: ObjectClassDefn,
19    pub module_header: Option<Rc<RefCell<ModuleHeader>>>,
20}
21
22impl ObjectClassAssignment {
23    pub(crate) fn is_parameterized(&self) -> bool {
24        !self.parameterization.parameters.is_empty()
25    }
26}
27
28#[derive(Debug, Clone, PartialEq)]
29pub struct ToplevelInformationDefinition {
30    pub comments: String,
31    pub name: String,
32    pub parameterization: Option<Parameterization>,
33    pub class: ClassLink,
34    pub value: ASN1Information,
35    pub module_header: Option<Rc<RefCell<ModuleHeader>>>,
36}
37
38impl From<(&str, ASN1Information, &str)> for ToplevelInformationDefinition {
39    fn from(value: (&str, ASN1Information, &str)) -> Self {
40        Self {
41            comments: String::new(),
42            name: value.0.to_owned(),
43            parameterization: None,
44            class: ClassLink::ByName(value.2.to_owned()),
45            value: value.1,
46            module_header: None,
47        }
48    }
49}
50
51#[cfg_attr(test, derive(EnumDebug))]
52#[cfg_attr(not(test), derive(Debug))]
53#[derive(Clone, PartialEq)]
54pub enum ClassLink {
55    ByName(String),
56    ByReference(ObjectClassDefn),
57}
58
59impl ToplevelInformationDefinition {
60    pub fn pdu(&self) -> &ASN1Information {
61        &self.value
62    }
63}
64
65impl
66    From<(
67        Vec<&str>,
68        &str,
69        Option<Parameterization>,
70        &str,
71        InformationObjectFields,
72    )> for ToplevelInformationDefinition
73{
74    fn from(
75        value: (
76            Vec<&str>,
77            &str,
78            Option<Parameterization>,
79            &str,
80            InformationObjectFields,
81        ),
82    ) -> Self {
83        Self {
84            comments: value.0.join("\n"),
85            name: value.1.into(),
86            class: ClassLink::ByName(value.3.into()),
87            parameterization: value.2,
88            value: ASN1Information::Object(InformationObject {
89                class_name: value.3.into(),
90                fields: value.4,
91            }),
92            module_header: None,
93        }
94    }
95}
96
97impl From<(Vec<&str>, &str, Option<Parameterization>, &str, ObjectSet)>
98    for ToplevelInformationDefinition
99{
100    fn from(value: (Vec<&str>, &str, Option<Parameterization>, &str, ObjectSet)) -> Self {
101        Self {
102            comments: value.0.join("\n"),
103            name: value.1.into(),
104            parameterization: value.2,
105            class: ClassLink::ByName(value.3.into()),
106            value: ASN1Information::ObjectSet(value.4),
107            module_header: None,
108        }
109    }
110}
111
112/// The possible types of an ASN1 information object.
113#[cfg_attr(test, derive(EnumDebug))]
114#[cfg_attr(not(test), derive(Debug))]
115#[derive(Clone, PartialEq)]
116pub enum ASN1Information {
117    ObjectSet(ObjectSet),
118    Object(InformationObject),
119}
120
121#[cfg_attr(test, derive(EnumDebug))]
122#[cfg_attr(not(test), derive(Debug))]
123#[derive(Clone, PartialEq)]
124pub enum SyntaxExpression {
125    Required(SyntaxToken),
126    Optional(Vec<SyntaxExpression>),
127}
128
129#[cfg_attr(test, derive(EnumDebug))]
130#[cfg_attr(not(test), derive(Debug))]
131#[derive(Clone, PartialEq)]
132pub enum SyntaxApplication {
133    ObjectSetDeclaration(ObjectSet),
134    ValueReference(ASN1Value),
135    TypeReference(ASN1Type),
136    Comma,
137    Literal(String),
138    LiteralOrTypeReference(DeclarationElsewhere),
139}
140
141impl SyntaxApplication {
142    /// Checks if a token of a syntactic expression matches a given syntax token,
143    /// considering the entire syntax (in form of a flattened SyntaxExpression Vec), in order to reliably match Literals
144    pub fn matches(
145        &self,
146        next_token: &SyntaxToken,
147        syntax: &[(bool, SyntaxToken)],
148        current_index: usize,
149    ) -> bool {
150        match (next_token, self) {
151            (SyntaxToken::Comma, SyntaxApplication::Comma) => true,
152            (SyntaxToken::Literal(t), SyntaxApplication::Literal(a)) if t == a => true,
153            (
154                SyntaxToken::Literal(t),
155                SyntaxApplication::LiteralOrTypeReference(DeclarationElsewhere {
156                    identifier, ..
157                }),
158            ) if t == identifier => true,
159            (
160                SyntaxToken::Field(ObjectFieldIdentifier::MultipleValue(_)),
161                SyntaxApplication::ObjectSetDeclaration(_),
162            ) => true,
163            (
164                SyntaxToken::Field(ObjectFieldIdentifier::MultipleValue(_)),
165                SyntaxApplication::TypeReference(_),
166            ) => true,
167            (
168                SyntaxToken::Field(ObjectFieldIdentifier::MultipleValue(_)),
169                SyntaxApplication::LiteralOrTypeReference(DeclarationElsewhere {
170                    identifier, ..
171                }),
172            ) => {
173                for (required, token) in &syntax[current_index + 1..] {
174                    if token.as_str() == identifier {
175                        return false;
176                    } else if *required {
177                        return true;
178                    }
179                }
180                true
181            }
182            (
183                SyntaxToken::Field(ObjectFieldIdentifier::SingleValue(_)),
184                SyntaxApplication::ValueReference(_),
185            ) => true,
186            (
187                SyntaxToken::Field(ObjectFieldIdentifier::SingleValue(_)),
188                SyntaxApplication::LiteralOrTypeReference(DeclarationElsewhere {
189                    identifier: lit,
190                    ..
191                }),
192            )
193            | (
194                SyntaxToken::Field(ObjectFieldIdentifier::SingleValue(_)),
195                SyntaxApplication::Literal(lit),
196            ) => {
197                let val = asn1_value(lit.as_str().into());
198                match val {
199                    Ok((_, ASN1Value::ElsewhereDeclaredValue { .. })) => false,
200                    Ok((_, _)) => true,
201                    _ => false,
202                }
203            }
204            _ => false,
205        }
206    }
207
208    pub(crate) fn as_str_or_none(&self) -> Option<&str> {
209        match self {
210            SyntaxApplication::ObjectSetDeclaration(_) => None,
211            SyntaxApplication::ValueReference(ASN1Value::ElsewhereDeclaredValue {
212                parent: None,
213                identifier,
214            })
215            | SyntaxApplication::LiteralOrTypeReference(DeclarationElsewhere {
216                parent: None,
217                identifier,
218                ..
219            })
220            | SyntaxApplication::TypeReference(ASN1Type::ElsewhereDeclaredType(
221                DeclarationElsewhere {
222                    parent: None,
223                    identifier,
224                    ..
225                },
226            )) => Some(identifier),
227            SyntaxApplication::Literal(l) => Some(l),
228            _ => None,
229        }
230    }
231}
232
233#[cfg_attr(test, derive(EnumDebug))]
234#[cfg_attr(not(test), derive(Debug))]
235#[derive(Clone, PartialEq)]
236pub enum SyntaxToken {
237    Literal(String),
238    Comma,
239    Field(ObjectFieldIdentifier),
240}
241
242impl SyntaxToken {
243    pub fn as_str(&self) -> &str {
244        match self {
245            SyntaxToken::Literal(s) => s.as_str(),
246            SyntaxToken::Comma => ",",
247            SyntaxToken::Field(_) => self.name_or_empty(),
248        }
249    }
250
251    pub fn name_or_empty(&self) -> &str {
252        match self {
253            SyntaxToken::Field(ObjectFieldIdentifier::SingleValue(v))
254            | SyntaxToken::Field(ObjectFieldIdentifier::MultipleValue(v)) => v.as_str(),
255            _ => "",
256        }
257    }
258}
259
260impl From<ObjectFieldIdentifier> for SyntaxToken {
261    fn from(value: ObjectFieldIdentifier) -> Self {
262        Self::Field(value)
263    }
264}
265
266impl From<&str> for SyntaxToken {
267    fn from(value: &str) -> Self {
268        if value == "," {
269            Self::Comma
270        } else {
271            Self::Literal(value.into())
272        }
273    }
274}
275
276#[derive(Debug, Clone, PartialEq)]
277pub struct InformationObjectSyntax {
278    pub expressions: Vec<SyntaxExpression>,
279}
280
281impl InformationObjectSyntax {
282    /// Information object syntax consists of mandatory and optional expressions.
283    /// Optional expressions may be nested without limit.
284    /// Declarations do not have this nested structure, but are always a sequence of
285    /// tokens, so in order to check whether an expression follows a given syntax we need to
286    /// flatten the nested structure into a sequence of tokens with a `required` marker.
287    pub fn flatten(&self) -> Vec<(bool, SyntaxToken)> {
288        fn iter_expressions(
289            expressions: &[SyntaxExpression],
290            optional_recursion: bool,
291        ) -> Vec<(bool, &SyntaxExpression)> {
292            expressions
293                .iter()
294                .flat_map(|x| match x {
295                    SyntaxExpression::Optional(o) => iter_expressions(o, true),
296                    r => vec![(!optional_recursion, r)],
297                })
298                .collect()
299        }
300
301        iter_expressions(&self.expressions, false)
302            .into_iter()
303            .map(|x| match x {
304                (is_required, SyntaxExpression::Required(r)) => (is_required, r.clone()),
305                _ => unreachable!(),
306            })
307            .collect()
308    }
309}
310
311/// X.681 9.3  Every class is ultimately defined by an "ObjectClassDefn".
312///
313/// Allows the definer to provide the field specifications, and optionally a syntax list. The
314/// definer may also specify semantics associated with the definition of the class.
315#[derive(Debug, Clone, PartialEq)]
316pub struct ObjectClassDefn {
317    /// Named field specifications, as defined in 9.4.
318    pub fields: Vec<InformationObjectClassField>,
319    /// An information object definition syntax ("SyntaxList"), as defined in 10.5.
320    pub syntax: Option<InformationObjectSyntax>,
321}
322
323impl
324    From<(
325        Vec<InformationObjectClassField>,
326        Option<Vec<SyntaxExpression>>,
327    )> for ObjectClassDefn
328{
329    fn from(
330        value: (
331            Vec<InformationObjectClassField>,
332            Option<Vec<SyntaxExpression>>,
333        ),
334    ) -> Self {
335        Self {
336            fields: value.0,
337            syntax: value
338                .1
339                .map(|expr| InformationObjectSyntax { expressions: expr }),
340        }
341    }
342}
343
344#[derive(Debug, Clone, PartialEq)]
345pub struct InformationObjectClassField {
346    pub identifier: ObjectFieldIdentifier,
347    pub ty: Option<ASN1Type>,
348    pub optionality: Optionality<ASN1Value>,
349    pub is_unique: bool,
350}
351
352impl
353    From<(
354        ObjectFieldIdentifier,
355        Option<ASN1Type>,
356        Option<&str>,
357        Optionality<ASN1Value>,
358    )> for InformationObjectClassField
359{
360    fn from(
361        value: (
362            ObjectFieldIdentifier,
363            Option<ASN1Type>,
364            Option<&str>,
365            Optionality<ASN1Value>,
366        ),
367    ) -> Self {
368        Self {
369            identifier: value.0,
370            ty: value.1,
371            is_unique: value.2.is_some(),
372            optionality: value.3,
373        }
374    }
375}
376
377#[cfg_attr(test, derive(EnumDebug))]
378#[cfg_attr(not(test), derive(Debug))]
379#[derive(Clone, PartialEq)]
380pub enum ObjectFieldIdentifier {
381    SingleValue(String),
382    MultipleValue(String),
383}
384
385impl ObjectFieldIdentifier {
386    pub fn identifier(&self) -> &String {
387        match self {
388            ObjectFieldIdentifier::SingleValue(s) => s,
389            ObjectFieldIdentifier::MultipleValue(s) => s,
390        }
391    }
392}
393
394#[derive(Debug, Clone, PartialEq)]
395pub struct InformationObject {
396    pub class_name: String,
397    pub fields: InformationObjectFields,
398}
399
400#[cfg_attr(test, derive(EnumDebug))]
401#[cfg_attr(not(test), derive(Debug))]
402#[derive(Clone, PartialEq)]
403pub enum InformationObjectFields {
404    DefaultSyntax(Vec<InformationObjectField>),
405    CustomSyntax(Vec<SyntaxApplication>),
406}
407
408#[cfg_attr(test, derive(EnumDebug))]
409#[cfg_attr(not(test), derive(Debug))]
410#[derive(Clone, PartialEq)]
411pub enum ObjectSetValue {
412    Reference(String),
413    Inline(InformationObjectFields),
414}
415
416impl From<&str> for ObjectSetValue {
417    fn from(value: &str) -> Self {
418        Self::Reference(value.into())
419    }
420}
421
422impl From<InformationObjectFields> for ObjectSetValue {
423    fn from(value: InformationObjectFields) -> Self {
424        Self::Inline(value)
425    }
426}
427
428#[derive(Debug, Clone, PartialEq)]
429pub struct ObjectSet {
430    pub values: Vec<ObjectSetValue>,
431    pub extensible: Option<usize>,
432}
433
434impl
435    From<(
436        Vec<ObjectSetValue>,
437        Option<ExtensionMarker>,
438        Option<Vec<ObjectSetValue>>,
439    )> for ObjectSet
440{
441    fn from(
442        mut value: (
443            Vec<ObjectSetValue>,
444            Option<ExtensionMarker>,
445            Option<Vec<ObjectSetValue>>,
446        ),
447    ) -> Self {
448        let index_of_first_extension = value.0.len();
449        value.0.append(&mut value.2.unwrap_or_default());
450        ObjectSet {
451            values: value.0,
452            extensible: value.1.map(|_| index_of_first_extension),
453        }
454    }
455}
456
457#[cfg_attr(test, derive(EnumDebug))]
458#[cfg_attr(not(test), derive(Debug))]
459#[derive(Clone, PartialEq)]
460pub enum InformationObjectField {
461    TypeField(TypeField),
462    FixedValueField(FixedValueField),
463    ObjectSetField(ObjectSetField),
464}
465
466impl InformationObjectField {
467    /// Returns the identifier of an InformationObjectField
468    pub fn identifier(&self) -> &String {
469        match self {
470            InformationObjectField::TypeField(f) => &f.identifier,
471            InformationObjectField::FixedValueField(f) => &f.identifier,
472            InformationObjectField::ObjectSetField(f) => &f.identifier,
473        }
474    }
475}
476
477#[derive(Debug, Clone, PartialEq)]
478pub struct FixedValueField {
479    pub identifier: String,
480    pub value: ASN1Value,
481}
482
483impl From<(ObjectFieldIdentifier, ASN1Value)> for InformationObjectField {
484    fn from(value: (ObjectFieldIdentifier, ASN1Value)) -> Self {
485        Self::FixedValueField(FixedValueField {
486            identifier: value.0.identifier().clone(),
487            value: value.1,
488        })
489    }
490}
491
492#[derive(Debug, Clone, PartialEq)]
493pub struct TypeField {
494    pub identifier: String,
495    pub ty: ASN1Type,
496}
497
498impl From<(ObjectFieldIdentifier, ASN1Type)> for InformationObjectField {
499    fn from(value: (ObjectFieldIdentifier, ASN1Type)) -> Self {
500        Self::TypeField(TypeField {
501            identifier: value.0.identifier().clone(),
502            ty: value.1,
503        })
504    }
505}
506
507#[derive(Debug, Clone, PartialEq)]
508pub struct ObjectSetField {
509    pub identifier: String,
510    pub value: ObjectSet,
511}
512
513impl From<(ObjectFieldIdentifier, ObjectSet)> for InformationObjectField {
514    fn from(value: (ObjectFieldIdentifier, ObjectSet)) -> Self {
515        Self::ObjectSetField(ObjectSetField {
516            identifier: value.0.identifier().clone(),
517            value: value.1,
518        })
519    }
520}
521
522/// #### X.681 14 Notation for the object class field type
523/// _The type that is referenced by this notation depends on the category of the field name. For
524/// the different categories of field names, 14.2 to 14.5 specify the type that is referenced._
525#[derive(Debug, Clone, PartialEq)]
526pub struct ObjectClassFieldType {
527    pub class: String,
528    pub field_path: Vec<ObjectFieldIdentifier>,
529    pub constraints: Vec<Constraint>,
530}
531
532impl ObjectClassFieldType {
533    /// Returns the field path as string.
534    /// The field path is stringified by joining
535    /// the stringified `ObjectFieldIdentifier`s with
536    /// the `$` character as a separator.
537    pub fn field_path_as_str(&self) -> String {
538        self.field_path
539            .iter()
540            .map(|o| o.identifier().clone())
541            .collect::<Vec<_>>()
542            .join("$")
543    }
544}
545
546impl From<(&str, Vec<ObjectFieldIdentifier>, Option<Vec<Constraint>>)> for ObjectClassFieldType {
547    fn from(value: (&str, Vec<ObjectFieldIdentifier>, Option<Vec<Constraint>>)) -> Self {
548        Self {
549            class: value.0.into(),
550            field_path: value.1,
551            constraints: value.2.unwrap_or_default(),
552        }
553    }
554}