/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bstr-1.12.1/src/byteset/scalar.rs
Line | Count | Source |
1 | | // This is adapted from `fallback.rs` from rust-memchr. It's modified to return |
2 | | // the 'inverse' query of memchr, e.g. finding the first byte not in the |
3 | | // provided set. This is simple for the 1-byte case. |
4 | | |
5 | | use core::{cmp, usize}; |
6 | | |
7 | | const USIZE_BYTES: usize = core::mem::size_of::<usize>(); |
8 | | const ALIGN_MASK: usize = core::mem::align_of::<usize>() - 1; |
9 | | |
10 | | // The number of bytes to loop at in one iteration of memchr/memrchr. |
11 | | const LOOP_SIZE: usize = 2 * USIZE_BYTES; |
12 | | |
13 | | /// Repeat the given byte into a word size number. That is, every 8 bits |
14 | | /// is equivalent to the given byte. For example, if `b` is `\x4E` or |
15 | | /// `01001110` in binary, then the returned value on a 32-bit system would be: |
16 | | /// `01001110_01001110_01001110_01001110`. |
17 | | #[inline(always)] |
18 | 0 | fn repeat_byte(b: u8) -> usize { |
19 | 0 | (b as usize) * (usize::MAX / 255) |
20 | 0 | } Unexecuted instantiation: bstr::byteset::scalar::repeat_byte Unexecuted instantiation: bstr::byteset::scalar::repeat_byte Unexecuted instantiation: bstr::byteset::scalar::repeat_byte Unexecuted instantiation: bstr::byteset::scalar::repeat_byte |
21 | | |
22 | 0 | pub fn inv_memchr(n1: u8, haystack: &[u8]) -> Option<usize> { |
23 | 0 | let vn1 = repeat_byte(n1); |
24 | 0 | let confirm = |byte| byte != n1; Unexecuted instantiation: bstr::byteset::scalar::inv_memchr::{closure#0}Unexecuted instantiation: bstr::byteset::scalar::inv_memchr::{closure#0}Unexecuted instantiation: bstr::byteset::scalar::inv_memchr::{closure#0}Unexecuted instantiation: bstr::byteset::scalar::inv_memchr::{closure#0} |
25 | 0 | let loop_size = cmp::min(LOOP_SIZE, haystack.len()); |
26 | 0 | let start_ptr = haystack.as_ptr(); |
27 | | |
28 | | unsafe { |
29 | 0 | let end_ptr = haystack.as_ptr().add(haystack.len()); |
30 | 0 | let mut ptr = start_ptr; |
31 | | |
32 | 0 | if haystack.len() < USIZE_BYTES { |
33 | 0 | return forward_search(start_ptr, end_ptr, ptr, confirm); |
34 | 0 | } |
35 | | |
36 | 0 | let chunk = read_unaligned_usize(ptr); |
37 | 0 | if (chunk ^ vn1) != 0 { |
38 | 0 | return forward_search(start_ptr, end_ptr, ptr, confirm); |
39 | 0 | } |
40 | | |
41 | 0 | ptr = ptr.add(USIZE_BYTES - (start_ptr as usize & ALIGN_MASK)); |
42 | 0 | debug_assert!(ptr > start_ptr); |
43 | 0 | debug_assert!(end_ptr.sub(USIZE_BYTES) >= start_ptr); |
44 | 0 | while loop_size == LOOP_SIZE && ptr <= end_ptr.sub(loop_size) { |
45 | 0 | debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES); |
46 | | |
47 | 0 | let a = *(ptr as *const usize); |
48 | 0 | let b = *(ptr.add(USIZE_BYTES) as *const usize); |
49 | 0 | let eqa = (a ^ vn1) != 0; |
50 | 0 | let eqb = (b ^ vn1) != 0; |
51 | 0 | if eqa || eqb { |
52 | 0 | break; |
53 | 0 | } |
54 | 0 | ptr = ptr.add(LOOP_SIZE); |
55 | | } |
56 | 0 | forward_search(start_ptr, end_ptr, ptr, confirm) |
57 | | } |
58 | 0 | } Unexecuted instantiation: bstr::byteset::scalar::inv_memchr Unexecuted instantiation: bstr::byteset::scalar::inv_memchr Unexecuted instantiation: bstr::byteset::scalar::inv_memchr Unexecuted instantiation: bstr::byteset::scalar::inv_memchr |
59 | | |
60 | | /// Return the last index not matching the byte `x` in `text`. |
61 | 0 | pub fn inv_memrchr(n1: u8, haystack: &[u8]) -> Option<usize> { |
62 | 0 | let vn1 = repeat_byte(n1); |
63 | 0 | let confirm = |byte| byte != n1; Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr::{closure#0}Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr::{closure#0}Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr::{closure#0}Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr::{closure#0} |
64 | 0 | let loop_size = cmp::min(LOOP_SIZE, haystack.len()); |
65 | 0 | let start_ptr = haystack.as_ptr(); |
66 | | |
67 | | unsafe { |
68 | 0 | let end_ptr = haystack.as_ptr().add(haystack.len()); |
69 | 0 | let mut ptr = end_ptr; |
70 | | |
71 | 0 | if haystack.len() < USIZE_BYTES { |
72 | 0 | return reverse_search(start_ptr, end_ptr, ptr, confirm); |
73 | 0 | } |
74 | | |
75 | 0 | let chunk = read_unaligned_usize(ptr.sub(USIZE_BYTES)); |
76 | 0 | if (chunk ^ vn1) != 0 { |
77 | 0 | return reverse_search(start_ptr, end_ptr, ptr, confirm); |
78 | 0 | } |
79 | | |
80 | 0 | ptr = ptr.sub(end_ptr as usize & ALIGN_MASK); |
81 | 0 | debug_assert!(start_ptr <= ptr && ptr <= end_ptr); |
82 | 0 | while loop_size == LOOP_SIZE && ptr >= start_ptr.add(loop_size) { |
83 | 0 | debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES); |
84 | | |
85 | 0 | let a = *(ptr.sub(2 * USIZE_BYTES) as *const usize); |
86 | 0 | let b = *(ptr.sub(1 * USIZE_BYTES) as *const usize); |
87 | 0 | let eqa = (a ^ vn1) != 0; |
88 | 0 | let eqb = (b ^ vn1) != 0; |
89 | 0 | if eqa || eqb { |
90 | 0 | break; |
91 | 0 | } |
92 | 0 | ptr = ptr.sub(loop_size); |
93 | | } |
94 | 0 | reverse_search(start_ptr, end_ptr, ptr, confirm) |
95 | | } |
96 | 0 | } Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr Unexecuted instantiation: bstr::byteset::scalar::inv_memrchr |
97 | | |
98 | | #[inline(always)] |
99 | 5.36M | unsafe fn forward_search<F: Fn(u8) -> bool>( |
100 | 5.36M | start_ptr: *const u8, |
101 | 5.36M | end_ptr: *const u8, |
102 | 5.36M | mut ptr: *const u8, |
103 | 5.36M | confirm: F, |
104 | 5.36M | ) -> Option<usize> { |
105 | 5.36M | debug_assert!(start_ptr <= ptr); |
106 | 5.36M | debug_assert!(ptr <= end_ptr); |
107 | | |
108 | 17.6M | while ptr < end_ptr { |
109 | 16.7M | if confirm(*ptr) { |
110 | 4.51M | return Some(sub(ptr, start_ptr)); |
111 | 12.2M | } |
112 | 12.2M | ptr = ptr.offset(1); |
113 | | } |
114 | 855k | None |
115 | 5.36M | } Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::scalar::inv_memchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::scalar::inv_memchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::scalar::inv_memchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::scalar::inv_memchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#2}>bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#1}>Line | Count | Source | 99 | 2.67M | unsafe fn forward_search<F: Fn(u8) -> bool>( | 100 | 2.67M | start_ptr: *const u8, | 101 | 2.67M | end_ptr: *const u8, | 102 | 2.67M | mut ptr: *const u8, | 103 | 2.67M | confirm: F, | 104 | 2.67M | ) -> Option<usize> { | 105 | 2.67M | debug_assert!(start_ptr <= ptr); | 106 | 2.67M | debug_assert!(ptr <= end_ptr); | 107 | | | 108 | 2.69M | while ptr < end_ptr { | 109 | 2.69M | if confirm(*ptr) { | 110 | 2.67M | return Some(sub(ptr, start_ptr)); | 111 | 19.3k | } | 112 | 19.3k | ptr = ptr.offset(1); | 113 | | } | 114 | 1.26k | None | 115 | 2.67M | } |
Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Line | Count | Source | 99 | 2.69M | unsafe fn forward_search<F: Fn(u8) -> bool>( | 100 | 2.69M | start_ptr: *const u8, | 101 | 2.69M | end_ptr: *const u8, | 102 | 2.69M | mut ptr: *const u8, | 103 | 2.69M | confirm: F, | 104 | 2.69M | ) -> Option<usize> { | 105 | 2.69M | debug_assert!(start_ptr <= ptr); | 106 | 2.69M | debug_assert!(ptr <= end_ptr); | 107 | | | 108 | 14.9M | while ptr < end_ptr { | 109 | 14.0M | if confirm(*ptr) { | 110 | 1.83M | return Some(sub(ptr, start_ptr)); | 111 | 12.2M | } | 112 | 12.2M | ptr = ptr.offset(1); | 113 | | } | 114 | 854k | None | 115 | 2.69M | } |
Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search::<bstr::byteset::find::{closure#0}> |
116 | | |
117 | | #[inline(always)] |
118 | 0 | unsafe fn reverse_search<F: Fn(u8) -> bool>( |
119 | 0 | start_ptr: *const u8, |
120 | 0 | end_ptr: *const u8, |
121 | 0 | mut ptr: *const u8, |
122 | 0 | confirm: F, |
123 | 0 | ) -> Option<usize> { |
124 | 0 | debug_assert!(start_ptr <= ptr); |
125 | 0 | debug_assert!(ptr <= end_ptr); |
126 | | |
127 | 0 | while ptr > start_ptr { |
128 | 0 | ptr = ptr.offset(-1); |
129 | 0 | if confirm(*ptr) { |
130 | 0 | return Some(sub(ptr, start_ptr)); |
131 | 0 | } |
132 | | } |
133 | 0 | None |
134 | 0 | } Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::scalar::inv_memrchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::scalar::inv_memrchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::scalar::inv_memrchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::scalar::inv_memrchr::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search::<bstr::byteset::rfind_not::{closure#1}> |
135 | | |
136 | 0 | unsafe fn read_unaligned_usize(ptr: *const u8) -> usize { |
137 | 0 | (ptr as *const usize).read_unaligned() |
138 | 0 | } Unexecuted instantiation: bstr::byteset::scalar::read_unaligned_usize Unexecuted instantiation: bstr::byteset::scalar::read_unaligned_usize Unexecuted instantiation: bstr::byteset::scalar::read_unaligned_usize Unexecuted instantiation: bstr::byteset::scalar::read_unaligned_usize |
139 | | |
140 | | /// Subtract `b` from `a` and return the difference. `a` should be greater than |
141 | | /// or equal to `b`. |
142 | 4.51M | fn sub(a: *const u8, b: *const u8) -> usize { |
143 | 4.51M | debug_assert!(a >= b); |
144 | 4.51M | (a as usize) - (b as usize) |
145 | 4.51M | } Unexecuted instantiation: bstr::byteset::scalar::sub Unexecuted instantiation: bstr::byteset::scalar::sub bstr::byteset::scalar::sub Line | Count | Source | 142 | 4.51M | fn sub(a: *const u8, b: *const u8) -> usize { | 143 | 4.51M | debug_assert!(a >= b); | 144 | 4.51M | (a as usize) - (b as usize) | 145 | 4.51M | } |
Unexecuted instantiation: bstr::byteset::scalar::sub |
146 | | |
147 | | /// Safe wrapper around `forward_search` |
148 | | #[inline] |
149 | 5.36M | pub(crate) fn forward_search_bytes<F: Fn(u8) -> bool>( |
150 | 5.36M | s: &[u8], |
151 | 5.36M | confirm: F, |
152 | 5.36M | ) -> Option<usize> { |
153 | | unsafe { |
154 | 5.36M | let start = s.as_ptr(); |
155 | 5.36M | let end = start.add(s.len()); |
156 | 5.36M | forward_search(start, end, start, confirm) |
157 | | } |
158 | 5.36M | } Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#2}>bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#1}>Line | Count | Source | 149 | 2.67M | pub(crate) fn forward_search_bytes<F: Fn(u8) -> bool>( | 150 | 2.67M | s: &[u8], | 151 | 2.67M | confirm: F, | 152 | 2.67M | ) -> Option<usize> { | 153 | | unsafe { | 154 | 2.67M | let start = s.as_ptr(); | 155 | 2.67M | let end = start.add(s.len()); | 156 | 2.67M | forward_search(start, end, start, confirm) | 157 | | } | 158 | 2.67M | } |
Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Line | Count | Source | 149 | 2.69M | pub(crate) fn forward_search_bytes<F: Fn(u8) -> bool>( | 150 | 2.69M | s: &[u8], | 151 | 2.69M | confirm: F, | 152 | 2.69M | ) -> Option<usize> { | 153 | | unsafe { | 154 | 2.69M | let start = s.as_ptr(); | 155 | 2.69M | let end = start.add(s.len()); | 156 | 2.69M | forward_search(start, end, start, confirm) | 157 | | } | 158 | 2.69M | } |
Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::forward_search_bytes::<bstr::byteset::find::{closure#0}> |
159 | | |
160 | | /// Safe wrapper around `reverse_search` |
161 | | #[inline] |
162 | 0 | pub(crate) fn reverse_search_bytes<F: Fn(u8) -> bool>( |
163 | 0 | s: &[u8], |
164 | 0 | confirm: F, |
165 | 0 | ) -> Option<usize> { |
166 | | unsafe { |
167 | 0 | let start = s.as_ptr(); |
168 | 0 | let end = start.add(s.len()); |
169 | 0 | reverse_search(start, end, end, confirm) |
170 | | } |
171 | 0 | } Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#1}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<_> Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#0}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#2}>Unexecuted instantiation: bstr::byteset::scalar::reverse_search_bytes::<bstr::byteset::rfind_not::{closure#1}> |
172 | | |
173 | | #[cfg(all(test, feature = "std"))] |
174 | | mod tests { |
175 | | use alloc::{vec, vec::Vec}; |
176 | | |
177 | | use super::{inv_memchr, inv_memrchr}; |
178 | | |
179 | | // search string, search byte, inv_memchr result, inv_memrchr result. |
180 | | // these are expanded into a much larger set of tests in build_tests |
181 | | const TESTS: &[(&[u8], u8, usize, usize)] = &[ |
182 | | (b"z", b'a', 0, 0), |
183 | | (b"zz", b'a', 0, 1), |
184 | | (b"aza", b'a', 1, 1), |
185 | | (b"zaz", b'a', 0, 2), |
186 | | (b"zza", b'a', 0, 1), |
187 | | (b"zaa", b'a', 0, 0), |
188 | | (b"zzz", b'a', 0, 2), |
189 | | ]; |
190 | | |
191 | | type TestCase = (Vec<u8>, u8, Option<(usize, usize)>); |
192 | | |
193 | | fn build_tests() -> Vec<TestCase> { |
194 | | #[cfg(not(miri))] |
195 | | const MAX_PER: usize = 515; |
196 | | #[cfg(miri)] |
197 | | const MAX_PER: usize = 10; |
198 | | |
199 | | let mut result = vec![]; |
200 | | for &(search, byte, fwd_pos, rev_pos) in TESTS { |
201 | | result.push((search.to_vec(), byte, Some((fwd_pos, rev_pos)))); |
202 | | for i in 1..MAX_PER { |
203 | | // add a bunch of copies of the search byte to the end. |
204 | | let mut suffixed: Vec<u8> = search.into(); |
205 | | suffixed.extend(std::iter::repeat(byte).take(i)); |
206 | | result.push((suffixed, byte, Some((fwd_pos, rev_pos)))); |
207 | | |
208 | | // add a bunch of copies of the search byte to the start. |
209 | | let mut prefixed: Vec<u8> = |
210 | | std::iter::repeat(byte).take(i).collect(); |
211 | | prefixed.extend(search); |
212 | | result.push(( |
213 | | prefixed, |
214 | | byte, |
215 | | Some((fwd_pos + i, rev_pos + i)), |
216 | | )); |
217 | | |
218 | | // add a bunch of copies of the search byte to both ends. |
219 | | let mut surrounded: Vec<u8> = |
220 | | std::iter::repeat(byte).take(i).collect(); |
221 | | surrounded.extend(search); |
222 | | surrounded.extend(std::iter::repeat(byte).take(i)); |
223 | | result.push(( |
224 | | surrounded, |
225 | | byte, |
226 | | Some((fwd_pos + i, rev_pos + i)), |
227 | | )); |
228 | | } |
229 | | } |
230 | | |
231 | | // build non-matching tests for several sizes |
232 | | for i in 0..MAX_PER { |
233 | | result.push(( |
234 | | std::iter::repeat(b'\0').take(i).collect(), |
235 | | b'\0', |
236 | | None, |
237 | | )); |
238 | | } |
239 | | |
240 | | result |
241 | | } |
242 | | |
243 | | #[test] |
244 | | fn test_inv_memchr() { |
245 | | use crate::{ByteSlice, B}; |
246 | | |
247 | | #[cfg(not(miri))] |
248 | | const MAX_OFFSET: usize = 130; |
249 | | #[cfg(miri)] |
250 | | const MAX_OFFSET: usize = 13; |
251 | | |
252 | | for (search, byte, matching) in build_tests() { |
253 | | assert_eq!( |
254 | | inv_memchr(byte, &search), |
255 | | matching.map(|m| m.0), |
256 | | "inv_memchr when searching for {:?} in {:?}", |
257 | | byte as char, |
258 | | // better printing |
259 | | B(&search).as_bstr(), |
260 | | ); |
261 | | assert_eq!( |
262 | | inv_memrchr(byte, &search), |
263 | | matching.map(|m| m.1), |
264 | | "inv_memrchr when searching for {:?} in {:?}", |
265 | | byte as char, |
266 | | // better printing |
267 | | B(&search).as_bstr(), |
268 | | ); |
269 | | // Test a rather large number off offsets for potential alignment |
270 | | // issues. |
271 | | for offset in 1..MAX_OFFSET { |
272 | | if offset >= search.len() { |
273 | | break; |
274 | | } |
275 | | // If this would cause us to shift the results off the end, |
276 | | // skip it so that we don't have to recompute them. |
277 | | if let Some((f, r)) = matching { |
278 | | if offset > f || offset > r { |
279 | | break; |
280 | | } |
281 | | } |
282 | | let realigned = &search[offset..]; |
283 | | |
284 | | let forward_pos = matching.map(|m| m.0 - offset); |
285 | | let reverse_pos = matching.map(|m| m.1 - offset); |
286 | | |
287 | | assert_eq!( |
288 | | inv_memchr(byte, &realigned), |
289 | | forward_pos, |
290 | | "inv_memchr when searching (realigned by {}) for {:?} in {:?}", |
291 | | offset, |
292 | | byte as char, |
293 | | realigned.as_bstr(), |
294 | | ); |
295 | | assert_eq!( |
296 | | inv_memrchr(byte, &realigned), |
297 | | reverse_pos, |
298 | | "inv_memrchr when searching (realigned by {}) for {:?} in {:?}", |
299 | | offset, |
300 | | byte as char, |
301 | | realigned.as_bstr(), |
302 | | ); |
303 | | } |
304 | | } |
305 | | } |
306 | | } |