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