rasn_compiler/intermediate/
constraints.rs

1#[cfg(test)]
2use internal_macros::EnumDebug;
3use std::error::Error;
4
5use super::{
6    error::{GrammarError, GrammarErrorType},
7    information_object::{InformationObjectFields, ObjectSet},
8    ASN1Type, ASN1Value, IntegerType,
9};
10
11#[derive(Debug, PartialEq)]
12pub struct OptionalMarker();
13
14impl From<&str> for OptionalMarker {
15    fn from(_: &str) -> Self {
16        OptionalMarker()
17    }
18}
19
20#[derive(Debug)]
21pub struct RangeSeperator();
22
23#[derive(Debug, Clone, PartialEq)]
24pub struct ExtensionMarker();
25
26/// X.680 49.6 Constraint specification.
27///
28/// _See X.682 (02/2021) 8_
29#[cfg_attr(test, derive(EnumDebug))]
30#[cfg_attr(not(test), derive(Debug))]
31#[derive(Clone, PartialEq)]
32pub enum Constraint {
33    Subtype(ElementSetSpecs),
34    /// A TableConstraint as specified in X.682 9.
35    Table(TableConstraint),
36    Parameter(Vec<Parameter>),
37    /// A ContentsConstraint as specified in X.682 11.
38    Content(ContentConstraint),
39}
40
41impl Constraint {
42    /// Returns the type of integer that should be used in a representation when applying the
43    /// GeneralConstraint.
44    pub fn integer_constraints(&self) -> IntegerType {
45        let (mut min, mut max, mut is_extensible) = (i128::MAX, i128::MIN, false);
46        if let Ok((cmin, cmax, extensible)) = self.unpack_as_value_range() {
47            is_extensible = is_extensible || extensible;
48            if let Some(ASN1Value::Integer(i)) = cmin {
49                min = (*i).min(min);
50            };
51            if let Some(ASN1Value::Integer(i)) = cmax {
52                max = (*i).max(max);
53            };
54        } else if let Ok((val, extensible)) = self.unpack_as_strict_value() {
55            is_extensible = is_extensible || extensible;
56            if let ASN1Value::Integer(i) = val {
57                min = (*i).min(min);
58                max = (*i).max(max);
59            };
60        };
61        if min > max || is_extensible {
62            IntegerType::Unbounded
63        } else if min >= 0 {
64            match max {
65                r if r <= u8::MAX.into() => IntegerType::Uint8,
66                r if r <= u16::MAX.into() => IntegerType::Uint16,
67                r if r <= u32::MAX.into() => IntegerType::Uint32,
68                r if r <= u64::MAX.into() => IntegerType::Uint64,
69                _ => IntegerType::Unbounded,
70            }
71        } else {
72            match (min, max) {
73                (mi, ma) if mi >= i8::MIN.into() && ma <= i8::MAX.into() => IntegerType::Int8,
74                (mi, ma) if mi >= i16::MIN.into() && ma <= i16::MAX.into() => IntegerType::Int16,
75                (mi, ma) if mi >= i32::MIN.into() && ma <= i32::MAX.into() => IntegerType::Int32,
76                (mi, ma) if mi >= i64::MIN.into() && ma <= i64::MAX.into() => IntegerType::Int64,
77                _ => IntegerType::Unbounded,
78            }
79        }
80    }
81
82    pub fn unpack_as_value_range(
83        &self,
84    ) -> Result<(&Option<ASN1Value>, &Option<ASN1Value>, bool), GrammarError> {
85        if let Constraint::Subtype(set) = self {
86            if let ElementOrSetOperation::Element(SubtypeElements::ValueRange {
87                min,
88                max,
89                extensible,
90            }) = &set.set
91            {
92                return Ok((min, max, *extensible));
93            }
94        }
95        Err(GrammarError::new(
96            &format!("Failed to unpack constraint as value range. Constraint: {self:?}"),
97            GrammarErrorType::UnpackingError,
98        ))
99    }
100
101    pub fn unpack_as_strict_value(&self) -> Result<(&ASN1Value, bool), GrammarError> {
102        if let Constraint::Subtype(set) = self {
103            if let ElementOrSetOperation::Element(SubtypeElements::SingleValue {
104                value,
105                extensible,
106            }) = &set.set
107            {
108                return Ok((value, *extensible));
109            }
110        }
111        Err(GrammarError::new(
112            &format!("Failed to unpack constraint as strict value. Constraint: {self:?}"),
113            GrammarErrorType::UnpackingError,
114        ))
115    }
116}
117
118/// A ContentConstraint.
119///
120/// _See: ITU-T X.682 (02/2021) 11_
121#[cfg_attr(test, derive(EnumDebug))]
122#[cfg_attr(not(test), derive(Debug))]
123#[derive(Clone, PartialEq)]
124pub enum ContentConstraint {
125    /// **X.682 11.4** _The abstract value of the octet string or bit string is the encoding of an
126    /// (any) abstract value of "Type" that is produced by the encoding rules that are applied to
127    /// the octet string or bit string._
128    Containing(ASN1Type),
129    /// **X.682 11.5** _The procedures identified by the object identifier value "Value" shall be
130    /// used to produce and to interpret the contents of the bit string or octet string. If the bit
131    /// string or octet string is already constrained, it is a specification error if these
132    /// procedures do not produce encodings that satisfy the constraint._
133    EncodedBy(ASN1Value),
134    /// **X.682 11.6** _The abstract value of the octet string or bit string is the encoding of an
135    /// (any) abstract value of "Type" that is produced by the encoding rules identified by the
136    /// object identifier value "Value"._
137    ContainingEncodedBy {
138        containing: ASN1Type,
139        encoded_by: ASN1Value,
140    },
141}
142
143#[cfg_attr(test, derive(EnumDebug))]
144#[cfg_attr(not(test), derive(Debug))]
145#[derive(Clone, PartialEq)]
146pub enum Parameter {
147    ValueParameter(ASN1Value),
148    TypeParameter(ASN1Type),
149    InformationObjectParameter(InformationObjectFields),
150    ObjectSetParameter(ObjectSet),
151}
152
153#[cfg_attr(test, derive(EnumDebug))]
154#[cfg_attr(not(test), derive(Debug))]
155#[derive(Clone, PartialEq)]
156pub enum SetOperator {
157    Intersection,
158    Union,
159    Except,
160}
161
162#[derive(Debug, Clone, PartialEq)]
163pub struct CompositeConstraint {
164    pub base_constraint: Box<Constraint>,
165    pub operation: Vec<(SetOperator, Box<Constraint>)>,
166    pub extensible: bool,
167}
168
169impl
170    From<(
171        Constraint,
172        Vec<(SetOperator, Constraint)>,
173        Option<ExtensionMarker>,
174    )> for CompositeConstraint
175{
176    fn from(
177        value: (
178            Constraint,
179            Vec<(SetOperator, Constraint)>,
180            Option<ExtensionMarker>,
181        ),
182    ) -> Self {
183        Self {
184            base_constraint: Box::new(value.0),
185            operation: value
186                .1
187                .into_iter()
188                .map(|(op, c)| (op, Box::new(c)))
189                .collect(),
190            extensible: value.2.is_some(),
191        }
192    }
193}
194
195#[cfg_attr(test, derive(EnumDebug))]
196#[cfg_attr(not(test), derive(Debug))]
197#[derive(Clone, PartialEq)]
198pub enum ComponentPresence {
199    Absent,
200    Present,
201    Unspecified,
202}
203
204/// Representation of a component constraint used for subtyping
205/// in ASN1 specifications
206#[derive(Debug, Clone, PartialEq)]
207pub struct InnerTypeConstraint {
208    pub is_partial: bool,
209    pub constraints: Vec<NamedConstraint>,
210}
211
212/// Representation of a single component within a component constraint
213/// in ASN1 specifications
214#[derive(Debug, Clone, PartialEq)]
215pub struct NamedConstraint {
216    pub identifier: String,
217    pub constraints: Vec<Constraint>,
218    pub presence: ComponentPresence,
219}
220
221/// Representation of a range constraint used for subtyping
222/// in ASN1 specifications
223#[derive(Debug, Clone, PartialEq)]
224pub struct ValueConstraint {
225    pub min_value: Option<ASN1Value>,
226    pub max_value: Option<ASN1Value>,
227    pub extensible: bool,
228}
229
230impl From<ASN1Value> for ValueConstraint {
231    fn from(value: ASN1Value) -> Self {
232        Self {
233            min_value: Some(value.clone()),
234            max_value: Some(value),
235            extensible: false,
236        }
237    }
238}
239
240impl From<(ASN1Value, RangeSeperator, ASN1Value)> for ValueConstraint {
241    fn from(value: (ASN1Value, RangeSeperator, ASN1Value)) -> Self {
242        Self {
243            min_value: Some(value.0),
244            max_value: Some(value.2),
245            extensible: false,
246        }
247    }
248}
249
250impl From<(ASN1Value, ExtensionMarker)> for ValueConstraint {
251    fn from(value: (ASN1Value, ExtensionMarker)) -> Self {
252        Self {
253            min_value: Some(value.0.clone()),
254            max_value: Some(value.0),
255            extensible: true,
256        }
257    }
258}
259
260impl From<(ASN1Value, RangeSeperator, ASN1Value, ExtensionMarker)> for ValueConstraint {
261    fn from(value: (ASN1Value, RangeSeperator, ASN1Value, ExtensionMarker)) -> Self {
262        Self {
263            min_value: Some(value.0),
264            max_value: Some(value.2),
265            extensible: true,
266        }
267    }
268}
269
270/// Representation of a table constraint used for subtyping
271/// in ASN1 specifications
272/// _See: ITU-T X.682 (02/2021) 10_
273#[derive(Debug, Clone, PartialEq)]
274pub struct TableConstraint {
275    pub object_set: ObjectSet,
276    pub linked_fields: Vec<RelationalConstraint>,
277}
278
279impl From<(ObjectSet, Option<Vec<RelationalConstraint>>)> for TableConstraint {
280    fn from(value: (ObjectSet, Option<Vec<RelationalConstraint>>)) -> Self {
281        Self {
282            object_set: value.0,
283            linked_fields: value.1.unwrap_or_default(),
284        }
285    }
286}
287
288/// Representation of a table's relational constraint
289/// _See: ITU-T X.682 (02/2021) 10.7_
290#[derive(Debug, Clone, PartialEq)]
291pub struct RelationalConstraint {
292    pub field_name: String,
293    /// The level is null if the field is in the outermost object set of the declaration.
294    /// The level is 1-n counting from the innermost object set of the declaration
295    pub level: usize,
296}
297
298impl From<(usize, &str)> for RelationalConstraint {
299    fn from(value: (usize, &str)) -> Self {
300        Self {
301            field_name: value.1.into(),
302            level: value.0,
303        }
304    }
305}
306
307/// Representation of a pattern constraint
308/// _See: ITU-T X.680 (02/2021) 51.9_
309#[derive(Debug, Clone, PartialEq)]
310pub struct PatternConstraint {
311    pub pattern: String,
312}
313
314impl From<&str> for PatternConstraint {
315    fn from(value: &str) -> Self {
316        Self {
317            pattern: value.into(),
318        }
319    }
320}
321
322/// Representation of a user-defined constraint
323/// _See: ITU-T X.682 (02/2021) 9_
324#[derive(Debug, Clone, PartialEq)]
325pub struct UserDefinedConstraint {
326    pub definition: String,
327}
328
329impl From<&str> for UserDefinedConstraint {
330    fn from(value: &str) -> Self {
331        Self {
332            definition: value.into(),
333        }
334    }
335}
336
337/// Representation of a property settings constraint
338/// _See: ITU-T X.680 (02/2021) 51.10_
339#[derive(Debug, Clone, PartialEq)]
340pub struct PropertySettings {
341    pub property_settings_list: Vec<PropertyAndSettingsPair>,
342}
343
344impl From<Vec<&str>> for PropertySettings {
345    fn from(_value: Vec<&str>) -> Self {
346        todo!()
347    }
348}
349
350#[cfg_attr(test, derive(EnumDebug))]
351#[cfg_attr(not(test), derive(Debug))]
352#[derive(Clone, PartialEq)]
353pub enum PropertyAndSettingsPair {
354    Basic(BasicSettings),
355    Date(DateSettings),
356    Year(YearSettings),
357    Time(TimeSettings),
358    LocalOrUtc(LocalOrUtcSettings),
359    IntervalType(IntervalTypeSettings),
360    StartEndPoint(StartEndPointSettings),
361    Recurrence(RecurrenceSettings),
362    Midnight(MidnightSettings),
363}
364
365impl TryFrom<(&str, &str)> for PropertyAndSettingsPair {
366    fn try_from(value: (&str, &str)) -> Result<PropertyAndSettingsPair, Box<dyn Error>> {
367        match value.0 {
368            BasicSettings::NAME => BasicSettings::from_str(value.1).map(Self::Basic),
369            DateSettings::NAME => DateSettings::from_str(value.1).map(Self::Date),
370            YearSettings::NAME => YearSettings::from_str(value.1).map(Self::Year),
371            TimeSettings::NAME => TimeSettings::from_str(value.1).map(Self::Time),
372            LocalOrUtcSettings::NAME => LocalOrUtcSettings::from_str(value.1).map(Self::LocalOrUtc),
373            IntervalTypeSettings::NAME => {
374                IntervalTypeSettings::from_str(value.1).map(Self::IntervalType)
375            }
376            StartEndPointSettings::NAME => {
377                StartEndPointSettings::from_str(value.1).map(Self::StartEndPoint)
378            }
379            RecurrenceSettings::NAME => RecurrenceSettings::from_str(value.1).map(Self::Recurrence),
380            MidnightSettings::NAME => MidnightSettings::from_str(value.1).map(Self::Midnight),
381            _ => Err("Unknown Settings value.".into()),
382        }
383    }
384
385    type Error = Box<dyn Error>;
386}
387
388pub trait PropertySetting {
389    const NAME: &'static str;
390
391    fn setting_name(&self) -> String;
392
393    fn from_str(value: &str) -> Result<Self, Box<dyn Error>>
394    where
395        Self: Sized;
396}
397
398#[cfg_attr(test, derive(EnumDebug))]
399#[cfg_attr(not(test), derive(Debug))]
400#[derive(Clone, PartialEq)]
401pub enum BasicSettings {
402    Date,
403    Time,
404    DateTime,
405    Interval,
406    RecInterval,
407}
408
409impl PropertySetting for BasicSettings {
410    const NAME: &'static str = "Basic";
411
412    fn setting_name(&self) -> String {
413        match self {
414            BasicSettings::Date => "Date".into(),
415            BasicSettings::Time => "Time".into(),
416            BasicSettings::DateTime => "Date-Time".into(),
417            BasicSettings::Interval => "Interval".into(),
418            BasicSettings::RecInterval => "Rec-Interval".into(),
419        }
420    }
421
422    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
423        match value {
424            "Date" => Ok(BasicSettings::Date),
425            "Time" => Ok(BasicSettings::Time),
426            "Date-Time" => Ok(BasicSettings::DateTime),
427            "Interval" => Ok(BasicSettings::Interval),
428            "Rec-Interval" => Ok(BasicSettings::RecInterval),
429            _ => Err("Unknown Settings value.".into()),
430        }
431    }
432}
433
434impl PropertySetting for DateSettings {
435    const NAME: &'static str = "Date";
436
437    fn setting_name(&self) -> String {
438        match self {
439            DateSettings::Century => "C".into(),
440            DateSettings::Year => "Y".into(),
441            DateSettings::YearMonth => "YM".into(),
442            DateSettings::YearMonthDay => "YMD".into(),
443            DateSettings::YearDay => "YD".into(),
444            DateSettings::YearWeek => "YW".into(),
445            DateSettings::YearWeekDay => "YWD".into(),
446        }
447    }
448
449    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
450        match value {
451            "C" => Ok(DateSettings::Century),
452            "Y" => Ok(DateSettings::Year),
453            "YM" => Ok(DateSettings::YearMonth),
454            "YMD" => Ok(DateSettings::YearMonthDay),
455            "YD" => Ok(DateSettings::YearDay),
456            "YW" => Ok(DateSettings::YearWeek),
457            "YWD" => Ok(DateSettings::YearWeekDay),
458            _ => Err("Unknown Settings value.".into()),
459        }
460    }
461}
462
463#[cfg_attr(test, derive(EnumDebug))]
464#[cfg_attr(not(test), derive(Debug))]
465#[derive(Clone, PartialEq)]
466pub enum DateSettings {
467    Century,
468    Year,
469    YearMonth,
470    YearMonthDay,
471    YearDay,
472    YearWeek,
473    YearWeekDay,
474}
475
476impl PropertySetting for YearSettings {
477    const NAME: &'static str = "Year";
478
479    fn setting_name(&self) -> String {
480        match self {
481            YearSettings::Basic => "Basic".into(),
482            YearSettings::Proleptic => "Proleptic".into(),
483            YearSettings::Negative => "Negative".into(),
484            YearSettings::Large(i) => format!("L{i}"),
485        }
486    }
487
488    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
489        match value {
490            "Basic" => Ok(YearSettings::Basic),
491            "Proleptic" => Ok(YearSettings::Proleptic),
492            "Negative" => Ok(YearSettings::Negative),
493            s if s.starts_with('L') => Ok(s[1..].parse().map(YearSettings::Large)?),
494            _ => Err("Unknown Settings value.".into()),
495        }
496    }
497}
498
499#[cfg_attr(test, derive(EnumDebug))]
500#[cfg_attr(not(test), derive(Debug))]
501#[derive(Clone, PartialEq)]
502pub enum YearSettings {
503    Basic,
504    Proleptic,
505    Negative,
506    Large(usize),
507}
508
509impl PropertySetting for TimeSettings {
510    const NAME: &'static str = "Time";
511
512    fn setting_name(&self) -> String {
513        match self {
514            TimeSettings::Hour => "H".into(),
515            TimeSettings::HourMinute => "HM".into(),
516            TimeSettings::HourMinuteSecond => "HMS".into(),
517            TimeSettings::HourDecimalFraction(i) => format!("HF{i}"),
518            TimeSettings::HourMinuteFraction(i) => format!("HMF{i}"),
519            TimeSettings::HourMinuteSecondFraction(i) => format!("HMSF{i}"),
520        }
521    }
522
523    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
524        match value {
525            "H" => Ok(TimeSettings::Hour),
526            "HM" => Ok(TimeSettings::HourMinute),
527            "HMS" => Ok(TimeSettings::HourMinuteSecond),
528            s if s.starts_with("HF") => {
529                Ok(s[2..].parse().map(TimeSettings::HourDecimalFraction)?)
530            }
531            s if s.starts_with("HMF") => {
532                Ok(s[3..].parse().map(TimeSettings::HourMinuteFraction)?)
533            }
534            s if s.starts_with("HMSF") => {
535                Ok(s[4..].parse().map(TimeSettings::HourMinuteSecondFraction)?)
536            }
537            _ => Err("Unknown Settings value.".into()),
538        }
539    }
540}
541
542#[cfg_attr(test, derive(EnumDebug))]
543#[cfg_attr(not(test), derive(Debug))]
544#[derive(Clone, PartialEq)]
545pub enum TimeSettings {
546    Hour,
547    HourMinute,
548    HourMinuteSecond,
549    HourDecimalFraction(usize),
550    HourMinuteFraction(usize),
551    HourMinuteSecondFraction(usize),
552}
553
554impl PropertySetting for LocalOrUtcSettings {
555    const NAME: &'static str = "Local-or-UTC";
556
557    fn setting_name(&self) -> String {
558        match self {
559            LocalOrUtcSettings::Local => "L".into(),
560            LocalOrUtcSettings::Utc => "Z".into(),
561            LocalOrUtcSettings::LocalAndDifference => "LD".into(),
562        }
563    }
564
565    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
566        match value {
567            "L" => Ok(LocalOrUtcSettings::Local),
568            "Z" => Ok(LocalOrUtcSettings::Utc),
569            "LD" => Ok(LocalOrUtcSettings::LocalAndDifference),
570            _ => Err("Unknown Settings value.".into()),
571        }
572    }
573}
574
575#[cfg_attr(test, derive(EnumDebug))]
576#[cfg_attr(not(test), derive(Debug))]
577#[derive(Clone, PartialEq)]
578pub enum LocalOrUtcSettings {
579    Local,
580    Utc,
581    LocalAndDifference,
582}
583
584impl PropertySetting for IntervalTypeSettings {
585    const NAME: &'static str = "Interval-type";
586
587    fn setting_name(&self) -> String {
588        match self {
589            IntervalTypeSettings::StartAndEnd => "SE".into(),
590            IntervalTypeSettings::Duration => "D".into(),
591            IntervalTypeSettings::StartAndDuration => "SD".into(),
592            IntervalTypeSettings::DurationAndEnd => "DE".into(),
593        }
594    }
595
596    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
597        match value {
598            "SE" => Ok(IntervalTypeSettings::StartAndEnd),
599            "D" => Ok(IntervalTypeSettings::Duration),
600            "SD" => Ok(IntervalTypeSettings::StartAndDuration),
601            "DE" => Ok(IntervalTypeSettings::DurationAndEnd),
602            _ => Err("Unknown Settings value.".into()),
603        }
604    }
605}
606
607#[cfg_attr(test, derive(EnumDebug))]
608#[cfg_attr(not(test), derive(Debug))]
609#[derive(Clone, PartialEq)]
610pub enum IntervalTypeSettings {
611    StartAndEnd,
612    Duration,
613    StartAndDuration,
614    DurationAndEnd,
615}
616
617impl PropertySetting for StartEndPointSettings {
618    const NAME: &'static str = "SE-point";
619
620    fn setting_name(&self) -> String {
621        match self {
622            StartEndPointSettings::Date => "Date".into(),
623            StartEndPointSettings::Time => "Time".into(),
624            StartEndPointSettings::DateTime => "Date-Time".into(),
625        }
626    }
627
628    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
629        match value {
630            "Date" => Ok(StartEndPointSettings::Date),
631            "Time" => Ok(StartEndPointSettings::Time),
632            "Date-Time" => Ok(StartEndPointSettings::DateTime),
633            _ => Err("Unknown Settings value.".into()),
634        }
635    }
636}
637
638#[cfg_attr(test, derive(EnumDebug))]
639#[cfg_attr(not(test), derive(Debug))]
640#[derive(Clone, PartialEq)]
641pub enum StartEndPointSettings {
642    Date,
643    Time,
644    DateTime,
645}
646
647impl PropertySetting for RecurrenceSettings {
648    const NAME: &'static str = "Recurrence";
649
650    fn setting_name(&self) -> String {
651        match self {
652            RecurrenceSettings::Unlimited => "Unlimited".into(),
653            RecurrenceSettings::Recurrences(i) => format!("R{i}"),
654        }
655    }
656
657    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
658        match value {
659            "Unlimited" => Ok(RecurrenceSettings::Unlimited),
660            s if s.starts_with('R') => Ok(s[1..].parse().map(RecurrenceSettings::Recurrences)?),
661            _ => Err("Unknown Settings value.".into()),
662        }
663    }
664}
665
666#[cfg_attr(test, derive(EnumDebug))]
667#[cfg_attr(not(test), derive(Debug))]
668#[derive(Clone, PartialEq)]
669pub enum RecurrenceSettings {
670    Unlimited,
671    Recurrences(usize),
672}
673
674impl PropertySetting for MidnightSettings {
675    const NAME: &'static str = "Midnight";
676
677    fn setting_name(&self) -> String {
678        match self {
679            MidnightSettings::StartOfDay => "Start".into(),
680            MidnightSettings::EndOfDay => "End".into(),
681        }
682    }
683
684    fn from_str(value: &str) -> Result<Self, Box<dyn Error>> {
685        match value {
686            "Start" => Ok(MidnightSettings::StartOfDay),
687            "End" => Ok(MidnightSettings::EndOfDay),
688            _ => Err("Unknown Settings value.".into()),
689        }
690    }
691}
692
693#[cfg_attr(test, derive(EnumDebug))]
694#[cfg_attr(not(test), derive(Debug))]
695#[derive(Clone, PartialEq)]
696pub enum MidnightSettings {
697    StartOfDay,
698    EndOfDay,
699}
700
701#[cfg_attr(test, derive(EnumDebug))]
702#[cfg_attr(not(test), derive(Debug))]
703#[derive(Clone, PartialEq)]
704pub enum SubtypeElements {
705    SingleValue {
706        value: ASN1Value,
707        extensible: bool,
708    },
709    ContainedSubtype {
710        subtype: ASN1Type,
711        extensible: bool,
712    },
713    ValueRange {
714        min: Option<ASN1Value>,
715        max: Option<ASN1Value>,
716        extensible: bool,
717    },
718    PermittedAlphabet(Box<ElementOrSetOperation>),
719    SizeConstraint(Box<ElementOrSetOperation>),
720    TypeConstraint(ASN1Type),
721    SingleTypeConstraint(Vec<Constraint>),
722    MultipleTypeConstraints(InnerTypeConstraint),
723    PatternConstraint(PatternConstraint),
724    UserDefinedConstraint(UserDefinedConstraint),
725    PropertySettings(PropertySettings), // DurationRange
726                                        // TimePointRange
727                                        // RecurrenceRange
728}
729
730impl From<(ASN1Value, Option<ExtensionMarker>)> for SubtypeElements {
731    fn from(value: (ASN1Value, Option<ExtensionMarker>)) -> Self {
732        Self::SingleValue {
733            value: value.0,
734            extensible: value.1.is_some(),
735        }
736    }
737}
738
739impl From<Constraint> for SubtypeElements {
740    fn from(value: Constraint) -> Self {
741        match value {
742            Constraint::Subtype(set) => Self::SizeConstraint(Box::new(set.set)),
743            _ => unreachable!(),
744        }
745    }
746}
747
748impl From<(Option<ExtensionMarker>, Vec<NamedConstraint>)> for SubtypeElements {
749    fn from(value: (Option<ExtensionMarker>, Vec<NamedConstraint>)) -> Self {
750        SubtypeElements::MultipleTypeConstraints(InnerTypeConstraint {
751            is_partial: value.0.is_some(),
752            constraints: value.1,
753        })
754    }
755}
756
757/// X.680 50. Element set specification
758///
759/// *50.1* _In some notations a set of elements of some identified type or information object class
760/// (the governor) can be specified. In such cases, the notation "ElementSetSpec" is used._
761#[derive(Debug, Clone, PartialEq)]
762pub struct ElementSetSpecs {
763    pub set: ElementOrSetOperation,
764    pub extensible: bool,
765}
766
767impl From<(ElementOrSetOperation, Option<ExtensionMarker>)> for ElementSetSpecs {
768    fn from(value: (ElementOrSetOperation, Option<ExtensionMarker>)) -> Self {
769        Self {
770            set: value.0,
771            extensible: value.1.is_some(),
772        }
773    }
774}
775
776#[cfg_attr(test, derive(EnumDebug))]
777#[cfg_attr(not(test), derive(Debug))]
778#[derive(Clone, PartialEq)]
779pub enum ElementOrSetOperation {
780    Element(SubtypeElements),
781    SetOperation(SetOperation),
782}
783
784#[derive(Debug, Clone, PartialEq)]
785pub struct SetOperation {
786    pub base: SubtypeElements, //TODO: Handle exclusions
787    pub operator: SetOperator,
788    pub operant: Box<ElementOrSetOperation>,
789}
790
791impl From<(SubtypeElements, SetOperator, ElementOrSetOperation)> for SetOperation {
792    fn from(value: (SubtypeElements, SetOperator, ElementOrSetOperation)) -> Self {
793        Self {
794            base: value.0,
795            operator: value.1,
796            operant: Box::new(value.2),
797        }
798    }
799}