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                module: None,
213                parent: None,
214                identifier,
215            })
216            | SyntaxApplication::LiteralOrTypeReference(DeclarationElsewhere {
217                parent: None,
218                identifier,
219                ..
220            })
221            | SyntaxApplication::TypeReference(ASN1Type::ElsewhereDeclaredType(
222                DeclarationElsewhere {
223                    parent: None,
224                    identifier,
225                    ..
226                },
227            )) => Some(identifier),
228            SyntaxApplication::Literal(l) => Some(l),
229            _ => None,
230        }
231    }
232}
233
234#[cfg_attr(test, derive(EnumDebug))]
235#[cfg_attr(not(test), derive(Debug))]
236#[derive(Clone, PartialEq)]
237pub enum SyntaxToken {
238    Literal(String),
239    Comma,
240    Field(ObjectFieldIdentifier),
241}
242
243impl SyntaxToken {
244    pub fn as_str(&self) -> &str {
245        match self {
246            SyntaxToken::Literal(s) => s.as_str(),
247            SyntaxToken::Comma => ",",
248            SyntaxToken::Field(_) => self.name_or_empty(),
249        }
250    }
251
252    pub fn name_or_empty(&self) -> &str {
253        match self {
254            SyntaxToken::Field(ObjectFieldIdentifier::SingleValue(v))
255            | SyntaxToken::Field(ObjectFieldIdentifier::MultipleValue(v)) => v.as_str(),
256            _ => "",
257        }
258    }
259}
260
261impl From<ObjectFieldIdentifier> for SyntaxToken {
262    fn from(value: ObjectFieldIdentifier) -> Self {
263        Self::Field(value)
264    }
265}
266
267impl From<&str> for SyntaxToken {
268    fn from(value: &str) -> Self {
269        if value == "," {
270            Self::Comma
271        } else {
272            Self::Literal(value.into())
273        }
274    }
275}
276
277#[derive(Debug, Clone, PartialEq)]
278pub struct InformationObjectSyntax {
279    pub expressions: Vec<SyntaxExpression>,
280}
281
282impl InformationObjectSyntax {
283    /// Information object syntax consists of mandatory and optional expressions.
284    /// Optional expressions may be nested without limit.
285    /// Declarations do not have this nested structure, but are always a sequence of
286    /// tokens, so in order to check whether an expression follows a given syntax we need to
287    /// flatten the nested structure into a sequence of tokens with a `required` marker.
288    pub fn flatten(&self) -> Vec<(bool, SyntaxToken)> {
289        fn iter_expressions(
290            expressions: &[SyntaxExpression],
291            optional_recursion: bool,
292        ) -> Vec<(bool, &SyntaxExpression)> {
293            expressions
294                .iter()
295                .flat_map(|x| match x {
296                    SyntaxExpression::Optional(o) => iter_expressions(o, true),
297                    r => vec![(!optional_recursion, r)],
298                })
299                .collect()
300        }
301
302        iter_expressions(&self.expressions, false)
303            .into_iter()
304            .map(|x| match x {
305                (is_required, SyntaxExpression::Required(r)) => (is_required, r.clone()),
306                _ => unreachable!(),
307            })
308            .collect()
309    }
310}
311
312/// X.681 9.3  Every class is ultimately defined by an "ObjectClassDefn".
313///
314/// Allows the definer to provide the field specifications, and optionally a syntax list. The
315/// definer may also specify semantics associated with the definition of the class.
316#[derive(Debug, Clone, PartialEq)]
317pub struct ObjectClassDefn {
318    /// Named field specifications, as defined in 9.4.
319    pub fields: Vec<InformationObjectClassField>,
320    /// An information object definition syntax ("SyntaxList"), as defined in 10.5.
321    pub syntax: Option<InformationObjectSyntax>,
322}
323
324impl
325    From<(
326        Vec<InformationObjectClassField>,
327        Option<Vec<SyntaxExpression>>,
328    )> for ObjectClassDefn
329{
330    fn from(
331        value: (
332            Vec<InformationObjectClassField>,
333            Option<Vec<SyntaxExpression>>,
334        ),
335    ) -> Self {
336        Self {
337            fields: value.0,
338            syntax: value
339                .1
340                .map(|expr| InformationObjectSyntax { expressions: expr }),
341        }
342    }
343}
344
345#[derive(Debug, Clone, PartialEq)]
346pub struct InformationObjectClassField {
347    pub identifier: ObjectFieldIdentifier,
348    pub ty: Option<ASN1Type>,
349    pub optionality: Optionality<ASN1Value>,
350    pub is_unique: bool,
351}
352
353impl
354    From<(
355        ObjectFieldIdentifier,
356        Option<ASN1Type>,
357        Option<&str>,
358        Optionality<ASN1Value>,
359    )> for InformationObjectClassField
360{
361    fn from(
362        value: (
363            ObjectFieldIdentifier,
364            Option<ASN1Type>,
365            Option<&str>,
366            Optionality<ASN1Value>,
367        ),
368    ) -> Self {
369        Self {
370            identifier: value.0,
371            ty: value.1,
372            is_unique: value.2.is_some(),
373            optionality: value.3,
374        }
375    }
376}
377
378#[cfg_attr(test, derive(EnumDebug))]
379#[cfg_attr(not(test), derive(Debug))]
380#[derive(Clone, PartialEq)]
381pub enum ObjectFieldIdentifier {
382    SingleValue(String),
383    MultipleValue(String),
384}
385
386impl ObjectFieldIdentifier {
387    pub fn identifier(&self) -> &String {
388        match self {
389            ObjectFieldIdentifier::SingleValue(s) => s,
390            ObjectFieldIdentifier::MultipleValue(s) => s,
391        }
392    }
393}
394
395#[derive(Debug, Clone, PartialEq)]
396pub struct InformationObject {
397    pub class_name: String,
398    pub fields: InformationObjectFields,
399}
400
401#[cfg_attr(test, derive(EnumDebug))]
402#[cfg_attr(not(test), derive(Debug))]
403#[derive(Clone, PartialEq)]
404pub enum InformationObjectFields {
405    DefaultSyntax(Vec<InformationObjectField>),
406    CustomSyntax(Vec<SyntaxApplication>),
407}
408
409#[cfg_attr(test, derive(EnumDebug))]
410#[cfg_attr(not(test), derive(Debug))]
411#[derive(Clone, PartialEq)]
412pub enum ObjectSetValue {
413    Reference(String),
414    Inline(InformationObjectFields),
415}
416
417impl From<&str> for ObjectSetValue {
418    fn from(value: &str) -> Self {
419        Self::Reference(value.into())
420    }
421}
422
423impl From<InformationObjectFields> for ObjectSetValue {
424    fn from(value: InformationObjectFields) -> Self {
425        Self::Inline(value)
426    }
427}
428
429#[derive(Debug, Clone, PartialEq)]
430pub struct ObjectSet {
431    pub values: Vec<ObjectSetValue>,
432    pub extensible: Option<usize>,
433}
434
435impl
436    From<(
437        Vec<ObjectSetValue>,
438        Option<ExtensionMarker>,
439        Option<Vec<ObjectSetValue>>,
440    )> for ObjectSet
441{
442    fn from(
443        mut value: (
444            Vec<ObjectSetValue>,
445            Option<ExtensionMarker>,
446            Option<Vec<ObjectSetValue>>,
447        ),
448    ) -> Self {
449        let index_of_first_extension = value.0.len();
450        value.0.append(&mut value.2.unwrap_or_default());
451        ObjectSet {
452            values: value.0,
453            extensible: value.1.map(|_| index_of_first_extension),
454        }
455    }
456}
457
458#[cfg_attr(test, derive(EnumDebug))]
459#[cfg_attr(not(test), derive(Debug))]
460#[derive(Clone, PartialEq)]
461pub enum InformationObjectField {
462    TypeField(TypeField),
463    FixedValueField(FixedValueField),
464    ObjectSetField(ObjectSetField),
465}
466
467impl InformationObjectField {
468    /// Returns the identifier of an InformationObjectField
469    pub fn identifier(&self) -> &String {
470        match self {
471            InformationObjectField::TypeField(f) => &f.identifier,
472            InformationObjectField::FixedValueField(f) => &f.identifier,
473            InformationObjectField::ObjectSetField(f) => &f.identifier,
474        }
475    }
476}
477
478#[derive(Debug, Clone, PartialEq)]
479pub struct FixedValueField {
480    pub identifier: String,
481    pub value: ASN1Value,
482}
483
484impl From<(ObjectFieldIdentifier, ASN1Value)> for InformationObjectField {
485    fn from(value: (ObjectFieldIdentifier, ASN1Value)) -> Self {
486        Self::FixedValueField(FixedValueField {
487            identifier: value.0.identifier().clone(),
488            value: value.1,
489        })
490    }
491}
492
493#[derive(Debug, Clone, PartialEq)]
494pub struct TypeField {
495    pub identifier: String,
496    pub ty: ASN1Type,
497}
498
499impl From<(ObjectFieldIdentifier, ASN1Type)> for InformationObjectField {
500    fn from(value: (ObjectFieldIdentifier, ASN1Type)) -> Self {
501        Self::TypeField(TypeField {
502            identifier: value.0.identifier().clone(),
503            ty: value.1,
504        })
505    }
506}
507
508#[derive(Debug, Clone, PartialEq)]
509pub struct ObjectSetField {
510    pub identifier: String,
511    pub value: ObjectSet,
512}
513
514impl From<(ObjectFieldIdentifier, ObjectSet)> for InformationObjectField {
515    fn from(value: (ObjectFieldIdentifier, ObjectSet)) -> Self {
516        Self::ObjectSetField(ObjectSetField {
517            identifier: value.0.identifier().clone(),
518            value: value.1,
519        })
520    }
521}
522
523/// #### X.681 14 Notation for the object class field type
524/// _The type that is referenced by this notation depends on the category of the field name. For
525/// the different categories of field names, 14.2 to 14.5 specify the type that is referenced._
526#[derive(Debug, Clone, PartialEq)]
527pub struct ObjectClassFieldType {
528    pub class: String,
529    pub field_path: Vec<ObjectFieldIdentifier>,
530    pub constraints: Vec<Constraint>,
531}
532
533impl ObjectClassFieldType {
534    /// Returns the field path as string.
535    /// The field path is stringified by joining
536    /// the stringified `ObjectFieldIdentifier`s with
537    /// the `$` character as a separator.
538    pub fn field_path_as_str(&self) -> String {
539        self.field_path
540            .iter()
541            .map(|o| o.identifier().clone())
542            .collect::<Vec<_>>()
543            .join("$")
544    }
545}
546
547impl From<(&str, Vec<ObjectFieldIdentifier>, Option<Vec<Constraint>>)> for ObjectClassFieldType {
548    fn from(value: (&str, Vec<ObjectFieldIdentifier>, Option<Vec<Constraint>>)) -> Self {
549        Self {
550            class: value.0.into(),
551            field_path: value.1,
552            constraints: value.2.unwrap_or_default(),
553        }
554    }
555}