rasn_compiler/intermediate/encoding_rules/
per_visible.rs

1use crate::intermediate::{
2    constraints::{Constraint, ElementOrSetOperation, SetOperation, SetOperator, SubtypeElements},
3    error::{GrammarError, GrammarErrorType},
4    types::{Choice, Enumerated},
5    ASN1Type, ASN1Value, CharacterStringType,
6};
7use std::{collections::BTreeMap, ops::AddAssign};
8
9pub fn to_per_visible(
10    constraints: Vec<Constraint>,
11    character_string_type: Option<CharacterStringType>,
12) -> Result<
13    (
14        PerVisibleRangeConstraints,
15        Option<PerVisibleAlphabetConstraints>,
16    ),
17    GrammarError,
18> {
19    Ok((
20        constraints
21            .iter()
22            .try_fold(PerVisibleRangeConstraints::default(), |mut acc, curr| {
23                let constraints = curr.try_into()?;
24                acc += constraints;
25                Ok(acc)
26            })?,
27        character_string_type
28            .map(|c| {
29                constraints.iter().try_fold(
30                    PerVisibleAlphabetConstraints::default_for(c),
31                    |mut acc, curr| {
32                        if let Some(mut constraints) =
33                            PerVisibleAlphabetConstraints::try_new(curr, c)?
34                        {
35                            acc += &mut constraints;
36                        }
37                        Ok(acc)
38                    },
39                )
40            })
41            .transpose()?,
42    ))
43}
44
45trait PerVisible {
46    fn per_visible(&self) -> bool;
47}
48
49#[derive(Debug, PartialEq)]
50pub enum CharsetSubset {
51    Single(char),
52    Range {
53        from: Option<char>,
54        to: Option<char>,
55    },
56}
57
58#[derive(Debug, PartialEq)]
59pub struct PerVisibleAlphabetConstraints {
60    string_type: CharacterStringType,
61    character_by_index: BTreeMap<usize, char>,
62    index_by_character: Option<BTreeMap<char, usize>>,
63    charset_subsets: Vec<CharsetSubset>,
64}
65
66impl PerVisibleAlphabetConstraints {
67    pub fn try_new(
68        constraint: &Constraint,
69        string_type: CharacterStringType,
70    ) -> Result<Option<Self>, GrammarError> {
71        // ITU-T X.691 clause 30.1, 30.6: Known-multiplier character strings types
72        match string_type {
73            // 30.1: Known-multiplier character string types
74            CharacterStringType::NumericString | CharacterStringType::PrintableString |
75            CharacterStringType::VisibleString | CharacterStringType::IA5String |
76            CharacterStringType::BMPString | CharacterStringType::UniversalString => {},
77            // 30.6: Non-known-multiplier character string types
78            _ => return Ok(None),
79        }
80        match constraint {
81            Constraint::Subtype(c) => match &c.set {
82                ElementOrSetOperation::Element(e) => Self::from_subtype_elem(Some(e), string_type),
83                ElementOrSetOperation::SetOperation(s) => Self::from_subtype_elem(
84                    fold_constraint_set(s, Some(&string_type.character_set()), false)?.as_ref(),
85                    string_type,
86                ),
87            },
88            _ => Ok(None),
89        }
90    }
91
92    fn from_subtype_elem(
93        element: Option<&SubtypeElements>,
94        string_type: CharacterStringType,
95    ) -> Result<Option<Self>, GrammarError> {
96        match element {
97            None => Ok(None),
98            Some(SubtypeElements::PermittedAlphabet(elem_or_set)) => {
99                let mut result = PerVisibleAlphabetConstraints::default_for(string_type);
100                match &**elem_or_set {
101                    ElementOrSetOperation::Element(e) => {
102                        if let Some(mut p) = Self::from_subtype_elem(Some(e), string_type)? {
103                            result += &mut p;
104                        }
105                    }
106                    ElementOrSetOperation::SetOperation(s) => {
107                        fn flatten_set(elems: &mut Vec<SubtypeElements>, set: &SetOperation) {
108                            elems.push(set.base.clone());
109                            match &*set.operant {
110                                ElementOrSetOperation::Element(e2) => elems.push(e2.clone()),
111                                ElementOrSetOperation::SetOperation(inner) => {
112                                    flatten_set(elems, inner)
113                                }
114                            }
115                        }
116                        let mut elems = Vec::new();
117                        flatten_set(&mut elems, s);
118                        for elem in elems {
119                            if let Some(mut p) = Self::from_subtype_elem(Some(&elem), string_type)?
120                            {
121                                result += &mut p;
122                            }
123                        }
124                    }
125                }
126                Ok(Some(result))
127            }
128            Some(SubtypeElements::SingleValue { value, extensible }) => match (value, extensible) {
129                (ASN1Value::String(s), false) => {
130                    let mut char_subset = s
131                        .clone()
132                        .chars()
133                        .map(|c| find_char_index(&string_type.character_set(), c).map(|i| (i, c)))
134                        .collect::<Result<Vec<(usize, char)>, _>>()?;
135                    char_subset.sort_by(|(a, _), (b, _)| a.cmp(b));
136                    Ok(Some(PerVisibleAlphabetConstraints {
137                        string_type,
138                        character_by_index: char_subset
139                            .iter()
140                            .map(|(_, c)| *c)
141                            .enumerate()
142                            .collect(),
143                        index_by_character: None,
144                        charset_subsets: s.chars().map(CharsetSubset::Single).collect(),
145                    }))
146                }
147                _ => Ok(None),
148            },
149            Some(SubtypeElements::ValueRange {
150                min,
151                max,
152                extensible,
153            }) => {
154                let char_set = string_type.character_set();
155                if *extensible {
156                    return Ok(None);
157                }
158                let (lower, upper) = match (min, max) {
159                    (Some(ASN1Value::String(min)), Some(ASN1Value::String(max))) => (
160                        find_string_index(min, &char_set)?,
161                        find_string_index(max, &char_set)?,
162                    ),
163                    (None, Some(ASN1Value::String(max))) => (0, find_string_index(max, &char_set)?),
164                    (Some(ASN1Value::String(min)), None) => {
165                        (find_string_index(min, &char_set)?, char_set.len() - 1)
166                    }
167                    _ => (0, char_set.len() - 1),
168                };
169                if lower > upper {
170                    return Err(GrammarError::new(&format!("Invalid range for permitted alphabet: Charset {char_set:?}; Range: {lower}..={upper}"), GrammarErrorType::UnpackingError
171                    ));
172                }
173                Ok(Some(PerVisibleAlphabetConstraints {
174                    string_type,
175                    character_by_index: char_set
176                        .iter()
177                        .filter_map(|(i, c)| (lower..=upper).contains(i).then_some(*c))
178                        .enumerate()
179                        .collect(),
180                    index_by_character: None,
181                    charset_subsets: vec![CharsetSubset::Range {
182                        from: char_set.get(&lower).copied(),
183                        to: char_set.get(&upper).copied(),
184                    }],
185                }))
186            }
187            Some(SubtypeElements::ContainedSubtype {
188                subtype,
189                extensible: _,
190            }) => {
191                if let ASN1Type::CharacterString(c_string) = subtype {
192                    let mut permitted_alphabet =
193                        PerVisibleAlphabetConstraints::default_for(string_type);
194                    for c in &c_string.constraints {
195                        if let Some(mut p) = PerVisibleAlphabetConstraints::try_new(c, c_string.ty)?
196                        {
197                            permitted_alphabet += &mut p
198                        }
199                    }
200                    Ok(Some(permitted_alphabet))
201                } else {
202                    Ok(None)
203                }
204            }
205            _ => Ok(None),
206        }
207    }
208
209    pub fn charset_subsets(&self) -> &Vec<CharsetSubset> {
210        &self.charset_subsets
211    }
212
213    pub fn finalize(&mut self) {
214        // sort charset_subsets by starting character to ensure consistent order
215        self.charset_subsets.sort_by_key(|subset| match subset {
216            CharsetSubset::Single(c) => *c,
217            CharsetSubset::Range { from, .. } => from.unwrap_or('\0'),
218        });
219        self.index_by_character = Some(
220            self.character_by_index
221                .iter()
222                .map(|(i, c)| (*c, *i))
223                .collect(),
224        );
225    }
226
227    pub fn default_for(string_type: CharacterStringType) -> Self {
228        Self {
229            character_by_index: BTreeMap::new(),
230            string_type,
231            index_by_character: None,
232            charset_subsets: vec![],
233        }
234    }
235}
236
237fn find_string_index(value: &str, char_set: &BTreeMap<usize, char>) -> Result<usize, GrammarError> {
238    let as_char = value.chars().next().unwrap();
239    find_char_index(char_set, as_char)
240}
241
242fn find_char_index(char_set: &BTreeMap<usize, char>, as_char: char) -> Result<usize, GrammarError> {
243    char_set
244        .iter()
245        .find_map(|(i, c)| (as_char == *c).then_some(*i))
246        .ok_or(GrammarError::new(
247            &format!("Character {as_char} is not in char set: {char_set:?}"),
248            GrammarErrorType::UnpackingError,
249        ))
250}
251
252impl AddAssign<&mut PerVisibleAlphabetConstraints> for PerVisibleAlphabetConstraints {
253    fn add_assign(&mut self, rhs: &mut PerVisibleAlphabetConstraints) {
254        // merge character index mappings
255        self.character_by_index.append(&mut rhs.character_by_index);
256        // merge charset subsets (ranges and singletons)
257        self.charset_subsets.append(&mut rhs.charset_subsets);
258    }
259}
260
261#[derive(Default)]
262pub struct PerVisibleRangeConstraints {
263    min: Option<i128>,
264    max: Option<i128>,
265    extensible: bool,
266    is_size_constraint: bool,
267}
268
269impl PerVisibleRangeConstraints {
270    pub fn default_unsigned() -> Self {
271        Self {
272            min: Some(0),
273            max: None,
274            extensible: false,
275            is_size_constraint: false,
276        }
277    }
278
279    pub fn is_extensible(&self) -> bool {
280        self.extensible
281    }
282
283    pub fn min<I: num::Integer + num::FromPrimitive>(&self) -> Option<I> {
284        self.min.and_then(|m| I::from_i128(m))
285    }
286
287    pub fn max<I: num::Integer + num::FromPrimitive>(&self) -> Option<I> {
288        self.max.and_then(|m| I::from_i128(m))
289    }
290
291    pub fn is_size_constraint(&self) -> bool {
292        self.is_size_constraint
293    }
294}
295
296impl From<&Enumerated> for PerVisibleRangeConstraints {
297    fn from(value: &Enumerated) -> Self {
298        PerVisibleRangeConstraints {
299            min: Some(0),
300            max: Some(value.extensible.map_or(value.members.len() - 1, |i| i - 1) as i128),
301            extensible: value.extensible.is_some(),
302            is_size_constraint: false,
303        }
304    }
305}
306
307impl From<&Choice> for PerVisibleRangeConstraints {
308    fn from(value: &Choice) -> Self {
309        PerVisibleRangeConstraints {
310            min: Some(0),
311            max: Some(value.extensible.map_or(value.options.len() - 1, |i| i - 1) as i128),
312            extensible: value.extensible.is_some(),
313            is_size_constraint: false,
314        }
315    }
316}
317
318impl AddAssign<PerVisibleRangeConstraints> for PerVisibleRangeConstraints {
319    fn add_assign(&mut self, rhs: PerVisibleRangeConstraints) {
320        self.min = self.min.max(rhs.min);
321        self.max = match (self.max, rhs.max) {
322            (Some(m1), Some(m2)) => Some(m1.min(m2)),
323            (None, Some(m)) | (Some(m), None) => Some(m),
324            _ => None,
325        };
326        self.extensible = self.extensible || rhs.extensible;
327        self.is_size_constraint = self.is_size_constraint || rhs.is_size_constraint;
328    }
329}
330
331impl TryFrom<&Constraint> for PerVisibleRangeConstraints {
332    type Error = GrammarError;
333
334    fn try_from(value: &Constraint) -> Result<PerVisibleRangeConstraints, Self::Error> {
335        match value {
336            Constraint::Subtype(c) => {
337                let mut per_visible: PerVisibleRangeConstraints = match &c.set {
338                    ElementOrSetOperation::Element(e) => Some(e).try_into(),
339                    ElementOrSetOperation::SetOperation(s) => {
340                        let mut v: PerVisibleRangeConstraints = fold_constraint_set(s, None, true)?.as_ref().try_into()?;
341                        if s.operator == SetOperator::Intersection && (matches!(s.base, SubtypeElements::SizeConstraint(_)) |
342                            matches!(*s.operant, ElementOrSetOperation::Element(SubtypeElements::SizeConstraint(_)))) {
343                            v.is_size_constraint = true;
344                        }
345                        Ok(v)
346                    }
347                }?;
348                if let (PerVisibleRangeConstraints { min, max, .. }, true) =
349                    (&mut per_visible, c.extensible)
350                {
351                    if min.or(*max).is_some() {
352                        per_visible.extensible = true;
353                    }
354                }
355                Ok(per_visible)
356            }
357            _ => Ok(Self::default()),
358        }
359    }
360}
361
362impl TryFrom<Option<&SubtypeElements>> for PerVisibleRangeConstraints {
363    type Error = GrammarError;
364    fn try_from(
365        value: Option<&SubtypeElements>,
366    ) -> Result<PerVisibleRangeConstraints, Self::Error> {
367        match value {
368            Some(SubtypeElements::PermittedAlphabet(_)) | None => Ok(Self::default()),
369            Some(SubtypeElements::SingleValue { value, extensible }) => {
370                let val = value.unwrap_as_integer().ok();
371                Ok(Self {
372                    min: val,
373                    max: val,
374                    extensible: *extensible,
375                    is_size_constraint: false,
376                })
377            }
378            Some(SubtypeElements::ValueRange {
379                min,
380                max,
381                extensible,
382            }) => Ok(Self {
383                min: min.as_ref().and_then(|i| i.unwrap_as_integer().ok()),
384                max: max.as_ref().and_then(|i| i.unwrap_as_integer().ok()),
385                extensible: *extensible,
386                is_size_constraint: false,
387            }),
388            Some(SubtypeElements::SizeConstraint(s)) => match &**s {
389                ElementOrSetOperation::Element(e) => <Option<&SubtypeElements> as TryInto<
390                    PerVisibleRangeConstraints,
391                >>::try_into(Some(e))
392                .map(|mut c| {
393                    c.is_size_constraint = true;
394                    c
395                }),
396                ElementOrSetOperation::SetOperation(s) => {
397                    <Option<&SubtypeElements> as TryInto<PerVisibleRangeConstraints>>::try_into(
398                        fold_constraint_set(s, None, true)?.as_ref(),
399                    )
400                    .map(|mut c| {
401                        c.is_size_constraint = true;
402                        c
403                    })
404                }
405            },
406            Some(SubtypeElements::ContainedSubtype {
407                subtype,
408                extensible: _,
409            }) => per_visible_range_constraints(
410                matches!(subtype, ASN1Type::Integer(_)),
411                subtype.constraints().unwrap_or(&vec![]),
412            ),
413            x => {
414                println!("{x:?}");
415                unreachable!()
416            }
417        }
418    }
419}
420
421impl PerVisible for Constraint {
422    fn per_visible(&self) -> bool {
423        match self {
424            Constraint::Subtype(s) => s.set.per_visible(),
425            _ => false,
426        }
427    }
428}
429
430impl PerVisible for ElementOrSetOperation {
431    fn per_visible(&self) -> bool {
432        match self {
433            ElementOrSetOperation::Element(e) => e.per_visible(),
434            ElementOrSetOperation::SetOperation(o) => {
435                o.operant.per_visible() || o.operant.per_visible()
436            }
437        }
438    }
439}
440
441impl PerVisible for SubtypeElements {
442    fn per_visible(&self) -> bool {
443        match self {
444            SubtypeElements::SingleValue {
445                value: _,
446                extensible: _,
447            } => true,
448            SubtypeElements::ContainedSubtype {
449                subtype: s,
450                extensible: _,
451            } => s
452                .constraints()
453                .is_some_and(|c| c.iter().any(|c| c.per_visible())),
454            SubtypeElements::ValueRange {
455                min: _,
456                max: _,
457                extensible: _,
458            } => true,
459            SubtypeElements::PermittedAlphabet(p) => p.per_visible(),
460            SubtypeElements::SizeConstraint(s) => s.per_visible(),
461            _ => false,
462        }
463    }
464}
465
466pub fn per_visible_range_constraints(
467    signed: bool,
468    constraint_list: &[Constraint],
469) -> Result<PerVisibleRangeConstraints, GrammarError> {
470    let mut constraints = if signed {
471        PerVisibleRangeConstraints::default()
472    } else {
473        PerVisibleRangeConstraints::default_unsigned()
474    };
475    for c in constraint_list.iter().filter(|c| c.per_visible()) {
476        constraints += c.try_into()?
477    }
478    Ok(constraints)
479}
480
481/// 10.3.21 If a constraint that is PER-visible is part of an INTERSECTION construction,
482/// then the resulting constraint is PER-visible, and consists of the INTERSECTION of
483/// all PER-visible parts (with the non-PER-visible parts ignored).
484/// If a constraint which is not PER-visible is part of a UNION construction,
485/// then the resulting constraint is not PER-visible.
486/// If a constraint has an EXCEPT clause, the EXCEPT and the following value set is completely ignored,
487/// whether the value set following the EXCEPT is PER-visible or not.
488fn fold_constraint_set(
489    set: &SetOperation,
490    char_set: Option<&BTreeMap<usize, char>>,
491    range_constraint: bool,
492) -> Result<Option<SubtypeElements>, GrammarError> {
493    let folded_operant = match &*set.operant {
494        ElementOrSetOperation::Element(e) => e.per_visible().then(|| e.clone()),
495        ElementOrSetOperation::SetOperation(s) => fold_constraint_set(s, char_set, range_constraint)?,
496    };
497    match (&set.base, &folded_operant) {
498        (base, Some(SubtypeElements::PermittedAlphabet(elem_or_set)))
499        | (SubtypeElements::PermittedAlphabet(elem_or_set), Some(base))
500        | (base, Some(SubtypeElements::SizeConstraint(elem_or_set)))
501        | (SubtypeElements::SizeConstraint(elem_or_set), Some(base)) => {
502            return fold_constraint_set(
503                &SetOperation {
504                    base: base.clone(),
505                    operator: set.operator.clone(),
506                    operant: elem_or_set.clone(),
507                },
508                char_set,
509                range_constraint,
510            )
511        }
512        (
513            SubtypeElements::ContainedSubtype {
514                subtype: _,
515                extensible: _,
516            },
517            None,
518        )
519        | (
520            SubtypeElements::ContainedSubtype {
521                subtype: _,
522                extensible: _,
523            },
524            Some(SubtypeElements::ContainedSubtype {
525                subtype: _,
526                extensible: _,
527            }),
528        ) => return Ok(None),
529        (
530            SubtypeElements::ContainedSubtype {
531                subtype: _,
532                extensible: _,
533            },
534            Some(c),
535        )
536        | (
537            c,
538            Some(SubtypeElements::ContainedSubtype {
539                subtype: _,
540                extensible: _,
541            }),
542        ) => return Ok(Some(c.clone())),
543        (SubtypeElements::PermittedAlphabet(elem_or_set), None)
544        | (SubtypeElements::SizeConstraint(elem_or_set), None) => {
545            return match &**elem_or_set {
546                ElementOrSetOperation::Element(e) => Ok(Some(e.clone())),
547                ElementOrSetOperation::SetOperation(s) => fold_constraint_set(s, char_set, range_constraint),
548            }
549        }
550        _ => (),
551    }
552
553    match set.operator {
554        SetOperator::Intersection => match (&set.base, &folded_operant) {
555            (b, _) if !b.per_visible() => Ok(None),
556            (b, None) => Ok(Some(b.clone())),
557            (b, Some(f)) if !f.per_visible() => Ok(Some(b.clone())),
558            (
559                SubtypeElements::SingleValue {
560                    value: v1,
561                    extensible: x1,
562                },
563                Some(SubtypeElements::SingleValue {
564                    value: v2,
565                    extensible: x2,
566                }),
567            ) => match (v1, v2, char_set.is_some()) {
568                (ASN1Value::Integer(_), ASN1Value::String(_), false)
569                | (ASN1Value::String(_), ASN1Value::Integer(_), true) => Ok(Some(set.base.clone())),
570                (ASN1Value::String(_), ASN1Value::Integer(_), false)
571                | (ASN1Value::Integer(_), ASN1Value::String(_), true) => Ok(folded_operant),
572                (ASN1Value::Integer(i1), ASN1Value::Integer(i2), _) => {
573                    if *i1 != *i2 {
574                        Err(GrammarError::new(
575                            &format!(
576                                "Empty intersection result for {:?} and {:?}",
577                                v1,
578                                ASN1Value::Integer(*i2)
579                            ),
580                            GrammarErrorType::UnpackingError,
581                        ))
582                    } else {
583                        Ok(Some(SubtypeElements::SingleValue {
584                            value: ASN1Value::Integer(*i2),
585                            extensible: *x1 || *x2,
586                        }))
587                    }
588                }
589                (ASN1Value::String(s1), ASN1Value::String(s2), _) => {
590                    if *x1 || *x2 {
591                        Ok(None)
592                    } else {
593                        let permitted: String = s2.chars().filter(|c| s1.contains(*c)).collect();
594                        if permitted.is_empty() {
595                            return Err(GrammarError::new(
596                                &format!(
597                                    "Empty intersection result for {:?} and {:?}",
598                                    v1,
599                                    ASN1Value::String(s2.clone())
600                                ),
601                                GrammarErrorType::UnpackingError,
602                            ));
603                        }
604                        Ok(Some(SubtypeElements::SingleValue {
605                            value: ASN1Value::String(permitted),
606                            extensible: false,
607                        }))
608                    }
609                }
610                (v1, v2, _) => Err(GrammarError::new(
611                    &format!("Unsupported operation for ASN1Values {v1:?} and {v2:?}"),
612                    GrammarErrorType::UnpackingError,
613                )),
614            },
615            (
616                SubtypeElements::SingleValue {
617                    value,
618                    extensible: x1,
619                },
620                Some(SubtypeElements::ValueRange {
621                    min,
622                    max,
623                    extensible: x2,
624                }),
625            ) => intersect_single_and_range(value, min.as_ref(), max.as_ref(), *x1, *x2, char_set, range_constraint),
626            (
627                SubtypeElements::ValueRange {
628                    min,
629                    max,
630                    extensible: x2,
631                },
632                Some(SubtypeElements::SingleValue {
633                    value,
634                    extensible: x1,
635                }),
636            ) => intersect_single_and_range(value, min.as_ref(), max.as_ref(), *x1, *x2, char_set, range_constraint),
637            (
638                _,
639                Some(SubtypeElements::SingleValue {
640                    value: v,
641                    extensible: x,
642                }),
643            ) => Ok(Some(SubtypeElements::SingleValue {
644                value: v.clone(),
645                extensible: *x,
646            })),
647            (
648                SubtypeElements::ValueRange {
649                    min: min1,
650                    max: max1,
651                    extensible: x1,
652                },
653                Some(SubtypeElements::ValueRange {
654                    min: min2,
655                    max: max2,
656                    extensible: x2,
657                }),
658            ) => {
659                match (min1, max1, &min2, &max2) {
660                    (Some(ASN1Value::Integer(_)), _, Some(ASN1Value::String(_)), _)
661                    | (_, Some(ASN1Value::Integer(_)), Some(ASN1Value::String(_)), _)
662                    | (Some(ASN1Value::Integer(_)), _, _, Some(ASN1Value::String(_)))
663                    | (_, Some(ASN1Value::Integer(_)), _, Some(ASN1Value::String(_))) => {
664                        return if char_set.is_none() {
665                            Ok(Some(set.base.clone()))
666                        } else if !x2 {
667                            Ok(folded_operant.clone())
668                        } else {
669                            Ok(None)
670                        }
671                    }
672                    (Some(ASN1Value::String(_)), _, Some(ASN1Value::Integer(_)), _)
673                    | (_, Some(ASN1Value::String(_)), Some(ASN1Value::Integer(_)), _)
674                    | (Some(ASN1Value::String(_)), _, _, Some(ASN1Value::Integer(_)))
675                    | (_, Some(ASN1Value::String(_)), _, Some(ASN1Value::Integer(_))) => {
676                        return if char_set.is_none() {
677                            Ok(folded_operant)
678                        } else if !x1 {
679                            Ok(Some(set.base.clone()))
680                        } else {
681                            Ok(None)
682                        }
683                    }
684                    _ => (),
685                };
686                let min = compare_optional_asn1values(min1.as_ref(), min2.as_ref(), |m1, m2| {
687                    m1.max(m2, char_set)
688                })?;
689                let max = compare_optional_asn1values(max1.as_ref(), max2.as_ref(), |m1, m2| {
690                    m1.min(m2, char_set)
691                })?;
692                Ok(Some(SubtypeElements::ValueRange {
693                    min,
694                    max,
695                    extensible: *x1 || *x2,
696                }))
697            }
698            _ => unreachable!(),
699        },
700        SetOperator::Union => match (&set.base, folded_operant) {
701            (b, _) if !b.per_visible() => Ok(None),
702            (_, None) => Ok(None),
703            (_, Some(f)) if !f.per_visible() => Ok(None),
704            (
705                SubtypeElements::SingleValue {
706                    value: v1,
707                    extensible: x1,
708                },
709                Some(SubtypeElements::SingleValue {
710                    value: v2,
711                    extensible: x2,
712                }),
713            ) => match (v1, &v2) {
714                (ASN1Value::String(_), ASN1Value::Integer(_))
715                | (ASN1Value::Integer(_), ASN1Value::String(_)) => Ok(None),
716                (ASN1Value::Integer(v1_int), ASN1Value::Integer(v2_int)) => {
717                    Ok(Some(SubtypeElements::ValueRange {
718                        min: Some(ASN1Value::Integer(*v2_int.min(v1_int))),
719                        max: Some(ASN1Value::Integer(*v2_int.max(v1_int))),
720                        extensible: *x1 || x2,
721                    }))
722                }
723                (ASN1Value::String(v1_str), ASN1Value::String(v2_str)) => {
724                    let mut v2_clone = v2_str.clone();
725                    v2_clone.extend(v1_str.chars().filter(|c| !v2_str.contains(*c)));
726                    Ok(Some(SubtypeElements::SingleValue {
727                        value: ASN1Value::String(v2_clone),
728                        extensible: *x1 || x2,
729                    }))
730                }
731                _ => Err(GrammarError::new(
732                    &format!("Unsupported operation for ASN1Values {v1:?} and {v2:?}"),
733                    GrammarErrorType::UnpackingError,
734                )),
735            },
736            (
737                SubtypeElements::ValueRange {
738                    min,
739                    max,
740                    extensible: x1,
741                },
742                Some(SubtypeElements::SingleValue {
743                    value: v,
744                    extensible: x2,
745                }),
746            ) => union_single_and_range(&v, min.as_ref(), char_set, max.as_ref(), *x1, x2, range_constraint),
747            (
748                SubtypeElements::SingleValue {
749                    value: v,
750                    extensible: x1,
751                },
752                Some(SubtypeElements::ValueRange {
753                    min,
754                    max,
755                    extensible: x2,
756                }),
757            ) => union_single_and_range(v, min.as_ref(), char_set, max.as_ref(), *x1, x2, range_constraint),
758            (
759                SubtypeElements::ValueRange {
760                    min: min1,
761                    max: max1,
762                    extensible: x1,
763                },
764                Some(SubtypeElements::ValueRange {
765                    min: min2,
766                    max: max2,
767                    extensible: x2,
768                }),
769            ) => {
770                match (min1, max1, &min2, &max2) {
771                    (Some(ASN1Value::Integer(_)), _, Some(ASN1Value::String(_)), _)
772                    | (Some(ASN1Value::String(_)), _, Some(ASN1Value::Integer(_)), _)
773                    | (_, Some(ASN1Value::Integer(_)), Some(ASN1Value::String(_)), _)
774                    | (_, Some(ASN1Value::String(_)), Some(ASN1Value::Integer(_)), _)
775                    | (Some(ASN1Value::Integer(_)), _, _, Some(ASN1Value::String(_)))
776                    | (Some(ASN1Value::String(_)), _, _, Some(ASN1Value::Integer(_)))
777                    | (_, Some(ASN1Value::Integer(_)), _, Some(ASN1Value::String(_)))
778                    | (_, Some(ASN1Value::String(_)), _, Some(ASN1Value::Integer(_))) => {
779                        return Ok(None)
780                    }
781                    _ => (),
782                };
783                let min = compare_optional_asn1values(min1.as_ref(), min2.as_ref(), |m1, m2| {
784                    m1.min(m2, char_set)
785                })?;
786                let max = compare_optional_asn1values(max1.as_ref(), max2.as_ref(), |m1, m2| {
787                    m1.max(m2, char_set)
788                })?;
789                Ok(Some(SubtypeElements::ValueRange {
790                    min,
791                    max,
792                    extensible: *x1 || x2,
793                }))
794            }
795            _ => unreachable!(),
796        },
797        SetOperator::Except => {
798            if set.base.per_visible() {
799                Ok(Some(set.base.clone()))
800            } else {
801                Ok(None)
802            }
803        }
804    }
805}
806
807fn intersect_single_and_range(
808    value: &ASN1Value,
809    min: Option<&ASN1Value>,
810    max: Option<&ASN1Value>,
811    x1: bool,
812    x2: bool,
813    char_set: Option<&BTreeMap<usize, char>>,
814    range_constraint: bool,
815) -> Result<Option<SubtypeElements>, GrammarError> {
816    match (value, min, max, x1 || x2, char_set, range_constraint) {
817        (ASN1Value::Integer(_), _, Some(ASN1Value::String(_)), _, Some(_), _)
818        | (ASN1Value::Integer(_), Some(ASN1Value::String(_)), _, _, Some(_), _) => {
819            if x2 {
820                Ok(None)
821            } else {
822                Ok(Some(SubtypeElements::ValueRange {
823                    min: min.cloned(),
824                    max: max.cloned(),
825                    extensible: false,
826                }))
827            }
828        }
829        (ASN1Value::String(_), Some(ASN1Value::Integer(_)), _, _, Some(_), _)
830        | (ASN1Value::String(_), _, Some(ASN1Value::Integer(_)), _, Some(_), _) => {
831            if x1 {
832                Ok(None)
833            } else {
834                Ok(Some(SubtypeElements::SingleValue {
835                    value: value.clone(),
836                    extensible: false,
837                }))
838            }
839        }
840        (ASN1Value::Integer(_), _, Some(ASN1Value::String(_)), _, None, _)
841        | (ASN1Value::Integer(_), Some(ASN1Value::String(_)), _, _, None, _) => {
842            Ok(Some(SubtypeElements::SingleValue {
843                value: value.clone(),
844                extensible: x1,
845            }))
846        }
847        (ASN1Value::String(_), Some(ASN1Value::Integer(_)), _, _, None, _)
848        | (ASN1Value::String(_), _, Some(ASN1Value::Integer(_)), _, None, _) => {
849            Ok(Some(SubtypeElements::ValueRange {
850                min: min.cloned(),
851                max: max.cloned(),
852                extensible: x2,
853            }))
854        }
855        (ASN1Value::Integer(v), _, _, extensible, _, _) => Ok(Some(SubtypeElements::SingleValue {
856            value: ASN1Value::Integer(*v),
857            extensible,
858        })),
859        (_, _, _, true, _, _) => Ok(None),
860        (ASN1Value::String(s1), _, _, _, Some(chars), _) => {
861            let indices = s1
862                .chars()
863                .map(|c| find_char_index(chars, c).map(|i| (c, i)))
864                .collect::<Result<Vec<(char, usize)>, _>>()?;
865            let s_min = indices
866                .iter()
867                .min_by(|(_, a), (_, b)| a.cmp(b))
868                .map(|(c, _)| ASN1Value::String(format!("{c}")));
869            let s_max = indices
870                .iter()
871                .max_by(|(_, a), (_, b)| a.cmp(b))
872                .map(|(c, _)| ASN1Value::String(format!("{c}")));
873            Ok(Some(SubtypeElements::ValueRange {
874                min: compare_optional_asn1values(s_min.as_ref(), min, |a, b| a.max(b, char_set))?,
875                max: compare_optional_asn1values(s_max.as_ref(), max, |a, b| a.min(b, char_set))?,
876                extensible: false,
877            }))
878        }
879        (ASN1Value::String(_), _, _, _, None, true) => Ok(None),
880        _ => Err(GrammarError::new(
881            &format!("Unsupported operation for ASN1Values {value:?} and {min:?}..{max:?}"),
882            GrammarErrorType::UnpackingError,
883        )),
884    }
885}
886
887fn union_single_and_range(
888    v: &ASN1Value,
889    min: Option<&ASN1Value>,
890    char_set: Option<&BTreeMap<usize, char>>,
891    max: Option<&ASN1Value>,
892    x1: bool,
893    x2: bool,
894    range_constraint: bool,
895) -> Result<Option<SubtypeElements>, GrammarError> {
896    match (v, min, max, x1 || x2, char_set, range_constraint) {
897        (ASN1Value::Integer(_), _, Some(ASN1Value::String(_)), _, _, _)
898        | (ASN1Value::Integer(_), Some(ASN1Value::String(_)), _, _, _, _)
899        | (ASN1Value::String(_), Some(ASN1Value::Integer(_)), _, _, _, _)
900        | (ASN1Value::String(_), _, Some(ASN1Value::Integer(_)), _, _, _) => Ok(None),
901        (ASN1Value::Integer(_), _, _, extensible, _, _) => Ok(Some(SubtypeElements::ValueRange {
902            min: compare_optional_asn1values(Some(v), min, |a, b| a.min(b, char_set))?,
903            max: compare_optional_asn1values(Some(v), max, |a, b| a.max(b, char_set))?,
904            extensible,
905        })),
906        (_, _, _, true, _, _) => Ok(None),
907        (ASN1Value::String(s1), Some(ASN1Value::String(min)), Some(ASN1Value::String(max)), _, Some(chars), _) => {
908            let min_i = find_string_index(min, chars)?;
909            let max_i = find_string_index(max, chars)?;
910            let mut indicies = std::collections::BTreeSet::new();
911            for c in s1.chars() {
912                indicies.insert(find_char_index(chars, c)?);
913            }
914            for i in min_i..max_i {
915                indicies.insert(i);
916            }
917            let mut indices = indicies.iter().collect::<Vec<_>>();
918            indices.sort();
919            let mut last = indices[0];
920            let mut contiguous = true;
921            for v in indices[1..].iter() {
922                if **v != last + 1 {
923                    contiguous = false;
924                    break;
925                }
926                last = *v;
927            }
928            if contiguous {
929                let min_i = indices[0];
930                let max_i = indices[indices.len() - 1];
931                Ok(Some(SubtypeElements::ValueRange {
932                    min: Some(ASN1Value::String(chars.get(&min_i).unwrap().to_string())),
933                    max: Some(ASN1Value::String(chars.get(&max_i).unwrap().to_string())),
934                    extensible: false,
935                }))
936            } else {
937                let mut c = s1.to_string();
938                for i in min_i..=max_i {
939                    c.push(*chars.get(&i).unwrap());
940                }
941                Ok(Some(SubtypeElements::SingleValue {
942                    value: ASN1Value::String(c),
943                    extensible: false,
944                }))
945            }
946        },
947        (ASN1Value::String(_), _, _, _, None, true) => Ok(None),
948        _ => Err(GrammarError::new(
949            &format!("Unsupported operation for values {v:?} and {min:?}..{max:?}"),
950            GrammarErrorType::UnpackingError,
951        )),
952    }
953}
954
955fn compare_optional_asn1values(
956    first: Option<&ASN1Value>,
957    second: Option<&ASN1Value>,
958    predicate: impl Fn(&ASN1Value, &ASN1Value) -> Result<ASN1Value, GrammarError>,
959) -> Result<Option<ASN1Value>, GrammarError> {
960    match (first, second) {
961        (Some(f), Some(s)) => Ok(Some(predicate(f, s)?)),
962        (None, Some(s)) => Ok(Some(s.clone())),
963        (Some(f), None) => Ok(Some(f.clone())),
964        _ => Ok(None),
965    }
966}
967
968#[cfg(test)]
969mod tests {
970    use crate::intermediate::{constraints::*, *};
971
972    use super::*;
973
974    #[test]
975    fn initializes_per_visible_alphabet_from_single_value() {
976        assert_eq!(
977            PerVisibleAlphabetConstraints::try_new(
978                &Constraint::Subtype(ElementSetSpecs {
979                    extensible: false,
980                    set: ElementOrSetOperation::Element(SubtypeElements::SingleValue {
981                        value: ASN1Value::String("ABCDEF".to_owned()),
982                        extensible: false
983                    })
984                }),
985                CharacterStringType::IA5String,
986            )
987            .unwrap()
988            .unwrap(),
989            PerVisibleAlphabetConstraints {
990                string_type: CharacterStringType::IA5String,
991                character_by_index: [(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E'), (5, 'F')]
992                    .into_iter()
993                    .collect(),
994                index_by_character: None,
995                charset_subsets: vec![
996                    CharsetSubset::Single('A'),
997                    CharsetSubset::Single('B'),
998                    CharsetSubset::Single('C'),
999                    CharsetSubset::Single('D'),
1000                    CharsetSubset::Single('E'),
1001                    CharsetSubset::Single('F')
1002                ]
1003            }
1004        );
1005        assert_eq!(
1006            PerVisibleAlphabetConstraints::try_new(
1007                &Constraint::Subtype(ElementSetSpecs {
1008                    extensible: false,
1009                    set: ElementOrSetOperation::Element(SubtypeElements::SingleValue {
1010                        value: ASN1Value::String("132".to_owned()),
1011                        extensible: false
1012                    })
1013                }),
1014                CharacterStringType::NumericString
1015            )
1016            .unwrap()
1017            .unwrap(),
1018            PerVisibleAlphabetConstraints {
1019                string_type: CharacterStringType::NumericString,
1020                character_by_index: [(0, '1'), (2, '3'), (1, '2')].into_iter().collect(),
1021                index_by_character: None,
1022                charset_subsets: vec![
1023                    CharsetSubset::Single('1'),
1024                    CharsetSubset::Single('3'),
1025                    CharsetSubset::Single('2')
1026                ]
1027            }
1028        )
1029    }
1030
1031    #[test]
1032    fn initializes_per_visible_alphabet_from_range_value() {
1033        assert_eq!(
1034            PerVisibleAlphabetConstraints::try_new(
1035                &Constraint::Subtype(ElementSetSpecs {
1036                    extensible: false,
1037                    set: ElementOrSetOperation::Element(SubtypeElements::ValueRange {
1038                        min: Some(ASN1Value::String("A".to_owned())),
1039                        max: Some(ASN1Value::String("F".to_owned())),
1040                        extensible: false
1041                    })
1042                }),
1043                CharacterStringType::IA5String,
1044            )
1045            .unwrap()
1046            .unwrap(),
1047            PerVisibleAlphabetConstraints {
1048                string_type: CharacterStringType::IA5String,
1049                character_by_index: [(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E'), (5, 'F')]
1050                    .into_iter()
1051                    .collect(),
1052                index_by_character: None,
1053                charset_subsets: vec![CharsetSubset::Range {
1054                    from: Some('A'),
1055                    to: Some('F')
1056                }]
1057            }
1058        );
1059        assert_eq!(
1060            PerVisibleAlphabetConstraints::try_new(
1061                &Constraint::Subtype(ElementSetSpecs {
1062                    extensible: false,
1063                    set: ElementOrSetOperation::Element(SubtypeElements::ValueRange {
1064                        min: None,
1065                        max: Some(ASN1Value::String("3".to_owned())),
1066                        extensible: false
1067                    })
1068                }),
1069                CharacterStringType::NumericString
1070            )
1071            .unwrap()
1072            .unwrap(),
1073            PerVisibleAlphabetConstraints {
1074                string_type: CharacterStringType::NumericString,
1075                character_by_index: [(0, ' '), (1, '0'), (2, '1'), (3, '2'), (4, '3')]
1076                    .into_iter()
1077                    .collect(),
1078                index_by_character: None,
1079                charset_subsets: vec![CharsetSubset::Range {
1080                    from: Some(' '),
1081                    to: Some('3')
1082                }]
1083            }
1084        )
1085    }
1086
1087    #[test]
1088    fn folds_single_value_alphabet_constraints() {
1089        assert_eq!(
1090            fold_constraint_set(
1091                &SetOperation {
1092                    base: SubtypeElements::SingleValue {
1093                        value: ASN1Value::String("ABC".into()),
1094                        extensible: false
1095                    },
1096                    operator: SetOperator::Intersection,
1097                    operant: Box::new(ElementOrSetOperation::Element(
1098                        SubtypeElements::SingleValue {
1099                            value: ASN1Value::String("CDE".into()),
1100                            extensible: false
1101                        }
1102                    ))
1103                },
1104                Some(&CharacterStringType::IA5String.character_set()),
1105                false
1106            )
1107            .unwrap()
1108            .unwrap(),
1109            SubtypeElements::SingleValue {
1110                value: ASN1Value::String("C".into()),
1111                extensible: false
1112            }
1113        );
1114        assert_eq!(
1115            fold_constraint_set(
1116                &SetOperation {
1117                    base: SubtypeElements::SingleValue {
1118                        value: ASN1Value::String("ABC".into()),
1119                        extensible: false
1120                    },
1121                    operator: SetOperator::Union,
1122                    operant: Box::new(ElementOrSetOperation::Element(
1123                        SubtypeElements::SingleValue {
1124                            value: ASN1Value::String("CDE".into()),
1125                            extensible: false
1126                        }
1127                    ))
1128                },
1129                Some(&CharacterStringType::IA5String.character_set()),
1130                false
1131            )
1132            .unwrap()
1133            .unwrap(),
1134            SubtypeElements::SingleValue {
1135                value: ASN1Value::String("CDEAB".into()),
1136                extensible: false
1137            }
1138        )
1139    }
1140
1141    #[test]
1142    fn folds_range_value_alphabet_constraints() {
1143        assert_eq!(
1144            fold_constraint_set(
1145                &SetOperation {
1146                    base: SubtypeElements::ValueRange {
1147                        min: Some(ASN1Value::String("A".into())),
1148                        max: Some(ASN1Value::String("C".into())),
1149                        extensible: false
1150                    },
1151                    operator: SetOperator::Intersection,
1152                    operant: Box::new(ElementOrSetOperation::Element(
1153                        SubtypeElements::SingleValue {
1154                            value: ASN1Value::String("CDE".into()),
1155                            extensible: false
1156                        }
1157                    ))
1158                },
1159                Some(&CharacterStringType::PrintableString.character_set()),
1160                false,
1161            )
1162            .unwrap()
1163            .unwrap(),
1164            SubtypeElements::ValueRange {
1165                min: Some(ASN1Value::String("C".into())),
1166                max: Some(ASN1Value::String("C".into())),
1167                extensible: false
1168            }
1169        );
1170        assert_eq!(
1171            fold_constraint_set(
1172                &SetOperation {
1173                    base: SubtypeElements::ValueRange {
1174                        min: Some(ASN1Value::String("A".into())),
1175                        max: Some(ASN1Value::String("C".into())),
1176                        extensible: false
1177                    },
1178                    operator: SetOperator::Union,
1179                    operant: Box::new(ElementOrSetOperation::Element(
1180                        SubtypeElements::SingleValue {
1181                            value: ASN1Value::String("CDE".into()),
1182                            extensible: false
1183                        }
1184                    ))
1185                },
1186                Some(&CharacterStringType::PrintableString.character_set()),
1187                false
1188            )
1189            .unwrap()
1190            .unwrap(),
1191            SubtypeElements::ValueRange {
1192                min: Some(ASN1Value::String("A".into())),
1193                max: Some(ASN1Value::String("E".into())),
1194                extensible: false
1195            }
1196        )
1197    }
1198
1199    #[test]
1200    fn folds_range_values_alphabet_constraints() {
1201        assert_eq!(
1202            fold_constraint_set(
1203                &SetOperation {
1204                    base: SubtypeElements::ValueRange {
1205                        min: Some(ASN1Value::String("A".into())),
1206                        max: Some(ASN1Value::String("C".into())),
1207                        extensible: false
1208                    },
1209                    operator: SetOperator::Intersection,
1210                    operant: Box::new(ElementOrSetOperation::Element(
1211                        SubtypeElements::ValueRange {
1212                            min: Some(ASN1Value::String("C".into())),
1213                            max: Some(ASN1Value::String("E".into())),
1214                            extensible: false
1215                        }
1216                    ))
1217                },
1218                Some(&CharacterStringType::VisibleString.character_set()),
1219                false,
1220            )
1221            .unwrap()
1222            .unwrap(),
1223            SubtypeElements::ValueRange {
1224                min: Some(ASN1Value::String("C".into())),
1225                max: Some(ASN1Value::String("C".into())),
1226                extensible: false
1227            }
1228        );
1229        assert_eq!(
1230            fold_constraint_set(
1231                &SetOperation {
1232                    base: SubtypeElements::ValueRange {
1233                        min: Some(ASN1Value::String("A".into())),
1234                        max: Some(ASN1Value::String("C".into())),
1235                        extensible: false
1236                    },
1237                    operator: SetOperator::Union,
1238                    operant: Box::new(ElementOrSetOperation::Element(
1239                        SubtypeElements::ValueRange {
1240                            min: Some(ASN1Value::String("C".into())),
1241                            max: Some(ASN1Value::String("E".into())),
1242                            extensible: false
1243                        }
1244                    ))
1245                },
1246                Some(&CharacterStringType::PrintableString.character_set()),
1247                false
1248            )
1249            .unwrap()
1250            .unwrap(),
1251            SubtypeElements::ValueRange {
1252                min: Some(ASN1Value::String("A".into())),
1253                max: Some(ASN1Value::String("E".into())),
1254                extensible: false
1255            }
1256        )
1257    }
1258
1259    #[test]
1260    fn folds_single_value_numeric_constraints() {
1261        assert_eq!(
1262            fold_constraint_set(
1263                &SetOperation {
1264                    base: SubtypeElements::SingleValue {
1265                        value: ASN1Value::Integer(4),
1266                        extensible: false
1267                    },
1268                    operator: SetOperator::Intersection,
1269                    operant: Box::new(ElementOrSetOperation::Element(
1270                        SubtypeElements::SingleValue {
1271                            value: ASN1Value::Integer(4),
1272                            extensible: true
1273                        }
1274                    ))
1275                },
1276                None,
1277                true
1278            )
1279            .unwrap()
1280            .unwrap(),
1281            SubtypeElements::SingleValue {
1282                value: ASN1Value::Integer(4),
1283                extensible: true
1284            }
1285        );
1286    }
1287
1288    #[test]
1289    fn folds_range_value_integer_constraints() {
1290        assert_eq!(
1291            fold_constraint_set(
1292                &SetOperation {
1293                    base: SubtypeElements::ValueRange {
1294                        min: Some(ASN1Value::Integer(-1)),
1295                        max: Some(ASN1Value::Integer(3)),
1296                        extensible: false
1297                    },
1298                    operator: SetOperator::Intersection,
1299                    operant: Box::new(ElementOrSetOperation::Element(
1300                        SubtypeElements::SingleValue {
1301                            value: ASN1Value::Integer(2),
1302                            extensible: false
1303                        }
1304                    ))
1305                },
1306                None,
1307                true
1308            )
1309            .unwrap()
1310            .unwrap(),
1311            SubtypeElements::SingleValue {
1312                value: ASN1Value::Integer(2),
1313                extensible: false
1314            }
1315        );
1316        assert_eq!(
1317            fold_constraint_set(
1318                &SetOperation {
1319                    base: SubtypeElements::ValueRange {
1320                        min: Some(ASN1Value::Integer(-1)),
1321                        max: Some(ASN1Value::Integer(5)),
1322                        extensible: false
1323                    },
1324                    operator: SetOperator::Union,
1325                    operant: Box::new(ElementOrSetOperation::Element(
1326                        SubtypeElements::SingleValue {
1327                            value: ASN1Value::Integer(-3),
1328                            extensible: false
1329                        }
1330                    ))
1331                },
1332                None,
1333                true,
1334            )
1335            .unwrap()
1336            .unwrap(),
1337            SubtypeElements::ValueRange {
1338                min: Some(ASN1Value::Integer(-3)),
1339                max: Some(ASN1Value::Integer(5)),
1340                extensible: false
1341            }
1342        )
1343    }
1344
1345    #[test]
1346    fn folds_range_values_numeric_constraints() {
1347        assert_eq!(
1348            fold_constraint_set(
1349                &SetOperation {
1350                    base: SubtypeElements::ValueRange {
1351                        min: Some(ASN1Value::Integer(-2)),
1352                        max: Some(ASN1Value::Integer(3)),
1353                        extensible: false
1354                    },
1355                    operator: SetOperator::Intersection,
1356                    operant: Box::new(ElementOrSetOperation::Element(
1357                        SubtypeElements::ValueRange {
1358                            min: Some(ASN1Value::Integer(-5)),
1359                            max: Some(ASN1Value::Integer(1)),
1360                            extensible: false
1361                        }
1362                    ))
1363                },
1364                None,
1365                true,
1366            )
1367            .unwrap()
1368            .unwrap(),
1369            SubtypeElements::ValueRange {
1370                min: Some(ASN1Value::Integer(-2)),
1371                max: Some(ASN1Value::Integer(1)),
1372                extensible: false
1373            }
1374        );
1375        assert_eq!(
1376            fold_constraint_set(
1377                &SetOperation {
1378                    base: SubtypeElements::ValueRange {
1379                        min: Some(ASN1Value::Integer(-2)),
1380                        max: Some(ASN1Value::Integer(3)),
1381                        extensible: false
1382                    },
1383                    operator: SetOperator::Union,
1384                    operant: Box::new(ElementOrSetOperation::Element(
1385                        SubtypeElements::ValueRange {
1386                            min: Some(ASN1Value::Integer(-1)),
1387                            max: Some(ASN1Value::Integer(5)),
1388                            extensible: false
1389                        }
1390                    ))
1391                },
1392                None,
1393                true
1394            )
1395            .unwrap()
1396            .unwrap(),
1397            SubtypeElements::ValueRange {
1398                min: Some(ASN1Value::Integer(-2)),
1399                max: Some(ASN1Value::Integer(5)),
1400                extensible: false
1401            }
1402        )
1403    }
1404
1405    #[test]
1406    fn folds_single_value_mixed_constraints() {
1407        let set_op = |op: SetOperator| SetOperation {
1408            base: SubtypeElements::SingleValue {
1409                value: ASN1Value::Integer(4),
1410                extensible: false,
1411            },
1412            operator: op,
1413            operant: Box::new(ElementOrSetOperation::Element(
1414                SubtypeElements::SingleValue {
1415                    value: ASN1Value::String("abc".into()),
1416                    extensible: false,
1417                },
1418            )),
1419        };
1420        assert_eq!(
1421            fold_constraint_set(&set_op(SetOperator::Intersection), None, true)
1422                .unwrap()
1423                .unwrap(),
1424            SubtypeElements::SingleValue {
1425                value: ASN1Value::Integer(4),
1426                extensible: false
1427            }
1428        );
1429        assert_eq!(
1430            fold_constraint_set(
1431                &set_op(SetOperator::Intersection),
1432                Some(&CharacterStringType::IA5String.character_set()),
1433                false
1434            )
1435            .unwrap()
1436            .unwrap(),
1437            SubtypeElements::SingleValue {
1438                value: ASN1Value::String("abc".into()),
1439                extensible: false
1440            }
1441        );
1442        assert_eq!(
1443            fold_constraint_set(&set_op(SetOperator::Union), None, true).unwrap(),
1444            None
1445        );
1446        assert_eq!(
1447            fold_constraint_set(
1448                &set_op(SetOperator::Union),
1449                Some(&CharacterStringType::IA5String.character_set()),
1450                false
1451            )
1452            .unwrap(),
1453            None
1454        );
1455    }
1456
1457    #[test]
1458    fn folds_range_value_mixed_constraints() {
1459        let set_op = |op| SetOperation {
1460            base: SubtypeElements::ValueRange {
1461                min: Some(ASN1Value::Integer(-1)),
1462                max: Some(ASN1Value::Integer(3)),
1463                extensible: false,
1464            },
1465            operator: op,
1466            operant: Box::new(ElementOrSetOperation::Element(
1467                SubtypeElements::SingleValue {
1468                    value: ASN1Value::String("ABC".into()),
1469                    extensible: false,
1470                },
1471            )),
1472        };
1473        assert_eq!(
1474            fold_constraint_set(
1475                &set_op(SetOperator::Intersection),
1476                Some(&CharacterStringType::PrintableString.character_set()),
1477                false
1478            )
1479            .unwrap()
1480            .unwrap(),
1481            SubtypeElements::SingleValue {
1482                value: ASN1Value::String("ABC".into()),
1483                extensible: false,
1484            }
1485        );
1486        assert_eq!(
1487            fold_constraint_set(
1488                &set_op(SetOperator::Union),
1489                Some(&CharacterStringType::PrintableString.character_set()),
1490                false
1491            )
1492            .unwrap(),
1493            None
1494        );
1495        assert_eq!(
1496            fold_constraint_set(&set_op(SetOperator::Intersection), None, true)
1497                .unwrap()
1498                .unwrap(),
1499            SubtypeElements::ValueRange {
1500                min: Some(ASN1Value::Integer(-1)),
1501                max: Some(ASN1Value::Integer(3)),
1502                extensible: false,
1503            }
1504        );
1505        assert_eq!(
1506            fold_constraint_set(&set_op(SetOperator::Union), None, true).unwrap(),
1507            None
1508        );
1509    }
1510
1511    #[test]
1512    fn folds_range_values_mixed_constraints() {
1513        let set_op = |op| SetOperation {
1514            base: SubtypeElements::ValueRange {
1515                min: Some(ASN1Value::Integer(-2)),
1516                max: Some(ASN1Value::Integer(3)),
1517                extensible: false,
1518            },
1519            operator: op,
1520            operant: Box::new(ElementOrSetOperation::Element(
1521                SubtypeElements::ValueRange {
1522                    min: Some(ASN1Value::String("A".into())),
1523                    max: Some(ASN1Value::String("C".into())),
1524                    extensible: false,
1525                },
1526            )),
1527        };
1528        assert_eq!(
1529            fold_constraint_set(
1530                &set_op(SetOperator::Intersection),
1531                Some(&CharacterStringType::PrintableString.character_set()),
1532                true
1533            )
1534            .unwrap()
1535            .unwrap(),
1536            SubtypeElements::ValueRange {
1537                min: Some(ASN1Value::String("A".into())),
1538                max: Some(ASN1Value::String("C".into())),
1539                extensible: false,
1540            }
1541        );
1542        assert_eq!(
1543            fold_constraint_set(&set_op(SetOperator::Intersection), None, true)
1544                .unwrap()
1545                .unwrap(),
1546            SubtypeElements::ValueRange {
1547                min: Some(ASN1Value::Integer(-2)),
1548                max: Some(ASN1Value::Integer(3)),
1549                extensible: false,
1550            }
1551        );
1552        assert_eq!(
1553            fold_constraint_set(
1554                &set_op(SetOperator::Union),
1555                Some(&CharacterStringType::PrintableString.character_set()),
1556                true
1557            )
1558            .unwrap(),
1559            None
1560        );
1561        assert_eq!(
1562            fold_constraint_set(&set_op(SetOperator::Union), None, true).unwrap(),
1563            None
1564        );
1565    }
1566}