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