rasn_compiler/intermediate/encoding_rules/
per_visible.rs

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