rasn_compiler/intermediate/encoding_rules/
per_visible.rs

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