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