1use alloc::vec;
6use alloc::vec::Vec;
7use core::{char, cmp::Ordering, ops::RangeBounds};
8use potential_utf::PotentialCodePoint;
9
10use crate::codepointinvlist::{utils::deconstruct_range, CodePointInversionList};
11use zerovec::{ule::AsULE, ZeroVec};
12
13#[derive(Default)]
17pub struct CodePointInversionListBuilder {
18 intervals: Vec<u32>,
20}
21
22impl CodePointInversionListBuilder {
23 pub const fn new() -> Self {
25 Self { intervals: vec![] }
26 }
27
28 pub fn build(self) -> CodePointInversionList<'static> {
30 let inv_list: ZeroVec<PotentialCodePoint> = self
31 .intervals
32 .into_iter()
33 .map(PotentialCodePoint::from_u24)
34 .collect();
35 #[allow(clippy::unwrap_used)] CodePointInversionList::try_from_inversion_list(inv_list).unwrap()
37 }
38
39 fn add_remove_middle(&mut self, start: u32, end: u32, add: bool) {
43 if start >= end || end > char::MAX as u32 + 1 {
44 return;
45 }
46 let start_res = self.intervals.binary_search(&start);
47 let end_res = self.intervals.binary_search(&end);
48 let mut start_ind = start_res.unwrap_or_else(|x| x);
49 let mut end_ind = end_res.unwrap_or_else(|x| x);
50 let start_pos_check = (start_ind % 2 == 0) == add;
51 let end_pos_check = (end_ind % 2 == 0) == add;
52 let start_eq_end = start_ind == end_ind;
53
54 #[allow(clippy::indexing_slicing)] if start_eq_end && start_pos_check && end_res.is_err() {
56 self.intervals.splice(start_ind..end_ind, [start, end]);
57 } else {
58 if start_pos_check {
59 self.intervals[start_ind] = start;
60 start_ind += 1;
61 }
62 if end_pos_check {
63 if end_res.is_ok() {
64 end_ind += 1;
65 } else {
66 end_ind -= 1;
67 self.intervals[end_ind] = end;
68 }
69 }
70 if start_ind < end_ind {
71 self.intervals.drain(start_ind..end_ind);
72 }
73 }
74 }
75
76 fn add(&mut self, start: u32, end: u32) {
82 if start >= end {
83 return;
84 }
85 if self.intervals.is_empty() {
86 self.intervals.extend_from_slice(&[start, end]);
87 return;
88 }
89 self.add_remove_middle(start, end, true);
90 }
91
92 pub fn add_char(&mut self, c: char) {
104 let to_add = c as u32;
105 self.add(to_add, to_add + 1);
106 }
107
108 pub fn add32(&mut self, c: u32) {
125 if c <= char::MAX as u32 {
126 self.add(c, c + 1);
128 }
129 }
130
131 pub fn add_range(&mut self, range: impl RangeBounds<char>) {
143 let (start, end) = deconstruct_range(range);
144 self.add(start, end);
145 }
146
147 pub fn add_range32(&mut self, range: impl RangeBounds<u32>) {
159 let (start, end) = deconstruct_range(range);
160 if start <= end && end <= char::MAX as u32 + 1 {
162 self.add(start, end);
163 }
164 }
165
166 #[allow(unused_assignments)]
184 pub fn add_set(&mut self, set: &CodePointInversionList) {
185 #[allow(clippy::indexing_slicing)] set.as_inversion_list()
187 .as_ule_slice()
188 .chunks(2)
189 .for_each(|pair| {
190 self.add(
191 u32::from(PotentialCodePoint::from_unaligned(pair[0])),
192 u32::from(PotentialCodePoint::from_unaligned(pair[1])),
193 )
194 });
195 }
196
197 fn remove(&mut self, start: u32, end: u32) {
202 if start >= end || self.intervals.is_empty() {
203 return;
204 }
205 if let Some(&last) = self.intervals.last() {
206 #[allow(clippy::indexing_slicing)]
207 if start <= self.intervals[0] && end >= last {
209 self.intervals.clear();
210 } else {
211 self.add_remove_middle(start, end, false);
212 }
213 }
214 }
215
216 pub fn remove_char(&mut self, c: char) {
228 self.remove32(c as u32)
229 }
230
231 pub fn remove32(&mut self, c: u32) {
233 self.remove(c, c + 1);
234 }
235
236 pub fn remove_range(&mut self, range: impl RangeBounds<char>) {
248 let (start, end) = deconstruct_range(range);
249 self.remove(start, end);
250 }
251
252 pub fn remove_range32(&mut self, range: impl RangeBounds<u32>) {
254 let (start, end) = deconstruct_range(range);
255 self.remove(start, end);
256 }
257
258 #[allow(clippy::indexing_slicing)] pub fn remove_set(&mut self, set: &CodePointInversionList) {
272 set.as_inversion_list()
273 .as_ule_slice()
274 .chunks(2)
275 .for_each(|pair| {
276 self.remove(
277 u32::from(PotentialCodePoint::from_unaligned(pair[0])),
278 u32::from(PotentialCodePoint::from_unaligned(pair[1])),
279 )
280 });
281 }
282
283 pub fn retain_char(&mut self, c: char) {
298 self.retain32(c as u32)
299 }
300
301 pub fn retain32(&mut self, c: u32) {
303 self.remove(0, c);
304 self.remove(c + 1, (char::MAX as u32) + 1);
305 }
306
307 pub fn retain_range(&mut self, range: impl RangeBounds<char>) {
323 let (start, end) = deconstruct_range(range);
324 self.remove(0, start);
325 self.remove(end, (char::MAX as u32) + 1);
326 }
327
328 pub fn retain_range32(&mut self, range: impl RangeBounds<u32>) {
330 let (start, end) = deconstruct_range(range);
331 self.remove(0, start);
332 self.remove(end, (char::MAX as u32) + 1);
333 }
334
335 #[allow(clippy::indexing_slicing)] pub fn retain_set(&mut self, set: &CodePointInversionList) {
355 let mut prev = 0;
356 for pair in set.as_inversion_list().as_ule_slice().chunks(2) {
357 let range_start = u32::from(PotentialCodePoint::from_unaligned(pair[0]));
358 let range_limit = u32::from(PotentialCodePoint::from_unaligned(pair[1]));
359 self.remove(prev, range_start);
360 prev = range_limit;
361 }
362 self.remove(prev, (char::MAX as u32) + 1);
363 }
364
365 fn complement_list(&mut self, set_iter: impl IntoIterator<Item = u32>) {
371 let mut res: Vec<u32> = vec![]; let mut ai = self.intervals.iter();
373 let mut bi = set_iter.into_iter();
374 let mut a = ai.next();
375 let mut b = bi.next();
376 while let (Some(c), Some(d)) = (a, b) {
377 match c.cmp(&d) {
378 Ordering::Less => {
379 res.push(*c);
380 a = ai.next();
381 }
382 Ordering::Greater => {
383 res.push(d);
384 b = bi.next();
385 }
386 Ordering::Equal => {
387 a = ai.next();
388 b = bi.next();
389 }
390 }
391 }
392 if let Some(c) = a {
393 res.push(*c)
394 }
395 if let Some(d) = b {
396 res.push(d)
397 }
398 res.extend(ai);
399 res.extend(bi);
400 self.intervals = res;
401 }
402
403 pub fn complement(&mut self) {
426 if !self.intervals.is_empty() {
427 #[allow(clippy::indexing_slicing)] if self.intervals[0] == 0 {
429 self.intervals.drain(0..1);
430 } else {
431 self.intervals.insert(0, 0);
432 }
433 if self.intervals.last() == Some(&(char::MAX as u32 + 1)) {
434 self.intervals.pop();
435 } else {
436 self.intervals.push(char::MAX as u32 + 1);
437 }
438 } else {
439 self.intervals
440 .extend_from_slice(&[0, (char::MAX as u32 + 1)]);
441 }
442 }
443
444 pub fn complement_char(&mut self, c: char) {
459 self.complement32(c as u32);
460 }
461
462 pub fn complement32(&mut self, c: u32) {
464 self.complement_list([c, c + 1]);
465 }
466
467 pub fn complement_range(&mut self, range: impl RangeBounds<char>) {
482 let (start, end) = deconstruct_range(range);
483 self.complement_list([start, end]);
484 }
485
486 pub fn complement_range32(&mut self, range: impl RangeBounds<u32>) {
488 let (start, end) = deconstruct_range(range);
489 self.complement_list([start, end]);
490 }
491
492 pub fn complement_set(&mut self, set: &CodePointInversionList) {
513 let inv_list_iter_owned = set.as_inversion_list().iter().map(u32::from);
514 self.complement_list(inv_list_iter_owned);
515 }
516
517 pub fn is_empty(&self) -> bool {
528 self.intervals.is_empty()
529 }
530}
531
532#[cfg(test)]
533mod tests {
534 use super::{CodePointInversionList, CodePointInversionListBuilder};
535 use core::char;
536
537 fn generate_tester(ex: &[u32]) -> CodePointInversionListBuilder {
538 let check = CodePointInversionList::try_from_u32_inversion_list_slice(ex).unwrap();
539 let mut builder = CodePointInversionListBuilder::new();
540 builder.add_set(&check);
541 builder
542 }
543
544 #[test]
545 fn test_new() {
546 let ex = CodePointInversionListBuilder::new();
547 assert!(ex.intervals.is_empty());
548 }
549
550 #[test]
551 fn test_build() {
552 let mut builder = CodePointInversionListBuilder::new();
553 builder.add(0x41, 0x42);
554 let check: CodePointInversionList = builder.build();
555 assert_eq!(check.iter_chars().next(), Some('A'));
556 }
557
558 #[test]
559 fn test_empty_build() {
560 let builder = CodePointInversionListBuilder::new();
561 let check: CodePointInversionList = builder.build();
562 assert!(check.is_empty());
563 }
564
565 #[test]
566 fn test_add_to_empty() {
567 let mut builder = CodePointInversionListBuilder::new();
568 builder.add(0x0, 0xA);
569 assert_eq!(builder.intervals, [0x0, 0xA]);
570 }
571
572 #[test]
573 fn test_add_invalid() {
574 let mut builder = CodePointInversionListBuilder::new();
575 builder.add(0x0, 0x0);
576 builder.add(0x5, 0x0);
577 assert!(builder.intervals.is_empty());
578 }
579
580 #[test]
581 fn test_add_to_start() {
582 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
583 builder.add(0x0, 0x5);
584 let expected = [0x0, 0x5, 0xA, 0x14, 0x28, 0x32];
585 assert_eq!(builder.intervals, expected);
586 }
587
588 #[test]
589 fn test_add_to_start_overlap() {
590 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
591 builder.add(0x0, 0xE);
592 let expected = [0x0, 0x14, 0x28, 0x32];
593 assert_eq!(builder.intervals, expected);
594 }
595
596 #[test]
597 fn test_add_to_end() {
598 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
599 builder.add(0x3C, 0x46);
600 let expected = [0xA, 0x14, 0x28, 0x32, 60, 70];
601 assert_eq!(builder.intervals, expected);
602 }
603
604 #[test]
605 fn test_add_to_end_overlap() {
606 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
607 builder.add(0x2B, 0x46);
608 let expected = [0xA, 0x14, 0x28, 0x46];
609 assert_eq!(builder.intervals, expected);
610 }
611
612 #[test]
613 fn test_add_to_middle_no_overlap() {
614 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
615 builder.add(0x19, 0x1B);
616 let expected = [0xA, 0x14, 0x19, 0x1B, 0x28, 0x32];
617 assert_eq!(builder.intervals, expected);
618 }
619
620 #[test]
621 fn test_add_to_middle_inside() {
622 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
623 builder.add(0xA, 0x14);
624 let expected = [0xA, 0x14, 0x28, 0x32];
625 assert_eq!(builder.intervals, expected);
626 }
627
628 #[test]
629 fn test_add_to_middle_left_overlap() {
630 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
631 builder.add(0xF, 0x19);
632 let expected = [0xA, 0x19, 0x28, 0x32];
633 assert_eq!(builder.intervals, expected);
634 }
635
636 #[test]
637 fn test_add_to_middle_right_overlap() {
638 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
639 builder.add(0x1E, 0x28);
640 let expected = [0xA, 0x14, 0x1E, 0x32];
641 assert_eq!(builder.intervals, expected);
642 }
643
644 #[test]
645 fn test_add_to_full_encompass() {
646 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
647 builder.add(0x0, 0x3C);
648 let expected = [0x0, 0x3C];
649 assert_eq!(builder.intervals, expected);
650 }
651
652 #[test]
653 fn test_add_to_partial_encompass() {
654 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
655 builder.add(0x0, 0x23);
656 let expected = [0x0, 0x23, 0x28, 0x32];
657 assert_eq!(builder.intervals, expected);
658 }
659
660 #[test]
661 fn test_add_aligned_front() {
662 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
663 builder.add(5, 10);
664 let expected = [5, 0x14, 0x28, 0x32];
665 assert_eq!(builder.intervals, expected);
666 }
667
668 #[test]
669 fn test_add_aligned_back() {
670 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
671 builder.add(0x32, 0x37);
672 let expected = [0xA, 0x14, 0x28, 0x37];
673 assert_eq!(builder.intervals, expected);
674 }
675
676 #[test]
677 fn test_add_aligned_start_middle() {
678 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
679 builder.add(0x14, 0x19);
680 let expected = [0xA, 0x19, 0x28, 0x32];
681 assert_eq!(builder.intervals, expected);
682 }
683
684 #[test]
685 fn test_add_aligned_end_middle() {
686 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
687 builder.add(0x23, 0x28);
688 let expected = [0xA, 0x14, 0x23, 0x32];
689 assert_eq!(builder.intervals, expected);
690 }
691
692 #[test]
693 fn test_add_aligned_in_between_end() {
694 let mut builder = generate_tester(&[0xA, 0x14, 0x1E, 0x28, 0x32, 0x3C]);
695 builder.add(0xF, 0x1E);
696 let expected = [0xA, 0x28, 0x32, 0x3C];
697 assert_eq!(builder.intervals, expected);
698 }
699
700 #[test]
701 fn test_add_aligned_in_between_start() {
702 let mut builder = generate_tester(&[0xA, 0x14, 0x1E, 0x28, 0x32, 0x3C]);
703 builder.add(20, 35);
704 let expected = [0xA, 0x28, 0x32, 0x3C];
705 assert_eq!(builder.intervals, expected);
706 }
707
708 #[test]
709 fn test_add_adjacent_ranges() {
710 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
711 builder.add(0x13, 0x14);
712 builder.add(0x14, 0x15);
713 builder.add(0x15, 0x16);
714 let expected = [0xA, 0x16, 0x28, 0x32];
715 assert_eq!(builder.intervals, expected);
716 }
717
718 #[test]
719 fn test_add_codepointinversionlist() {
720 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
721 let check = CodePointInversionList::try_from_u32_inversion_list_slice(&[
722 0x5, 0xA, 0x16, 0x21, 0x2C, 0x33,
723 ])
724 .unwrap();
725 builder.add_set(&check);
726 let expected = [0x5, 0x14, 0x16, 0x21, 0x28, 0x33];
727 assert_eq!(builder.intervals, expected);
728 }
729 #[test]
730 fn test_add_char() {
731 let mut builder = CodePointInversionListBuilder::new();
732 builder.add_char('a');
733 let expected = [0x61, 0x62];
734 assert_eq!(builder.intervals, expected);
735 }
736
737 #[test]
738 fn test_add_range() {
739 let mut builder = CodePointInversionListBuilder::new();
740 builder.add_range('A'..='Z');
741 let expected = [0x41, 0x5B];
742 assert_eq!(builder.intervals, expected);
743 }
744
745 #[test]
746 fn test_add_range32() {
747 let mut builder = CodePointInversionListBuilder::new();
748 builder.add_range32(0xd800..=0xdfff);
749 let expected = [0xd800, 0xe000];
750 assert_eq!(builder.intervals, expected);
751 }
752
753 #[test]
754 fn test_add_invalid_range() {
755 let mut builder = CodePointInversionListBuilder::new();
756 builder.add_range('Z'..='A');
757 assert!(builder.intervals.is_empty());
758 }
759
760 #[test]
761 fn test_remove_empty() {
762 let mut builder = CodePointInversionListBuilder::new();
763 builder.remove(0x0, 0xA);
764 assert!(builder.intervals.is_empty());
765 }
766
767 #[test]
768 fn test_remove_entire_builder() {
769 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
770 builder.remove(0xA, 0x32);
771 assert!(builder.intervals.is_empty());
772 }
773
774 #[test]
775 fn test_remove_entire_range() {
776 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
777 builder.remove(0xA, 0x14);
778 let expected = [0x28, 0x32];
779 assert_eq!(builder.intervals, expected);
780 }
781
782 #[test]
783 fn test_remove_partial_range_left() {
784 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
785 builder.remove(0xA, 0x2B);
786 let expected = [0x2B, 0x32];
787 assert_eq!(builder.intervals, expected);
788 }
789
790 #[test]
791 fn test_remove_ne_range() {
792 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
793 builder.remove(0x14, 0x28);
794 let expected = [0xA, 0x14, 0x28, 0x32];
795 assert_eq!(builder.intervals, expected);
796 }
797
798 #[test]
799 fn test_remove_partial_range_right() {
800 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
801 builder.remove(0xF, 0x37);
802 let expected = [0xA, 0xF];
803 assert_eq!(builder.intervals, expected);
804 }
805
806 #[test]
807 fn test_remove_middle_range() {
808 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
809 builder.remove(0xC, 0x12);
810 let expected = [0xA, 0xC, 0x12, 0x14, 0x28, 0x32];
811 assert_eq!(builder.intervals, expected);
812 }
813
814 #[test]
815 fn test_remove_ne_middle_range() {
816 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
817 builder.remove(0x19, 0x1B);
818 let expected = [0xA, 0x14, 0x28, 0x32];
819 assert_eq!(builder.intervals, expected);
820 }
821
822 #[test]
823 fn test_remove_encompassed_range() {
824 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]);
825 builder.remove(0x19, 0x37);
826 let expected = [0xA, 0x14, 0x46, 0x50];
827 assert_eq!(builder.intervals, expected);
828 }
829 #[test]
830 fn test_remove_adjacent_ranges() {
831 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
832 builder.remove(0x27, 0x28);
833 builder.remove(0x28, 0x29);
834 builder.remove(0x29, 0x2A);
835 let expected = [0xA, 0x14, 0x2A, 0x32];
836 assert_eq!(builder.intervals, expected);
837 }
838
839 #[test]
840 fn test_remove_char() {
841 let mut builder = generate_tester(&[0x41, 0x46]);
842 builder.remove_char('A'); let expected = [0x42, 0x46];
844 assert_eq!(builder.intervals, expected);
845 }
846
847 #[test]
848 fn test_remove_range() {
849 let mut builder = generate_tester(&[0x41, 0x5A]);
850 builder.remove_range('A'..'L'); let expected = [0x4C, 0x5A];
852 assert_eq!(builder.intervals, expected);
853 }
854
855 #[test]
856 fn test_remove_set() {
857 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]);
858 let remove =
859 CodePointInversionList::try_from_u32_inversion_list_slice(&[0xA, 0x14, 0x2D, 0x4B])
860 .unwrap();
861 builder.remove_set(&remove);
862 let expected = [0x28, 0x2D, 0x4B, 0x50];
863 assert_eq!(builder.intervals, expected);
864 }
865
866 #[test]
867 fn test_retain_char() {
868 let mut builder = generate_tester(&[0x41, 0x5A]);
869 builder.retain_char('A'); let expected = [0x41, 0x42];
871 assert_eq!(builder.intervals, expected);
872 }
873
874 #[test]
875 fn test_retain_range() {
876 let mut builder = generate_tester(&[0x41, 0x5A]);
877 builder.retain_range('C'..'F'); let expected = [0x43, 0x46];
879 assert_eq!(builder.intervals, expected);
880 }
881
882 #[test]
883 fn test_retain_range_empty() {
884 let mut builder = generate_tester(&[0x41, 0x46]);
885 builder.retain_range('F'..'Z');
886 assert!(builder.intervals.is_empty());
887 }
888
889 #[test]
890 fn test_retain_set() {
891 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]);
892 let retain = CodePointInversionList::try_from_u32_inversion_list_slice(&[
893 0xE, 0x14, 0x19, 0x37, 0x4D, 0x51,
894 ])
895 .unwrap();
896 builder.retain_set(&retain);
897 let expected = [0xE, 0x14, 0x28, 0x32, 0x4D, 0x50];
898 assert_eq!(builder.intervals, expected);
899 }
900
901 #[test]
902 fn test_complement() {
903 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
904 builder.complement();
905 let expected = [0x0, 0xA, 0x14, 0x28, 0x32, (char::MAX as u32) + 1];
906 assert_eq!(builder.intervals, expected);
907 }
908
909 #[test]
910 fn test_complement_empty() {
911 let mut builder = generate_tester(&[]);
912 builder.complement();
913 let expected = [0x0, (char::MAX as u32) + 1];
914 assert_eq!(builder.intervals, expected);
915
916 builder.complement();
917 let expected: [u32; 0] = [];
918 assert_eq!(builder.intervals, expected);
919 }
920
921 #[test]
922 fn test_complement_zero_max() {
923 let mut builder = generate_tester(&[0x0, 0xA, 0x5A, (char::MAX as u32) + 1]);
924 builder.complement();
925 let expected = [0xA, 0x5A];
926 assert_eq!(builder.intervals, expected);
927 }
928
929 #[test]
930 fn test_complement_interior() {
931 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
932 builder.complement_list([0xE, 0x14]);
933 let expected = [0xA, 0xE, 0x28, 0x32];
934 assert_eq!(builder.intervals, expected);
935 }
936
937 #[test]
938 fn test_complement_exterior() {
939 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
940 builder.complement_list([0x19, 0x23]);
941 let expected = [0xA, 0x14, 0x19, 0x23, 0x28, 0x32];
942 assert_eq!(builder.intervals, expected);
943 }
944
945 #[test]
946 fn test_complement_larger_list() {
947 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
948 builder.complement_list([0x1E, 0x37, 0x3C, 0x46]);
949 let expected = [0xA, 0x14, 0x1E, 0x28, 0x32, 0x37, 0x3C, 0x46];
950 assert_eq!(builder.intervals, expected);
951 }
952
953 #[test]
954 fn test_complement_char() {
955 let mut builder = generate_tester(&[0x41, 0x4C]); builder.complement_char('A');
957 builder.complement_char('L');
958 let expected = [0x42, 0x4D];
959 assert_eq!(builder.intervals, expected);
960 }
961
962 #[test]
963 fn test_complement_range() {
964 let mut builder = generate_tester(&[0x46, 0x4C]); builder.complement_range('A'..='Z');
966 let expected = [0x41, 0x46, 0x4C, 0x5B];
967 assert_eq!(builder.intervals, expected);
968 }
969
970 #[test]
971 fn test_complement_set() {
972 let mut builder = generate_tester(&[0x43, 0x4E]);
973 let set =
974 CodePointInversionList::try_from_u32_inversion_list_slice(&[0x41, 0x46, 0x4B, 0x5A])
975 .unwrap();
976 builder.complement_set(&set);
977 let expected = [0x41, 0x43, 0x46, 0x4B, 0x4E, 0x5A];
978 assert_eq!(builder.intervals, expected);
979 }
980
981 #[test]
982 fn test_is_empty() {
983 let builder = CodePointInversionListBuilder::new();
984 assert!(builder.is_empty());
985 }
986}