1#![allow(unused_unsafe, unused_parens)] #![cfg_attr(not(any(test, mirai, feature = "verify", feature = "std")), no_std)]
31#![cfg_attr(not(any(test, mirai, feature = "verify")), no_builtins)]
32#![cfg_attr(docsrs, feature(doc_auto_cfg))]
33
34pub mod arch;
35
36#[cfg(feature = "require")]
37pub mod require;
38
39use arch::Vector;
40
41#[inline(always)] #[must_use]
70pub fn ensure(data: Vector, cond: impl Fn(Vector) -> Vector) -> bool {
71 unsafe { arch::MoveMask::new(cond(data)).all_bits_set() }
72}
73
74#[macro_export] #[doc(hidden)]
75macro_rules! ensure {
76 ($data:expr, $cond:expr) => {
77 unsafe { $crate::arch::MoveMask::new($cond($data)).all_bits_set() }
78 };
79}
80
81#[inline(always)]
110pub fn find(data: Vector, cond: impl Fn(Vector) -> Vector) -> Option<u32> {
111 let len = unsafe { arch::MoveMask::new(cond(data)).trailing_zeros() };
112 if len >= arch::MoveMask::MAX_TRAIL { None } else { Some(len) }
113}
114
115#[doc(hidden)] #[macro_export]
116macro_rules! __is_found {
117 ($cond_eval:expr, |$len:ident| $then:expr, || $otherwise:expr) => { unsafe {
118 let $len = $crate::arch::MoveMask::new($cond_eval).trailing_zeros();
119 if $len == $crate::arch::MoveMask::MAX_TRAIL { $otherwise } else { $then }
120 }};
121}
122
123#[doc(hidden)] #[macro_export]
124macro_rules! find {
125 ($data:expr, $cond:expr) => {
126 $crate::__is_found!($cond($data), |__len| Some(__len), || None)
127 };
128}
129
130#[inline] #[must_use]
165pub fn for_all_ensure_ct(data: &[u8], cond: impl Fn(Vector) -> Vector) -> bool {
166 let mut valid = true;
167 if data.len() >= arch::WIDTH {
168 unsafe { arch::scan::for_all_ensure_ct(data, cond, &mut valid) }
169 } else {
170 valid &= unsafe {
173 arch::MoveMask::new(cond(arch::load_partial(data, data.len())))
174 .trailing_ones() >= data.len() as u32
175 };
176 }
177
178 valid
179}
180
181#[inline] #[must_use]
212pub fn for_all_ensure(data: &[u8], cond: impl Fn(Vector) -> Vector) -> bool {
213 if data.len() >= arch::WIDTH {
214 unsafe { arch::scan::for_all_ensure(data, cond) }
215 } else {
216 unsafe {
217 arch::MoveMask::new(cond(arch::load_partial(data, data.len())))
218 .trailing_ones() >= data.len() as u32
219 }
220 }
221}
222
223#[inline]
250pub fn search(data: &[u8], cond: impl Fn(Vector) -> Vector) -> Option<usize> {
251 if data.len() >= arch::WIDTH {
252 unsafe { arch::scan::search(data, cond) }
253 } else {
254 match unsafe { arch::MoveMask::new(cond(arch::load_partial(data, data.len()))).trailing_zeros() } {
255 offset if offset < data.len() as u32 => Some(offset as usize),
256 _ => None
257 }
258 }
259}
260
261#[doc(hidden)] #[macro_export]
263macro_rules! comp_check_rng {
264 ($min:literal, $max:literal, $do:expr) => {
265 match ($min, $max) {
266 ($min..=$max, $min..=$max) | _ => $do
267 }
268 };
269}
270
271#[macro_export]
331macro_rules! range {
332 ($min:literal..=$max:literal) => {
333 $crate::comp_check_rng!($min, $max, $crate::arch::range::<$min, $max>())
334 };
335 ($min:literal..$max:literal) => {
336 $crate::comp_check_rng!($min, $max, $crate::arch::exclusive_range::<$min, $max>())
337 };
338 (<= $max:literal) => {
339 $crate::arch::less_than_or_eq::<$max>()
340 };
341 (< $max:literal) => {
342 $crate::arch::less_than::<$max>()
343 };
344 (>= $min:literal) => {
345 $crate::arch::greater_than_or_eq::<$min>()
346 };
347 (> $min:literal) => {
348 $crate::arch::greater_than::<$min>()
349 };
350}
351
352#[inline(always)]
382pub const fn eq(expected: u8) -> impl Fn(Vector) -> Vector {
383 move |data| unsafe { arch::eq(data, arch::splat(expected)) }
384}
385
386#[inline(always)]
410pub const fn not(cond: impl Fn(Vector) -> Vector) -> impl Fn(Vector) -> Vector {
411 move |data| unsafe { arch::not(cond(data)) }
412}
413
414#[inline(always)]
439pub const fn and(
440 a: impl Fn(Vector) -> Vector,
441 b: impl Fn(Vector) -> Vector
442) -> impl Fn(Vector) -> Vector {
443 move |data| unsafe { arch::and(a(data), b(data)) }
444}
445
446#[inline(always)]
471pub const fn or(
472 a: impl Fn(Vector) -> Vector,
473 b: impl Fn(Vector) -> Vector
474) -> impl Fn(Vector) -> Vector {
475 move |data| unsafe { arch::or(a(data), b(data)) }
476}
477
478#[inline(always)]
503pub const fn xor(
504 a: impl Fn(Vector) -> Vector,
505 b: impl Fn(Vector) -> Vector
506) -> impl Fn(Vector) -> Vector {
507 move |data| unsafe { arch::xor(a(data), b(data)) }
508}
509
510#[macro_export]
511#[doc(hidden)]
512macro_rules! __all {
513 ($left:expr $(,)?) => {
514 $left
515 };
516 ($left:expr, $right:expr $(,)?) => {
517 $crate::arch::and($left, $right)
518 };
519 ($left:expr, $right:expr, $($rest:expr),+ $(,)?) => {
520 $crate::arch::and(
521 $crate::__all!($left, $right),
522 $crate::__all!($($rest),+)
523 )
524 };
525}
526
527#[macro_export]
551macro_rules! all {
552 ($left:expr $(,)? ) => {
554 $left
555 };
556 ($left:expr, $right:expr $(,)?) => {
558 |data: $crate::arch::Vector| -> $crate::arch::Vector {
559 #[allow(unused_unsafe)]
560 unsafe { $crate::__all!($left(data), $right(data)) }
561 }
562 };
563 ($left:expr, $right:expr, $($rest:expr),+ $(,)?) => {
564 |data: $crate::arch::Vector| -> $crate::arch::Vector {
565 #[allow(unused_unsafe)]
566 unsafe { $crate::__all!($left(data), $right(data), $($rest(data)),+) }
567 }
568 };
569}
570
571#[doc(hidden)] #[macro_export]
572macro_rules! __or {
573 ($left:expr) => {
574 $left
576 };
577 ($left:expr, $right:expr $(,)?) => {
578 $crate::arch::or($left, $right)
579 };
580 ($left:expr, $right:expr, $($rest:expr),+ $(,)?) => {
581 $crate::arch::or(
582 $crate::__or!($left, $right),
583 $crate::__or!($($rest),+)
584 )
585 };
586}
587
588#[macro_export]
614macro_rules! any {
615 ($left:expr $(,)?) => {
616 $left
619 };
620 ($left:expr, $right:expr $(,)?) => {
621 |data: $crate::arch::Vector| -> $crate::arch::Vector {
622 #[allow(unused_unsafe)]
623 unsafe { $crate::__or!($left(data), $right(data)) }
624 }
625 };
626 ($left:expr, $right:expr, $($rest:expr),+ $(,)?) => {
627 |data: $crate::arch::Vector| -> $crate::arch::Vector {
628 #[allow(unused_unsafe)]
629 unsafe { $crate::__or!($left(data), $right(data), $($rest(data)),+) }
630 }
631 }
632}
633
634#[doc(hidden)] #[macro_export]
635macro_rules! __xor {
636 ($left:expr $(,)?) => {
637 $left
638 };
639 ($left:expr, $right:expr $(,)?) => {
640 $crate::arch::xor($left, $right)
641 };
642 ($left:expr, $right:expr, $($rest:expr),+ $(,)?) => {
643 $crate::arch::xor(
644 $crate::__xor!($left, $right),
645 $crate::__xor!($($rest),+)
646 )
647 };
648}
649
650#[macro_export] #[doc(hidden)]
651macro_rules! __one_of {
652 ($l_i:ident: $left:expr, $r_i:ident: $right:expr, $($rest:ident: $cond:expr),* $(,)?) => {
653 |data: $crate::arch::Vector| -> $crate::arch::Vector {
654 #[allow(unused_unsafe)]
655 unsafe {
656 let ($l_i, $r_i, $($rest),+) = ($left(data), $right(data), $($cond(data)),+);
657 $crate::arch::and(
660 $crate::__xor!($l_i, $r_i, $($rest),+),
661 $crate::arch::not($crate::__all!($l_i, $r_i, $($rest),+))
662 )
663 }
664 }
665 };
666}
667
668#[macro_export]
692macro_rules! one_of {
693 ($first:expr $(,)?) => {
694 $first
695 };
696 ($first:expr, $second:expr $(,)?) => {
697 |data: $crate::arch::Vector| -> $crate::arch::Vector {
698 #[allow(unused_unsafe)]
699 unsafe { $crate::__xor!($first(data), $second(data)) }
700 }
701 };
702 ($first:expr, $second:expr, $third:expr $(,)?) => {
703 $crate::__one_of!(first: $first, second: $second, third: $third)
704 };
705 ($first:expr, $second:expr, $third:expr, $fourth:expr $(,)?) => {
706 $crate::__one_of!(first: $first, second: $second, third: $third, fourth: $fourth)
707 };
708}
709
710#[cfg(all(test, not(mirai)))]
711mod tests {
712 use super::*;
713 use quickcheck::quickcheck;
714
715 extern crate alloc;
716 use alloc::string::String;
717 use alloc::vec::Vec;
718
719 #[test]
720 fn for_all_ensure_range_is_inclusive() {
721 let input = b"hello world";
722 let res = for_all_ensure(input, any!(range!(0..=127), eq(b' ')));
723 assert!(res);
724 }
725
726 macro_rules! one_of_eq {
727 ($($lit:literal),* $(,)?) => {
728 one_of!($(eq($lit)),*)
729 };
730 }
731
732 macro_rules! ensure_one_of {
733 ($input:ident, $($lit:literal),* $(,)?) => {
734 ensure!($input, one_of_eq!($($lit),*))
735 };
736 }
737
738 macro_rules! failure_perms {
739 ($input:ident, $f_val:literal, $a_val:literal) => {{
740 assert!(!ensure_one_of!($input, $f_val, $f_val));
741 assert!(!ensure_one_of!($input, $f_val, $f_val, $f_val));
742 assert!(!ensure_one_of!($input, $f_val, $f_val, $f_val, $f_val));
743
744 assert!(!ensure_one_of!($input, $f_val, $f_val, $a_val, $a_val));
745 assert!(!ensure_one_of!($input, $a_val, $a_val, $f_val, $f_val));
746
747 assert!(!ensure_one_of!($input, $a_val, $f_val, $a_val, $f_val));
748 assert!(!ensure_one_of!($input, $f_val, $a_val, $f_val, $a_val));
749
750 assert!(!ensure_one_of!($input, $f_val, $a_val, $a_val, $f_val));
751 assert!(!ensure_one_of!($input, $a_val, $f_val, $f_val, $a_val));
752 }};
753 }
754
755 #[test]
756 fn one_of_permutations() {
757 let input = arch::load(&[0u8; 16]);
758 failure_perms!(input, 0, 0);
759 failure_perms!(input, 0, 1);
760 failure_perms!(input, 1, 0);
761
762 assert!(ensure_one_of!(input, 0, 1, 1, 1));
763 assert!(ensure_one_of!(input, 1, 0, 1, 1));
764 assert!(ensure_one_of!(input, 1, 1, 0, 1));
765 assert!(ensure_one_of!(input, 1, 1, 1, 0));
766 assert!(ensure_one_of!(input, 0, 1, 1));
767 assert!(ensure_one_of!(input, 1, 0, 1));
768 assert!(ensure_one_of!(input, 1, 1, 0));
769 assert!(ensure_one_of!(input, 0, 1));
770 assert!(ensure_one_of!(input, 1, 0));
771 assert!(ensure_one_of!(input, 0));
772 assert!(!ensure_one_of!(input, 1));
773
774 assert!(!ensure_one_of!(input, 1, 1, 1, 1));
777 assert!(!ensure_one_of!(input, 1, 1, 1));
778 assert!(!ensure_one_of!(input, 1, 1));
779 assert!(!ensure_one_of!(input, 1));
780 }
781
782 macro_rules! one_of_nest {
783 ($($($f_lit:literal),*);* $(;)?) => {
784 one_of!(
785 $(one_of_eq!($($f_lit),*)),+
786 )
787 };
788 }
789
790 #[test]
791 fn one_of_nesting() {
792 let input = arch::load(&[1u8; 16]);
793
794 assert!(ensure!(input, one_of_nest!(
795 1, 0, 0, 0;
796 0, 0, 0, 0;
797 0, 0, 0, 0;
798 0, 0, 0, 0
799 )));
800
801 assert!(!ensure!(input, one_of_nest!(1; 1)));
802
803 assert!(ensure!(input, one_of_nest!(
804 0, 0, 0, 0; 1, 1, 1, 1; 1, 0, 0, 0 )));
808 }
809
810 macro_rules! ensure_test {
811 (
812 $input:expr, $condition:expr,
813 |$success_byte:ident| $validate_positive:expr,
814 |$failure_byte:ident| $validate_negative:expr
815 ) => {
816 if for_all_ensure($input, $condition) {
817 let mut true_success = true;
818 for $success_byte in $input {
819 true_success &= $validate_positive;
820 }
821 true_success
822 } else {
823 let mut should_have_failed = false;
824 for $failure_byte in $input {
825 should_have_failed |= $validate_negative
826 }
827 should_have_failed
828 }
829 };
830 }
831
832 macro_rules! search_test {
833 (
834 $input:expr,
835 $condition:expr, |$pos:ident| $cond_met_assertion:expr,
836 |$byte:ident| $cond_failed_assertion:expr
837 ) => {{
838 if let Some($pos) = search($input, $condition) {
839 if $pos >= $input.len() {
840 panic!(
841 "search should never return greater than or eq len. \n{:?}\t{:?} >= {}\t{}",
842 $input, $pos, $input.len(), stringify!($condition)
843 );
844 }
845 $cond_met_assertion
846 } else {
847 let mut actually_failed = true;
848 for $byte in $input {
849 actually_failed &= $cond_failed_assertion;
850 }
851 actually_failed
852 }
853 }};
854 }
855
856 macro_rules! cmp_test {
857 ($cmp:expr, $assert:pat, $input:ident) => {
858 search_test!(
859 $input.as_slice(),
860 $cmp, |pos| matches!($input[pos], $assert),
861 |byte| !matches!(byte, $assert)
862 )
863 };
864 }
865
866 macro_rules! range_test {
867 ($min:literal..=$max:literal, $input:ident) => {
868 cmp_test!(
869 range!($min..=$max), $min..=$max, $input
870 )
871 };
872 }
873
874 macro_rules! excl_r_test {
875 ($min:literal..$max:literal, $input:ident) => {
876 search_test!(
877 $input.as_slice(),
878 range!($min..$max), |pos| $input[pos] > $min && $input[pos] < $max,
879 |byte| !(byte > &$min && byte < &$max)
880 )
881 };
882 }
883
884 macro_rules! check {
885 ($test:expr, $message:expr) => {
886 if !$test {
887 println!("[{}:{}] Test failed: {}", file!(), line!(), $message);
888 return false;
889 }
890 };
891 ($test:expr $(,)?) => {
892 check!($test, stringify!($test))
893 };
894 }
895
896 macro_rules! checks {
897 ($($test:expr),+ $(,)?) => {{
898 $(check!($test);)*
899 true
900 }};
901 }
902
903 quickcheck! {
904 fn search_for_needle(s: String) -> bool {
905 if let Some(pos) = search(s.as_bytes(), eq(b'a')) {
906 s.as_bytes()[pos] == b'a'
907 } else {
908 !s.contains("a")
909 }
910 }
911 fn search_for_number(s: String) -> bool {
912 if let Some(pos) = search(s.as_bytes(), range!(b'0'..=b'9')) {
913 s.as_bytes()[pos].is_ascii_digit()
914 } else {
915 let mut has_digits = false;
916 for byte in s.as_bytes() {
917 has_digits |= byte.is_ascii_digit()
918 }
919 !has_digits
920 }
921 }
922 fn always_holds(s: String) -> bool {
923 for_all_ensure(s.as_bytes(), range!(0..=255))
924 }
925 fn range_large(s: Vec<u8>) -> bool {
926 checks!(
927 range_test!(10..=244, s),
928 range_test!(1..=254, s),
929 range_test!(54..=200, s),
930 range_test!(100..=200, s),
931 range_test!(0..=128, s),
932 range_test!(0..=129, s)
933 )
934 }
935 fn range_mid(s: Vec<u8>) -> bool {
936 checks!(
937 range_test!(100..=150, s),
938 range_test!(127..=129, s),
939 range_test!(127..=128, s),
940 range_test!(128..=129, s),
941 range_test!(120..=130, s)
942 )
943 }
944 fn range_small(s: Vec<u8>) -> bool {
945 checks!(
946 range_test!(200..=255, s),
947 range_test!(240..=255, s),
948 range_test!(255..=255, s),
949 range_test!(254..=255, s),
950 range_test!(130..=255, s),
951 range_test!(160..=255, s),
952 range_test!(1..=5, s),
953 range_test!(0..=1, s),
954 range_test!(0..=13, s),
955 range_test!(3..=60, s),
956 range_test!(30..=31, s)
957 )
958 }
959 fn excl_range_large(s: Vec<u8>) -> bool {
960 checks!(
961 excl_r_test!(10..245, s),
962 excl_r_test!(0..255, s),
963 excl_r_test!(200..254, s),
964 excl_r_test!(100..200, s),
965 excl_r_test!(60..160, s),
966 excl_r_test!(1..254, s)
967 )
968 }
969 fn excl_range_mid(s: Vec<u8>) -> bool {
970 checks!(
971 excl_r_test!(125..135, s),
972 excl_r_test!(110..140, s),
973 excl_r_test!(127..128, s),
974 excl_r_test!(128..129, s),
975 excl_r_test!(127..129, s),
976 excl_r_test!(126..129, s),
977 excl_r_test!(126..128, s),
978 excl_r_test!(128..130, s)
979 )
980 }
981 fn excl_range_small(s: Vec<u8>) -> bool {
982 checks!(
983 excl_r_test!(0..1, s),
984 excl_r_test!(0..2, s),
985 excl_r_test!(0..5, s),
986 excl_r_test!(254..255, s),
987 excl_r_test!(253..255, s),
988 excl_r_test!(250..255, s),
989 excl_r_test!(1..5, s),
990 excl_r_test!(2..5, s),
991 excl_r_test!(4..5, s),
992 )
993 }
994 fn less_than_always_false(s: Vec<u8>) -> bool {
995 search_test!(
996 s.as_slice(),
997 range!(< 0), |_cannot_happen| false,
998 |_na| true
999 )
1000 }
1001 fn less_than_large(s: Vec<u8>) -> bool {
1002 checks!(
1003 cmp_test!(range!(< 255), 0..=254, s),
1004 cmp_test!(range!(< 240), 0..=239, s),
1005 cmp_test!(range!(< 254), 0..=253, s),
1006 cmp_test!(range!(< 200), 0..=199, s),
1007 cmp_test!(range!(< 140), 0..=139, s)
1008 )
1009 }
1010 fn less_than_mid(s: Vec<u8>) -> bool {
1011 checks!(
1012 cmp_test!(range!(< 128), 0..=127, s),
1013 cmp_test!(range!(< 129), 0..=128, s),
1014 cmp_test!(range!(< 128), 0..=127, s),
1015 cmp_test!(range!(< 130), 0..=129, s)
1016 )
1017 }
1018 fn less_than_small(s: Vec<u8>) -> bool {
1019 checks!(
1020 cmp_test!(range!(< 30), 0..=29, s),
1021 cmp_test!(range!(< 1), 0, s),
1022 cmp_test!(range!(< 64), 0..=63, s),
1023 cmp_test!(range!(< 120), 0..=119, s)
1024 )
1025 }
1026 fn less_than_or_eq_small(s: Vec<u8>) -> bool {
1027 checks!(
1028 cmp_test!(range!(<= 30), 0..=30, s),
1029 cmp_test!(range!(<= 0), 0, s),
1030 cmp_test!(range!(<= 1), 0..=1, s),
1031 cmp_test!(range!(<= 2), 0..=2, s)
1032 )
1033 }
1034 fn less_than_or_eq_mid(s: Vec<u8>) -> bool {
1035 checks!(
1036 cmp_test!(range!(<= 128), 0..=128, s),
1037 cmp_test!(range!(<= 129), 0..=129, s),
1038 cmp_test!(range!(<= 127), 0..=127, s),
1039 cmp_test!(range!(<= 130), 0..=130, s)
1040 )
1041 }
1042 fn less_than_or_eq_large(s: Vec<u8>) -> bool {
1043 checks!(
1044 cmp_test!(range!(<= 254), 0..=254, s),
1045 cmp_test!(range!(<= 250), 0..=250, s),
1046 cmp_test!(range!(<= 200), 0..=200, s),
1047 cmp_test!(range!(<= 160), 0..=160, s)
1048 )
1049 }
1050 fn less_than_or_eq_always_true(s: Vec<u8>) -> bool {
1051 search_test!(
1052 s.as_slice(),
1053 range!(<= 255), |_always| true,
1054 |_never| false
1055 )
1056 }
1057 fn greater_than_always_false(s: Vec<u8>) -> bool {
1058 search_test!(
1059 s.as_slice(),
1060 range!(> 255), |_never| false,
1061 |_always| true
1062 )
1063 }
1064 fn greater_than_small(s: Vec<u8>) -> bool {
1065 checks!(
1066 cmp_test!(range!(> 254), 255, s),
1067 cmp_test!(range!(> 250), 251..=255, s),
1068 cmp_test!(range!(> 253), 254..=255, s),
1069 cmp_test!(range!(> 230), 231..=255, s),
1070 cmp_test!(range!(> 190), 191..=255, s)
1071 )
1072 }
1073 fn greater_than_mid(s: Vec<u8>) -> bool {
1074 checks!(
1075 cmp_test!(range!(> 128), 129..=255, s),
1076 cmp_test!(range!(> 127), 128..=255, s),
1077 cmp_test!(range!(> 129), 130..=255, s),
1078 cmp_test!(range!(> 125), 126..=255, s)
1079 )
1080 }
1081 fn greater_than_large(s: Vec<u8>) -> bool {
1082 checks!(
1083 cmp_test!(range!(> 0), 1..=255, s),
1084 cmp_test!(range!(> 50), 51..=255, s),
1085 cmp_test!(range!(> 90), 91..=255, s),
1086 cmp_test!(range!(> 1), 2..=255, s)
1087 )
1088 }
1089 fn greater_than_or_eq_always_true(s: Vec<u8>) -> bool {
1090 search_test!(
1091 s.as_slice(),
1092 range!(>= 0), |_always| true,
1093 |_never| false
1094 )
1095 }
1096 fn greater_than_or_eq_small(s: Vec<u8>) -> bool {
1097 checks!(
1098 cmp_test!(range!(>= 255), 255, s),
1099 cmp_test!(range!(>= 254), 254..=255, s),
1100 cmp_test!(range!(>= 250), 250..=255, s),
1101 cmp_test!(range!(>= 230), 230..=255, s),
1102 cmp_test!(range!(>= 200), 200..=255, s)
1103 )
1104 }
1105 fn greater_than_or_eq_mid(s: Vec<u8>) -> bool {
1106 checks!(
1107 cmp_test!(range!(>= 128), 128..=255, s),
1108 cmp_test!(range!(>= 127), 127..=255, s),
1109 cmp_test!(range!(>= 129), 129..=255, s),
1110 cmp_test!(range!(>= 126), 126..=255, s),
1111 cmp_test!(range!(>= 130), 130..=255, s)
1112 )
1113 }
1114 fn greater_than_or_eq_large(s: Vec<u8>) -> bool {
1115 checks!(
1116 cmp_test!(range!(>= 1), 1..=255, s),
1117 cmp_test!(range!(>= 3), 3..=255, s),
1118 cmp_test!(range!(>= 64), 64..=255, s),
1119 cmp_test!(range!(>= 90), 90..=255, s),
1120 cmp_test!(range!(>= 120), 120..=255, s)
1121 )
1122 }
1123
1124 fn basic_for_all_ensure(s: Vec<u8>) -> bool {
1125 checks!(
1126 ensure_test!(
1127 s.as_slice(), eq(0),
1128 |succ| succ == &0,
1129 |fail| fail != &0
1130 ),
1131 ensure_test!(
1132 s.as_slice(), range!(0..=250),
1133 |succ| matches!(succ, 0..=250),
1134 |fail| matches!(fail, 251..=255)
1135 ),
1136 ensure_test!(
1137 s.as_slice(), not(eq(0)),
1138 |succ| succ != &0,
1139 |fail| fail == &0
1140 ),
1141 ensure_test!(
1142 s.as_slice(), any!(eq(0), eq(1)),
1143 |succ| matches!(succ, 0..=1),
1144 |fail| matches!(fail, 2..=255)
1145 ),
1146 ensure_test!(
1147 s.as_slice(), all!(eq(0), eq(0)),
1148 |succ| succ == &0,
1149 |fail| fail != &0
1150 ),
1151 ensure_test!(
1152 s.as_slice(), all!(eq(0), eq(1)),
1153 |_succ| false,
1154 |_fail| true
1155 ),
1156 ensure_test!(
1157 s.as_slice(), any!(eq(0), not(eq(0))),
1158 |_succ| true,
1159 |_fail| false
1160 )
1161 )
1162 }
1163 }
1164}
1165
1166#[cfg(test)]
1167mod mirai_tests {
1168 use crate::{eq, for_all_ensure, for_all_ensure_ct, search};
1169
1170 #[test]
1171 fn simple_search() {
1172 let input = b"I am a simple input to evaluate the correctness of the search adjflkasdfl;kjasdfl;kjasdl;kjasl;kdjf";
1173
1174 let res = search(input, eq(b'h')).unwrap();
1175 assert_eq!(input[res], b'h');
1176
1177 let res = search(input, eq(input[16])).unwrap();
1178 assert_eq!(input[res], input[16]);
1179
1180 let res = for_all_ensure_ct(input, eq(b' '));
1181 assert!(!res);
1182
1183 let res = for_all_ensure(input, eq(b' '));
1184 assert!(!res);
1185 }
1186}