1use alloc::vec;
6use alloc::vec::Vec;
7use core::{char, cmp::Ordering, ops::RangeBounds};
8
9use crate::codepointinvlist::{utils::deconstruct_range, CodePointInversionList};
10use zerovec::{ule::AsULE, ZeroVec};
11
12#[derive(Default)]
16pub struct CodePointInversionListBuilder {
17 intervals: Vec<u32>,
19}
20
21impl CodePointInversionListBuilder {
22 pub const fn new() -> Self {
24 Self { intervals: vec![] }
25 }
26
27 pub fn build(self) -> CodePointInversionList<'static> {
29 let inv_list: ZeroVec<u32> = ZeroVec::alloc_from_slice(&self.intervals);
30 #[allow(clippy::unwrap_used)] CodePointInversionList::try_from_inversion_list(inv_list).unwrap()
32 }
33
34 fn add_remove_middle(&mut self, start: u32, end: u32, add: bool) {
38 if start >= end || end > char::MAX as u32 + 1 {
39 return;
40 }
41 let start_res = self.intervals.binary_search(&start);
42 let end_res = self.intervals.binary_search(&end);
43 let mut start_ind = start_res.unwrap_or_else(|x| x);
44 let mut end_ind = end_res.unwrap_or_else(|x| x);
45 let start_pos_check = (start_ind % 2 == 0) == add;
46 let end_pos_check = (end_ind % 2 == 0) == add;
47 let start_eq_end = start_ind == end_ind;
48
49 #[allow(clippy::indexing_slicing)] if start_eq_end && start_pos_check && end_res.is_err() {
51 let ins = &[start, end];
52 self.intervals
53 .splice(start_ind..end_ind, ins.iter().copied());
54 } else {
55 if start_pos_check {
56 self.intervals[start_ind] = start;
57 start_ind += 1;
58 }
59 if end_pos_check {
60 if end_res.is_ok() {
61 end_ind += 1;
62 } else {
63 end_ind -= 1;
64 self.intervals[end_ind] = end;
65 }
66 }
67 if start_ind < end_ind {
68 self.intervals.drain(start_ind..end_ind);
69 }
70 }
71 }
72
73 fn add(&mut self, start: u32, end: u32) {
79 if start >= end {
80 return;
81 }
82 if self.intervals.is_empty() {
83 self.intervals.extend_from_slice(&[start, end]);
84 return;
85 }
86 self.add_remove_middle(start, end, true);
87 }
88
89 pub fn add_char(&mut self, c: char) {
101 let to_add = c as u32;
102 self.add(to_add, to_add + 1);
103 }
104
105 pub fn add32(&mut self, c: u32) {
122 if c <= char::MAX as u32 {
123 self.add(c, c + 1);
125 }
126 }
127
128 #[deprecated(since = "1.5.0", note = "Use `add32`")]
130 pub fn add_u32(&mut self, c: u32) {
131 self.add32(c)
132 }
133
134 pub fn add_range(&mut self, range: &impl RangeBounds<char>) {
146 let (start, end) = deconstruct_range(range);
147 self.add(start, end);
148 }
149
150 pub fn add_range32(&mut self, range: &impl RangeBounds<u32>) {
162 let (start, end) = deconstruct_range(range);
163 if start <= end && end <= char::MAX as u32 + 1 {
165 self.add(start, end);
166 }
167 }
168
169 #[deprecated(since = "1.5.0", note = "Use `add_range32`")]
171 pub fn add_range_u32(&mut self, range: &impl RangeBounds<u32>) {
172 self.add_range32(range)
173 }
174
175 #[allow(unused_assignments)]
192 pub fn add_set(&mut self, set: &CodePointInversionList) {
193 #[allow(clippy::indexing_slicing)] set.as_inversion_list()
195 .as_ule_slice()
196 .chunks(2)
197 .for_each(|pair| {
198 self.add(
199 AsULE::from_unaligned(pair[0]),
200 AsULE::from_unaligned(pair[1]),
201 )
202 });
203 }
204
205 fn remove(&mut self, start: u32, end: u32) {
210 if start >= end || self.intervals.is_empty() {
211 return;
212 }
213 if let Some(&last) = self.intervals.last() {
214 #[allow(clippy::indexing_slicing)]
215 if start <= self.intervals[0] && end >= last {
217 self.intervals.clear();
218 } else {
219 self.add_remove_middle(start, end, false);
220 }
221 }
222 }
223
224 pub fn remove_char(&mut self, c: char) {
236 self.remove32(c as u32)
237 }
238
239 pub fn remove32(&mut self, c: u32) {
241 self.remove(c, c + 1);
242 }
243
244 pub fn remove_range(&mut self, range: &impl RangeBounds<char>) {
256 let (start, end) = deconstruct_range(range);
257 self.remove(start, end);
258 }
259
260 pub fn remove_range32(&mut self, range: &impl RangeBounds<u32>) {
262 let (start, end) = deconstruct_range(range);
263 self.remove(start, end);
264 }
265
266 #[allow(clippy::indexing_slicing)] pub fn remove_set(&mut self, set: &CodePointInversionList) {
280 set.as_inversion_list()
281 .as_ule_slice()
282 .chunks(2)
283 .for_each(|pair| {
284 self.remove(
285 AsULE::from_unaligned(pair[0]),
286 AsULE::from_unaligned(pair[1]),
287 )
288 });
289 }
290
291 pub fn retain_char(&mut self, c: char) {
306 self.retain32(c as u32)
307 }
308
309 pub fn retain32(&mut self, c: u32) {
311 self.remove(0, c);
312 self.remove(c + 1, (char::MAX as u32) + 1);
313 }
314
315 pub fn retain_range(&mut self, range: &impl RangeBounds<char>) {
331 let (start, end) = deconstruct_range(range);
332 self.remove(0, start);
333 self.remove(end, (char::MAX as u32) + 1);
334 }
335
336 pub fn retain_range32(&mut self, range: &impl RangeBounds<u32>) {
338 let (start, end) = deconstruct_range(range);
339 self.remove(0, start);
340 self.remove(end, (char::MAX as u32) + 1);
341 }
342
343 #[allow(clippy::indexing_slicing)] pub fn retain_set(&mut self, set: &CodePointInversionList) {
362 let mut prev = 0;
363 for pair in set.as_inversion_list().as_ule_slice().chunks(2) {
364 let range_start = AsULE::from_unaligned(pair[0]);
365 let range_limit = AsULE::from_unaligned(pair[1]);
366 self.remove(prev, range_start);
367 prev = range_limit;
368 }
369 self.remove(prev, (char::MAX as u32) + 1);
370 }
371
372 fn complement_list(&mut self, set_iter: impl core::iter::Iterator<Item = u32>) {
378 let mut res: Vec<u32> = vec![]; let mut ai = self.intervals.iter();
380 let mut bi = set_iter;
381 let mut a = ai.next();
382 let mut b = bi.next();
383 while let (Some(c), Some(d)) = (a, b) {
384 match c.cmp(&d) {
385 Ordering::Less => {
386 res.push(*c);
387 a = ai.next();
388 }
389 Ordering::Greater => {
390 res.push(d);
391 b = bi.next();
392 }
393 Ordering::Equal => {
394 a = ai.next();
395 b = bi.next();
396 }
397 }
398 }
399 if let Some(c) = a {
400 res.push(*c)
401 }
402 if let Some(d) = b {
403 res.push(d)
404 }
405 res.extend(ai);
406 res.extend(bi);
407 self.intervals = res;
408 }
409
410 pub fn complement(&mut self) {
433 if !self.intervals.is_empty() {
434 #[allow(clippy::indexing_slicing)] if self.intervals[0] == 0 {
436 self.intervals.drain(0..1);
437 } else {
438 self.intervals.insert(0, 0);
439 }
440 if self.intervals.last() == Some(&(char::MAX as u32 + 1)) {
441 self.intervals.pop();
442 } else {
443 self.intervals.push(char::MAX as u32 + 1);
444 }
445 } else {
446 self.intervals
447 .extend_from_slice(&[0, (char::MAX as u32 + 1)]);
448 }
449 }
450
451 pub fn complement_char(&mut self, c: char) {
466 self.complement32(c as u32);
467 }
468
469 pub fn complement32(&mut self, c: u32) {
471 self.complement_list([c, c + 1].into_iter());
472 }
473
474 pub fn complement_range(&mut self, range: &impl RangeBounds<char>) {
489 let (start, end) = deconstruct_range(range);
490 let to_complement = [start, end];
491 self.complement_list(to_complement.iter().copied());
492 }
493
494 pub fn complement_range32(&mut self, range: &impl RangeBounds<u32>) {
496 let (start, end) = deconstruct_range(range);
497 let to_complement = [start, end];
498 self.complement_list(to_complement.iter().copied());
499 }
500
501 pub fn complement_set(&mut self, set: &CodePointInversionList) {
522 let inv_list_iter_owned = set.as_inversion_list().iter();
523 self.complement_list(inv_list_iter_owned);
524 }
525
526 pub fn is_empty(&self) -> bool {
537 self.intervals.is_empty()
538 }
539}
540
541#[cfg(test)]
542mod tests {
543 use super::{CodePointInversionList, CodePointInversionListBuilder};
544 use core::char;
545 use zerovec::ZeroVec;
546
547 fn generate_tester(ex: &[u32]) -> CodePointInversionListBuilder {
548 let inv_list = ZeroVec::<u32>::alloc_from_slice(ex);
549 let check = CodePointInversionList::try_from_inversion_list(inv_list).unwrap();
550 let mut builder = CodePointInversionListBuilder::new();
551 builder.add_set(&check);
552 builder
553 }
554
555 #[test]
556 fn test_new() {
557 let ex = CodePointInversionListBuilder::new();
558 assert!(ex.intervals.is_empty());
559 }
560
561 #[test]
562 fn test_build() {
563 let mut builder = CodePointInversionListBuilder::new();
564 builder.add(0x41, 0x42);
565 let check: CodePointInversionList = builder.build();
566 assert_eq!(check.iter_chars().next(), Some('A'));
567 }
568
569 #[test]
570 fn test_empty_build() {
571 let builder = CodePointInversionListBuilder::new();
572 let check: CodePointInversionList = builder.build();
573 assert!(check.is_empty());
574 }
575
576 #[test]
577 fn test_add_to_empty() {
578 let mut builder = CodePointInversionListBuilder::new();
579 builder.add(0x0, 0xA);
580 assert_eq!(builder.intervals, [0x0, 0xA]);
581 }
582
583 #[test]
584 fn test_add_invalid() {
585 let mut builder = CodePointInversionListBuilder::new();
586 builder.add(0x0, 0x0);
587 builder.add(0x5, 0x0);
588 assert!(builder.intervals.is_empty());
589 }
590
591 #[test]
592 fn test_add_to_start() {
593 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
594 builder.add(0x0, 0x5);
595 let expected = [0x0, 0x5, 0xA, 0x14, 0x28, 0x32];
596 assert_eq!(builder.intervals, expected);
597 }
598
599 #[test]
600 fn test_add_to_start_overlap() {
601 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
602 builder.add(0x0, 0xE);
603 let expected = [0x0, 0x14, 0x28, 0x32];
604 assert_eq!(builder.intervals, expected);
605 }
606
607 #[test]
608 fn test_add_to_end() {
609 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
610 builder.add(0x3C, 0x46);
611 let expected = [0xA, 0x14, 0x28, 0x32, 60, 70];
612 assert_eq!(builder.intervals, expected);
613 }
614
615 #[test]
616 fn test_add_to_end_overlap() {
617 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
618 builder.add(0x2B, 0x46);
619 let expected = [0xA, 0x14, 0x28, 0x46];
620 assert_eq!(builder.intervals, expected);
621 }
622
623 #[test]
624 fn test_add_to_middle_no_overlap() {
625 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
626 builder.add(0x19, 0x1B);
627 let expected = [0xA, 0x14, 0x19, 0x1B, 0x28, 0x32];
628 assert_eq!(builder.intervals, expected);
629 }
630
631 #[test]
632 fn test_add_to_middle_inside() {
633 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
634 builder.add(0xA, 0x14);
635 let expected = [0xA, 0x14, 0x28, 0x32];
636 assert_eq!(builder.intervals, expected);
637 }
638
639 #[test]
640 fn test_add_to_middle_left_overlap() {
641 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
642 builder.add(0xF, 0x19);
643 let expected = [0xA, 0x19, 0x28, 0x32];
644 assert_eq!(builder.intervals, expected);
645 }
646
647 #[test]
648 fn test_add_to_middle_right_overlap() {
649 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
650 builder.add(0x1E, 0x28);
651 let expected = [0xA, 0x14, 0x1E, 0x32];
652 assert_eq!(builder.intervals, expected);
653 }
654
655 #[test]
656 fn test_add_to_full_encompass() {
657 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
658 builder.add(0x0, 0x3C);
659 let expected = [0x0, 0x3C];
660 assert_eq!(builder.intervals, expected);
661 }
662
663 #[test]
664 fn test_add_to_partial_encompass() {
665 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
666 builder.add(0x0, 0x23);
667 let expected = [0x0, 0x23, 0x28, 0x32];
668 assert_eq!(builder.intervals, expected);
669 }
670
671 #[test]
672 fn test_add_aligned_front() {
673 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
674 builder.add(5, 10);
675 let expected = [5, 0x14, 0x28, 0x32];
676 assert_eq!(builder.intervals, expected);
677 }
678
679 #[test]
680 fn test_add_aligned_back() {
681 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
682 builder.add(0x32, 0x37);
683 let expected = [0xA, 0x14, 0x28, 0x37];
684 assert_eq!(builder.intervals, expected);
685 }
686
687 #[test]
688 fn test_add_aligned_start_middle() {
689 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
690 builder.add(0x14, 0x19);
691 let expected = [0xA, 0x19, 0x28, 0x32];
692 assert_eq!(builder.intervals, expected);
693 }
694
695 #[test]
696 fn test_add_aligned_end_middle() {
697 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
698 builder.add(0x23, 0x28);
699 let expected = [0xA, 0x14, 0x23, 0x32];
700 assert_eq!(builder.intervals, expected);
701 }
702
703 #[test]
704 fn test_add_aligned_in_between_end() {
705 let mut builder = generate_tester(&[0xA, 0x14, 0x1E, 0x28, 0x32, 0x3C]);
706 builder.add(0xF, 0x1E);
707 let expected = [0xA, 0x28, 0x32, 0x3C];
708 assert_eq!(builder.intervals, expected);
709 }
710
711 #[test]
712 fn test_add_aligned_in_between_start() {
713 let mut builder = generate_tester(&[0xA, 0x14, 0x1E, 0x28, 0x32, 0x3C]);
714 builder.add(20, 35);
715 let expected = [0xA, 0x28, 0x32, 0x3C];
716 assert_eq!(builder.intervals, expected);
717 }
718
719 #[test]
720 fn test_add_adjacent_ranges() {
721 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
722 builder.add(0x13, 0x14);
723 builder.add(0x14, 0x15);
724 builder.add(0x15, 0x16);
725 let expected = [0xA, 0x16, 0x28, 0x32];
726 assert_eq!(builder.intervals, expected);
727 }
728
729 #[test]
730 fn test_add_codepointinversionlist() {
731 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
732 let check = CodePointInversionList::try_from_inversion_list_slice(&[
733 0x5, 0xA, 0x16, 0x21, 0x2C, 0x33,
734 ])
735 .unwrap();
736 builder.add_set(&check);
737 let expected = [0x5, 0x14, 0x16, 0x21, 0x28, 0x33];
738 assert_eq!(builder.intervals, expected);
739 }
740 #[test]
741 fn test_add_char() {
742 let mut builder = CodePointInversionListBuilder::new();
743 builder.add_char('a');
744 let expected = [0x61, 0x62];
745 assert_eq!(builder.intervals, expected);
746 }
747
748 #[test]
749 fn test_add_range() {
750 let mut builder = CodePointInversionListBuilder::new();
751 builder.add_range(&('A'..='Z'));
752 let expected = [0x41, 0x5B];
753 assert_eq!(builder.intervals, expected);
754 }
755
756 #[test]
757 fn test_add_range32() {
758 let mut builder = CodePointInversionListBuilder::new();
759 builder.add_range32(&(0xd800..=0xdfff));
760 let expected = [0xd800, 0xe000];
761 assert_eq!(builder.intervals, expected);
762 }
763
764 #[test]
765 fn test_add_invalid_range() {
766 let mut builder = CodePointInversionListBuilder::new();
767 builder.add_range(&('Z'..='A'));
768 assert!(builder.intervals.is_empty());
769 }
770
771 #[test]
772 fn test_remove_empty() {
773 let mut builder = CodePointInversionListBuilder::new();
774 builder.remove(0x0, 0xA);
775 assert!(builder.intervals.is_empty());
776 }
777
778 #[test]
779 fn test_remove_entire_builder() {
780 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
781 builder.remove(0xA, 0x32);
782 assert!(builder.intervals.is_empty());
783 }
784
785 #[test]
786 fn test_remove_entire_range() {
787 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
788 builder.remove(0xA, 0x14);
789 let expected = [0x28, 0x32];
790 assert_eq!(builder.intervals, expected);
791 }
792
793 #[test]
794 fn test_remove_partial_range_left() {
795 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
796 builder.remove(0xA, 0x2B);
797 let expected = [0x2B, 0x32];
798 assert_eq!(builder.intervals, expected);
799 }
800
801 #[test]
802 fn test_remove_ne_range() {
803 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
804 builder.remove(0x14, 0x28);
805 let expected = [0xA, 0x14, 0x28, 0x32];
806 assert_eq!(builder.intervals, expected);
807 }
808
809 #[test]
810 fn test_remove_partial_range_right() {
811 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
812 builder.remove(0xF, 0x37);
813 let expected = [0xA, 0xF];
814 assert_eq!(builder.intervals, expected);
815 }
816
817 #[test]
818 fn test_remove_middle_range() {
819 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
820 builder.remove(0xC, 0x12);
821 let expected = [0xA, 0xC, 0x12, 0x14, 0x28, 0x32];
822 assert_eq!(builder.intervals, expected);
823 }
824
825 #[test]
826 fn test_remove_ne_middle_range() {
827 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
828 builder.remove(0x19, 0x1B);
829 let expected = [0xA, 0x14, 0x28, 0x32];
830 assert_eq!(builder.intervals, expected);
831 }
832
833 #[test]
834 fn test_remove_encompassed_range() {
835 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]);
836 builder.remove(0x19, 0x37);
837 let expected = [0xA, 0x14, 0x46, 0x50];
838 assert_eq!(builder.intervals, expected);
839 }
840 #[test]
841 fn test_remove_adjacent_ranges() {
842 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
843 builder.remove(0x27, 0x28);
844 builder.remove(0x28, 0x29);
845 builder.remove(0x29, 0x2A);
846 let expected = [0xA, 0x14, 0x2A, 0x32];
847 assert_eq!(builder.intervals, expected);
848 }
849
850 #[test]
851 fn test_remove_char() {
852 let mut builder = generate_tester(&[0x41, 0x46]);
853 builder.remove_char('A'); let expected = [0x42, 0x46];
855 assert_eq!(builder.intervals, expected);
856 }
857
858 #[test]
859 fn test_remove_range() {
860 let mut builder = generate_tester(&[0x41, 0x5A]);
861 builder.remove_range(&('A'..'L')); let expected = [0x4C, 0x5A];
863 assert_eq!(builder.intervals, expected);
864 }
865
866 #[test]
867 fn test_remove_set() {
868 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]);
869 let remove =
870 CodePointInversionList::try_from_inversion_list_slice(&[0xA, 0x14, 0x2D, 0x4B])
871 .unwrap();
872 builder.remove_set(&remove);
873 let expected = [0x28, 0x2D, 0x4B, 0x50];
874 assert_eq!(builder.intervals, expected);
875 }
876
877 #[test]
878 fn test_retain_char() {
879 let mut builder = generate_tester(&[0x41, 0x5A]);
880 builder.retain_char('A'); let expected = [0x41, 0x42];
882 assert_eq!(builder.intervals, expected);
883 }
884
885 #[test]
886 fn test_retain_range() {
887 let mut builder = generate_tester(&[0x41, 0x5A]);
888 builder.retain_range(&('C'..'F')); let expected = [0x43, 0x46];
890 assert_eq!(builder.intervals, expected);
891 }
892
893 #[test]
894 fn test_retain_range_empty() {
895 let mut builder = generate_tester(&[0x41, 0x46]);
896 builder.retain_range(&('F'..'Z'));
897 assert!(builder.intervals.is_empty());
898 }
899
900 #[test]
901 fn test_retain_set() {
902 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]);
903 let retain = CodePointInversionList::try_from_inversion_list_slice(&[
904 0xE, 0x14, 0x19, 0x37, 0x4D, 0x51,
905 ])
906 .unwrap();
907 builder.retain_set(&retain);
908 let expected = [0xE, 0x14, 0x28, 0x32, 0x4D, 0x50];
909 assert_eq!(builder.intervals, expected);
910 }
911
912 #[test]
913 fn test_complement() {
914 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
915 builder.complement();
916 let expected = [0x0, 0xA, 0x14, 0x28, 0x32, (char::MAX as u32) + 1];
917 assert_eq!(builder.intervals, expected);
918 }
919
920 #[test]
921 fn test_complement_empty() {
922 let mut builder = generate_tester(&[]);
923 builder.complement();
924 let expected = [0x0, (char::MAX as u32) + 1];
925 assert_eq!(builder.intervals, expected);
926
927 builder.complement();
928 let expected: [u32; 0] = [];
929 assert_eq!(builder.intervals, expected);
930 }
931
932 #[test]
933 fn test_complement_zero_max() {
934 let mut builder = generate_tester(&[0x0, 0xA, 0x5A, (char::MAX as u32) + 1]);
935 builder.complement();
936 let expected = [0xA, 0x5A];
937 assert_eq!(builder.intervals, expected);
938 }
939
940 #[test]
941 fn test_complement_interior() {
942 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
943 builder.complement_list([0xE, 0x14].iter().copied());
944 let expected = [0xA, 0xE, 0x28, 0x32];
945 assert_eq!(builder.intervals, expected);
946 }
947
948 #[test]
949 fn test_complement_exterior() {
950 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
951 builder.complement_list([0x19, 0x23].iter().copied());
952 let expected = [0xA, 0x14, 0x19, 0x23, 0x28, 0x32];
953 assert_eq!(builder.intervals, expected);
954 }
955
956 #[test]
957 fn test_complement_larger_list() {
958 let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]);
959 builder.complement_list([0x1E, 0x37, 0x3C, 0x46].iter().copied());
960 let expected = [0xA, 0x14, 0x1E, 0x28, 0x32, 0x37, 0x3C, 0x46];
961 assert_eq!(builder.intervals, expected);
962 }
963
964 #[test]
965 fn test_complement_char() {
966 let mut builder = generate_tester(&[0x41, 0x4C]); builder.complement_char('A');
968 builder.complement_char('L');
969 let expected = [0x42, 0x4D];
970 assert_eq!(builder.intervals, expected);
971 }
972
973 #[test]
974 fn test_complement_range() {
975 let mut builder = generate_tester(&[0x46, 0x4C]); builder.complement_range(&('A'..='Z'));
977 let expected = [0x41, 0x46, 0x4C, 0x5B];
978 assert_eq!(builder.intervals, expected);
979 }
980
981 #[test]
982 fn test_complement_set() {
983 let mut builder = generate_tester(&[0x43, 0x4E]);
984 let set = CodePointInversionList::try_from_inversion_list_slice(&[0x41, 0x46, 0x4B, 0x5A])
985 .unwrap();
986 builder.complement_set(&set);
987 let expected = [0x41, 0x43, 0x46, 0x4B, 0x4E, 0x5A];
988 assert_eq!(builder.intervals, expected);
989 }
990
991 #[test]
992 fn test_is_empty() {
993 let builder = CodePointInversionListBuilder::new();
994 assert!(builder.is_empty());
995 }
996}