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