rasn_compiler/intermediate/
information_object.rs

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