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