rasn_compiler/intermediate/
types.rs

1//! `types` contains representations for ASN.1's basic types, such as `BOOLEAN`s
2//! or `SEQUENCE`s.
3#[cfg(test)]
4use internal_macros::EnumDebug;
5use std::vec;
6
7#[cfg(doc)]
8use crate::Backend;
9
10use super::{constraints::*, *};
11
12/// Defines the optionality of a field.
13#[derive(Debug, Clone, PartialEq)]
14pub enum Optionality<T> {
15    /// All definitions are required to specify this field.
16    Required,
17    /// The field can be left undefined.
18    Optional,
19    /// Default if the field is omitted.
20    Default(T),
21}
22
23impl<T> Optionality<T> {
24    /// Get a reference to the default `T`, or None if there is no default.
25    pub fn default(&self) -> Option<&T> {
26        match self {
27            Optionality::Required | Optionality::Optional => None,
28            Optionality::Default(d) => Some(d),
29        }
30    }
31
32    /// Get a mutable reference to the default `T`, or None if there is no default.
33    pub fn default_mut(&mut self) -> Option<&mut T> {
34        match self {
35            Optionality::Required | Optionality::Optional => None,
36            Optionality::Default(d) => Some(d),
37        }
38    }
39}
40
41/// Trait shared by ASN1 `SET`, `SEQUENCE`, AND `CHOICE` that allows iterating
42/// over their field types.
43pub trait IterNameTypes {
44    fn iter_name_types(&self) -> impl Iterator<Item = (&str, &ASN1Type)>;
45}
46
47/// Convenience trait for processing members of constructed types (`SEQUENCE`, `SET`) and `CHOICE`s.
48pub trait MemberOrOption {
49    const IS_CHOICE_OPTION: bool;
50    fn name(&self) -> &str;
51    fn ty(&self) -> &ASN1Type;
52    fn constraints(&self) -> &[Constraint];
53    fn is_recursive(&self) -> bool;
54    fn tag(&self) -> Option<&AsnTag>;
55}
56
57/// Trait shared by all ASN1 types that can be constrained a.k.a subtyped.
58/// *See also Rec. ITU-T X.680 (02/2021) §49 - §51*
59pub trait Constrainable {
60    /// returns a reference to the type's constraints
61    fn constraints(&self) -> &Vec<Constraint>;
62    /// returns a mutable reference to the type's constraints
63    fn constraints_mut(&mut self) -> &mut Vec<Constraint>;
64}
65
66macro_rules! constrainable {
67    ($typ:ty) => {
68        impl Constrainable for $typ {
69            fn constraints(&self) -> &Vec<Constraint> {
70                &self.constraints
71            }
72
73            fn constraints_mut(&mut self) -> &mut Vec<Constraint> {
74                &mut self.constraints
75            }
76        }
77    };
78}
79
80constrainable!(Boolean);
81constrainable!(Integer);
82constrainable!(BitString);
83constrainable!(OctetString);
84constrainable!(CharacterString);
85constrainable!(Real);
86constrainable!(SequenceOrSet);
87constrainable!(SequenceOrSetOf);
88constrainable!(Choice);
89constrainable!(Enumerated);
90constrainable!(DeclarationElsewhere);
91constrainable!(ObjectClassFieldType);
92constrainable!(Time);
93
94/// Representation of an ASN1 BOOLEAN data element
95/// with corresponding constraints.
96/// *As defined in Rec. ITU-T X.680 (02/2021) §18*
97#[derive(Debug, Clone, PartialEq, Default)]
98pub struct Boolean {
99    pub constraints: Vec<Constraint>,
100}
101
102impl From<Option<Vec<Constraint>>> for Boolean {
103    fn from(value: Option<Vec<Constraint>>) -> Self {
104        Self {
105            constraints: value.unwrap_or_default(),
106        }
107    }
108}
109
110/// Representation of an ASN1 INTEGER data element
111/// with corresponding constraints and distinguished values.
112/// *As defined in Rec. ITU-T X.680 (02/2021) §19*
113#[derive(Debug, Clone, PartialEq, Default)]
114pub struct Integer {
115    pub constraints: Vec<Constraint>,
116    pub distinguished_values: Option<Vec<DistinguishedValue>>,
117}
118
119impl Integer {
120    /// Returns the [IntegerType] of `self`.
121    /// The [IntegerType] describes the absolute range of an integer
122    pub fn int_type(&self) -> IntegerType {
123        self.constraints
124            .iter()
125            .fold(IntegerType::Unbounded, |acc, c| {
126                c.integer_constraints().max_restrictive(acc)
127            })
128    }
129}
130
131impl From<(i128, i128, bool)> for Integer {
132    fn from(value: (i128, i128, bool)) -> Self {
133        Self {
134            constraints: vec![Constraint::Subtype(ElementSetSpecs {
135                set: ElementOrSetOperation::Element(SubtypeElements::ValueRange {
136                    min: Some(ASN1Value::Integer(value.0)),
137                    max: Some(ASN1Value::Integer(value.1)),
138                    extensible: value.2,
139                }),
140                extensible: value.2,
141            })],
142            distinguished_values: None,
143        }
144    }
145}
146
147impl From<(Option<i128>, Option<i128>, bool)> for Integer {
148    fn from(value: (Option<i128>, Option<i128>, bool)) -> Self {
149        Self {
150            constraints: vec![Constraint::Subtype(ElementSetSpecs {
151                set: ElementOrSetOperation::Element(SubtypeElements::ValueRange {
152                    min: value.0.map(ASN1Value::Integer),
153                    max: value.1.map(ASN1Value::Integer),
154                    extensible: value.2,
155                }),
156                extensible: value.2,
157            })],
158            distinguished_values: None,
159        }
160    }
161}
162
163impl
164    From<(
165        &str,
166        Option<Vec<DistinguishedValue>>,
167        Option<Vec<Constraint>>,
168    )> for Integer
169{
170    fn from(
171        value: (
172            &str,
173            Option<Vec<DistinguishedValue>>,
174            Option<Vec<Constraint>>,
175        ),
176    ) -> Self {
177        Self {
178            constraints: value.2.unwrap_or_default(),
179            distinguished_values: value.1,
180        }
181    }
182}
183
184/// Representation of an ASN1 REAL data element
185/// with corresponding constraints.
186/// *As defined in Rec. ITU-T X.680 (02/2021) §21*
187#[derive(Debug, Clone, PartialEq)]
188pub struct Real {
189    pub constraints: Vec<Constraint>,
190}
191
192impl From<Option<Vec<Constraint>>> for Real {
193    fn from(value: Option<Vec<Constraint>>) -> Self {
194        Self {
195            constraints: value.unwrap_or_default(),
196        }
197    }
198}
199
200/// Representation of an ASN1 GeneralizedTime data element
201/// with corresponding constraints.
202/// *As defined in Rec. ITU-T X.680 (02/2021) §46*
203#[derive(Debug, Clone, PartialEq)]
204pub struct GeneralizedTime {
205    pub constraints: Vec<Constraint>,
206}
207
208/// Representation of an ASN1 Universal time (a.k.a UTCTime)
209/// data element with corresponding constraints.
210/// *As defined in Rec. ITU-T X.680 (02/2021) §47*
211#[derive(Debug, Clone, PartialEq)]
212pub struct UTCTime {
213    pub constraints: Vec<Constraint>,
214}
215
216/// Representation of an ASN1 OCTET STRING data element
217/// with corresponding constraints.
218/// *As defined in Rec. ITU-T X.680 (02/2021) §23*
219#[derive(Debug, Clone, PartialEq)]
220pub struct OctetString {
221    pub constraints: Vec<Constraint>,
222}
223
224impl From<Option<Vec<Constraint>>> for OctetString {
225    fn from(value: Option<Vec<Constraint>>) -> Self {
226        OctetString {
227            constraints: value.unwrap_or_default(),
228        }
229    }
230}
231
232/// Representation of an ASN1 BIT STRING data element
233/// with corresponding constraints and distinguished values
234/// defining the individual bits.
235/// *As defined in Rec. ITU-T X.680 (02/2021) §22*
236#[derive(Debug, Clone, PartialEq)]
237pub struct BitString {
238    pub constraints: Vec<Constraint>,
239    pub distinguished_values: Option<Vec<DistinguishedValue>>,
240}
241
242impl From<(Option<Vec<DistinguishedValue>>, Option<Vec<Constraint>>)> for BitString {
243    fn from(value: (Option<Vec<DistinguishedValue>>, Option<Vec<Constraint>>)) -> Self {
244        BitString {
245            constraints: value.1.unwrap_or_default(),
246            distinguished_values: value.0,
247        }
248    }
249}
250
251/// Representation of an ASN1 OBJECT IDENTIFIER data element
252/// with corresponding constraints.
253/// *As defined in Rec. ITU-T X.680 (02/2021) §32*
254#[derive(Debug, Clone, PartialEq)]
255pub struct ObjectIdentifier {
256    pub constraints: Vec<Constraint>,
257}
258
259impl From<Option<Vec<Constraint>>> for ObjectIdentifier {
260    fn from(value: Option<Vec<Constraint>>) -> Self {
261        ObjectIdentifier {
262            constraints: value.unwrap_or_default(),
263        }
264    }
265}
266
267/// Representation of an ASN1 TIME data element
268/// with corresponding constraints.
269/// *As defined in Rec. ITU-T X.680 (02/2021) §38*
270#[derive(Debug, Clone, PartialEq)]
271pub struct Time {
272    pub constraints: Vec<Constraint>,
273}
274
275impl From<Option<Vec<Constraint>>> for Time {
276    fn from(value: Option<Vec<Constraint>>) -> Self {
277        Time {
278            constraints: value.unwrap_or_default(),
279        }
280    }
281}
282
283/// Representation of an ASN1 Character String type data element
284/// with corresponding constraints. ASN1 Character String types
285/// include IA5String, UTF8String, VideotexString.
286/// *As defined in Rec. ITU-T X.680 (02/2021) §39-*§44
287#[derive(Debug, Clone, PartialEq)]
288pub struct CharacterString {
289    pub constraints: Vec<Constraint>,
290    pub ty: CharacterStringType,
291}
292
293/// Representation of an ASN1 SEQUENCE OF and SET OF data element
294/// with corresponding constraints and element type info
295/// Whether the struct describes a SEQUENCE OF or a SET OF
296/// is identified by the `ASN1Type` enum variant that
297/// holds this struct as a value (i.e. `ASN1Type::SetOf(SequenceOrSetOf { .. })`
298/// or `ASN1Type::SequenceOf(SequenceOrSetOf { .. })`).
299/// *As defined in Rec. ITU-T X.680 (02/2021) §26 and §28*
300#[derive(Debug, Clone, PartialEq)]
301pub struct SequenceOrSetOf {
302    pub constraints: Vec<Constraint>,
303    /// [ASN.1 type](ASN1Type) of the individual elements of the collection
304    /// ### Example
305    /// The ASN.1 type
306    /// ```ignore
307    /// Sequence-of-booleans ::= SEQUENCE OF BOOLEAN
308    /// ```
309    /// will have an `element_type` field of
310    /// ```
311    /// # use rasn_compiler::prelude::ir::*;
312    /// # let test =
313    /// Box::new(ASN1Type::Boolean(Boolean { constraints: vec![] } ))
314    /// # ;
315    /// ```
316    pub element_type: Box<ASN1Type>,
317    pub element_tag: Option<AsnTag>,
318    pub is_recursive: bool,
319}
320
321impl From<(Option<Vec<Constraint>>, (Option<AsnTag>, ASN1Type))> for SequenceOrSetOf {
322    fn from(value: (Option<Vec<Constraint>>, (Option<AsnTag>, ASN1Type))) -> Self {
323        Self {
324            constraints: value.0.unwrap_or_default(),
325            element_type: Box::new(value.1 .1),
326            element_tag: value.1 .0,
327            is_recursive: false,
328        }
329    }
330}
331
332/// Representation of an ASN1 SEQUENCE or SET data element
333/// with corresponding members and extension information.
334/// Whether the struct describes a SEQUENCE or a SET
335/// is identified by the `ASN1Type` enum variant that
336/// holds this struct as a value (i.e. `ASN1Type::Set(SequenceOrSet { .. })`
337/// or `ASN1Type::Sequence(SequenceOrSet { .. })`).
338/// *As defined in Rec. ITU-T X.680 (02/2021) §25 and §27*
339#[derive(Debug, Clone, PartialEq)]
340pub struct SequenceOrSet {
341    pub components_of: Vec<String>,
342    pub extensible: Option<usize>,
343    pub constraints: Vec<Constraint>,
344    pub members: Vec<SequenceOrSetMember>,
345}
346
347impl IterNameTypes for SequenceOrSet {
348    fn iter_name_types(&self) -> impl Iterator<Item = (&str, &ASN1Type)> {
349        self.members.iter().map(|m| (m.name.as_str(), &m.ty))
350    }
351}
352
353impl
354    From<(
355        (
356            Vec<SequenceComponent>,
357            Option<ExtensionMarker>,
358            Option<Vec<SequenceComponent>>,
359        ),
360        Option<Vec<Constraint>>,
361    )> for SequenceOrSet
362{
363    fn from(
364        mut value: (
365            (
366                Vec<SequenceComponent>,
367                Option<ExtensionMarker>,
368                Option<Vec<SequenceComponent>>,
369            ),
370            Option<Vec<Constraint>>,
371        ),
372    ) -> Self {
373        let index_of_first_extension = value.0 .0.len();
374        value.0 .0.append(&mut value.0 .2.unwrap_or_default());
375        let mut components_of = vec![];
376        let mut members = vec![];
377        for comp in value.0 .0 {
378            match comp {
379                SequenceComponent::Member(m) => members.push(m),
380                SequenceComponent::ComponentsOf(c) => components_of.push(c),
381            }
382        }
383        SequenceOrSet {
384            components_of,
385            constraints: value.1.unwrap_or_default(),
386            extensible: value.0 .1.map(|_| index_of_first_extension),
387            members,
388        }
389    }
390}
391
392impl
393    From<(
394        (
395            Vec<SequenceOrSetMember>,
396            Option<ExtensionMarker>,
397            Option<Vec<SequenceOrSetMember>>,
398        ),
399        Option<Vec<Constraint>>,
400    )> for SequenceOrSet
401{
402    fn from(
403        mut value: (
404            (
405                Vec<SequenceOrSetMember>,
406                Option<ExtensionMarker>,
407                Option<Vec<SequenceOrSetMember>>,
408            ),
409            Option<Vec<Constraint>>,
410        ),
411    ) -> Self {
412        let index_of_first_extension = value.0 .0.len();
413        value.0 .0.append(&mut value.0 .2.unwrap_or_default());
414        SequenceOrSet {
415            components_of: vec![],
416            constraints: value.1.unwrap_or_default(),
417            extensible: value.0 .1.map(|_| index_of_first_extension),
418            members: value.0 .0,
419        }
420    }
421}
422
423/// Intermediate parsing type to parse COMPONENTS OF notation.
424/// `SequenceComponent` is an intermediary type that implementors of
425/// a [Backend] will usually not interact with.
426/// When parsing the body of an ASN.1 SEQUENCE or SET, the lexer
427/// distinguishes between a group of members (`SequenceComponent::ComponentsOf`) that is imnported from
428/// another ASN.1 data element using the `COMPONENTS OF` notation
429/// (i.e. `Extending-Sequence ::= SEQUENCE { COMPONENTS OF Another-Sequence, added-field BOOLEAN }`)
430/// and the regular member declaration (`SequenceComponent::Member`)
431/// (i.e. `Simple-Sequence ::= SEQUENCE { field BOOLEAN }`).
432/// When the lexer assembles the complete [SequenceOrSet] struct,
433/// it groups the parsed `SequenceComponent` items into the `members`
434/// and `components_of` fields of the [SequenceOrSet] struct. The linker
435/// will subsequently try to resolve the `components_of` identifiers.
436#[cfg_attr(test, derive(EnumDebug))]
437#[cfg_attr(not(test), derive(Debug))]
438#[allow(clippy::large_enum_variant)]
439#[derive(Clone, PartialEq)]
440pub enum SequenceComponent {
441    Member(SequenceOrSetMember),
442    ComponentsOf(String),
443}
444
445/// Representation of an single ASN1 SEQUENCE or SET member.
446/// ### Example
447/// The ASN.1 SEQUENCE defined as
448/// ```ignore
449/// Test-Sequence ::= SEQUENCE {
450///     int-member [0] INTEGER (0..2) DEFAULT 1
451/// }
452/// ```
453/// defines one member, which is representated as follows
454/// ```
455/// # use rasn_compiler::prelude::ir::*;
456/// # let test =
457/// SequenceOrSetMember {
458///     is_recursive: false,
459///     name: String::from("int-member"),
460///     tag: Some(AsnTag {
461///         environment: TaggingEnvironment::Automatic,
462///         tag_class: TagClass::ContextSpecific,
463///         id: 0,
464///     }),
465///     ty: ASN1Type::Integer(Integer {
466///         constraints: vec![
467///             Constraint::Subtype(ElementSetSpecs {
468///                 set: ElementOrSetOperation::Element(SubtypeElements::ValueRange {
469///                     min: Some(ASN1Value::Integer(0)),
470///                     max: Some(ASN1Value::Integer(2)),
471///                     extensible: false
472///                 }),
473///                 extensible: false
474///            })
475///         ],
476///         distinguished_values: None,
477///     }),
478///     optionality: Optionality::Default(ASN1Value::Integer(1)),
479///     constraints: vec![]
480/// }
481/// # ;
482/// ```
483#[derive(Debug, Clone, PartialEq)]
484pub struct SequenceOrSetMember {
485    pub name: String,
486    pub tag: Option<AsnTag>,
487    pub ty: ASN1Type,
488    pub optionality: Optionality<ASN1Value>,
489    pub is_recursive: bool,
490    pub constraints: Vec<Constraint>,
491}
492
493impl MemberOrOption for SequenceOrSetMember {
494    fn name(&self) -> &str {
495        &self.name
496    }
497
498    fn ty(&self) -> &ASN1Type {
499        &self.ty
500    }
501
502    fn constraints(&self) -> &[Constraint] {
503        &self.constraints
504    }
505
506    fn is_recursive(&self) -> bool {
507        self.is_recursive
508    }
509
510    fn tag(&self) -> Option<&AsnTag> {
511        self.tag.as_ref()
512    }
513
514    const IS_CHOICE_OPTION: bool = false;
515}
516
517impl
518    From<(
519        &str,
520        Option<AsnTag>,
521        ASN1Type,
522        Option<Vec<Constraint>>,
523        Optionality<ASN1Value>,
524    )> for SequenceOrSetMember
525{
526    fn from(
527        value: (
528            &str,
529            Option<AsnTag>,
530            ASN1Type,
531            Option<Vec<Constraint>>,
532            Optionality<ASN1Value>,
533        ),
534    ) -> Self {
535        SequenceOrSetMember {
536            name: value.0.into(),
537            tag: value.1,
538            ty: value.2,
539            optionality: value.4,
540            is_recursive: false,
541            constraints: value.3.unwrap_or_default(),
542        }
543    }
544}
545
546/// Representation of an ASN1 CHOICE data element
547/// with corresponding members and extension information.
548/// *As defined in Rec. ITU-T X.680 (02/2021) §29*
549#[derive(Debug, Clone, PartialEq)]
550pub struct Choice {
551    pub extensible: Option<usize>,
552    pub options: Vec<ChoiceOption>,
553    pub constraints: Vec<Constraint>,
554}
555
556impl IterNameTypes for Choice {
557    fn iter_name_types(&self) -> impl Iterator<Item = (&str, &ASN1Type)> {
558        self.options.iter().map(|o| (o.name.as_str(), &o.ty))
559    }
560}
561
562impl
563    From<(
564        Vec<ChoiceOption>,
565        Option<ExtensionMarker>,
566        Option<Vec<ChoiceOption>>,
567    )> for Choice
568{
569    fn from(
570        mut value: (
571            Vec<ChoiceOption>,
572            Option<ExtensionMarker>,
573            Option<Vec<ChoiceOption>>,
574        ),
575    ) -> Self {
576        let index_of_first_extension = value.0.len();
577        value.0.append(&mut value.2.unwrap_or_default());
578        Choice {
579            extensible: value.1.map(|_| index_of_first_extension),
580            options: value.0,
581            constraints: vec![],
582        }
583    }
584}
585
586/// Representation of an single ASN1 CHOICE option.
587/// ### Example
588/// The ASN.1 CHOICE defined as
589/// ```ignore
590/// Test-Choice ::= CHOICE {
591///     boolean-option [0] BOOLEAN
592/// }
593/// ```
594/// defines one option, which is representated as follows
595/// ```
596/// # use rasn_compiler::prelude::ir::*;
597/// # let test =
598/// ChoiceOption {
599///     name: String::from("boolean-option"),
600///     is_recursive: false,
601///     tag: Some(AsnTag {
602///         environment: TaggingEnvironment::Automatic,
603///         tag_class: TagClass::ContextSpecific,
604///         id: 0,
605///     }),
606///     ty: ASN1Type::Boolean(Boolean {
607///         constraints: vec![]
608///     }),
609///     constraints: vec![]
610/// }
611/// # ;
612/// ```
613#[derive(Debug, Clone, PartialEq)]
614pub struct ChoiceOption {
615    pub name: String,
616    pub tag: Option<AsnTag>,
617    pub ty: ASN1Type,
618    pub constraints: Vec<Constraint>,
619    pub is_recursive: bool,
620}
621
622impl MemberOrOption for ChoiceOption {
623    fn name(&self) -> &str {
624        &self.name
625    }
626
627    fn ty(&self) -> &ASN1Type {
628        &self.ty
629    }
630
631    fn constraints(&self) -> &[Constraint] {
632        &self.constraints
633    }
634
635    fn is_recursive(&self) -> bool {
636        self.is_recursive
637    }
638
639    fn tag(&self) -> Option<&AsnTag> {
640        self.tag.as_ref()
641    }
642
643    const IS_CHOICE_OPTION: bool = true;
644}
645
646impl From<(&str, Option<AsnTag>, ASN1Type, Option<Vec<Constraint>>)> for ChoiceOption {
647    fn from(value: (&str, Option<AsnTag>, ASN1Type, Option<Vec<Constraint>>)) -> Self {
648        ChoiceOption {
649            name: value.0.into(),
650            tag: value.1,
651            ty: value.2,
652            constraints: value.3.unwrap_or_default(),
653            is_recursive: false,
654        }
655    }
656}
657
658/// Representation of an ASN1 ENUMERATED data element
659/// with corresponding enumerals and extension information.
660/// *As defined in Rec. ITU-T X.680 (02/2021) §20*
661#[derive(Debug, Clone, PartialEq)]
662pub struct Enumerated {
663    pub members: Vec<Enumeral>,
664    pub extensible: Option<usize>,
665    pub constraints: Vec<Constraint>,
666}
667
668impl
669    From<(
670        Vec<Enumeral>,
671        Option<ExtensionMarker>,
672        Option<Vec<Enumeral>>,
673    )> for Enumerated
674{
675    fn from(
676        mut value: (
677            Vec<Enumeral>,
678            Option<ExtensionMarker>,
679            Option<Vec<Enumeral>>,
680        ),
681    ) -> Self {
682        let index_of_first_extension = value.0.len();
683        value.0.append(&mut value.2.unwrap_or_default());
684        Enumerated {
685            members: value.0,
686            extensible: value.1.map(|_| index_of_first_extension),
687            constraints: vec![],
688        }
689    }
690}
691
692/// Representation of a single member/enumeral of an ASN1
693/// ENUMERATED data element.
694/// ### Example
695/// The ASN.1 ENUMERATED defined as
696/// ```ignore
697/// Test-Enum ::= ENUMERATED {
698///     first-item(7) -- This is the first item of Test-Enum
699/// }
700/// ```
701/// defines one option, which is representated as follows
702/// ```
703/// # use rasn_compiler::prelude::ir::*;
704/// # let test =
705/// Enumeral {
706///     name: String::from("first-item"),
707///     description: Some(String::from(" This is the first item of Test-Enum")),
708///     index: 7
709/// }
710/// # ;
711/// ```
712#[derive(Debug, Clone, PartialEq)]
713pub struct Enumeral {
714    pub name: String,
715    pub description: Option<String>,
716    pub index: i128,
717}
718
719/// Representation of a ASN1 distinguished value,
720/// as seen in some INTEGER and BIT STRING declarations
721/// *As defined in Rec. ITU-T X.680 (02/2021) §19.5 and §22.4*
722#[derive(Debug, Clone, PartialEq)]
723pub struct DistinguishedValue {
724    pub name: String,
725    pub value: i128,
726}
727
728impl From<(&str, i128)> for DistinguishedValue {
729    fn from(value: (&str, i128)) -> Self {
730        Self {
731            name: value.0.into(),
732            value: value.1,
733        }
734    }
735}
736
737/// Representation of a ASN1 selection type as used with ASN1 CHOICEs
738/// *As defined in Rec. ITU-T X.680 (02/2021) §30*
739#[derive(Debug, Clone, PartialEq)]
740pub struct ChoiceSelectionType {
741    pub choice_name: String,
742    pub selected_option: String,
743}
744
745impl From<(&str, &str)> for ChoiceSelectionType {
746    fn from(value: (&str, &str)) -> Self {
747        Self {
748            choice_name: value.1.into(),
749            selected_option: value.0.into(),
750        }
751    }
752}