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