/rust/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.7.5/src/memchr.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use core::iter::Rev; |
2 | | |
3 | | use crate::arch::generic::memchr as generic; |
4 | | |
5 | | /// Search for the first occurrence of a byte in a slice. |
6 | | /// |
7 | | /// This returns the index corresponding to the first occurrence of `needle` in |
8 | | /// `haystack`, or `None` if one is not found. If an index is returned, it is |
9 | | /// guaranteed to be less than `haystack.len()`. |
10 | | /// |
11 | | /// While this is semantically the same as something like |
12 | | /// `haystack.iter().position(|&b| b == needle)`, this routine will attempt to |
13 | | /// use highly optimized vector operations that can be an order of magnitude |
14 | | /// faster (or more). |
15 | | /// |
16 | | /// # Example |
17 | | /// |
18 | | /// This shows how to find the first position of a byte in a byte string. |
19 | | /// |
20 | | /// ``` |
21 | | /// use memchr::memchr; |
22 | | /// |
23 | | /// let haystack = b"the quick brown fox"; |
24 | | /// assert_eq!(memchr(b'k', haystack), Some(8)); |
25 | | /// ``` |
26 | | #[inline] |
27 | 0 | pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> { |
28 | 0 | // SAFETY: memchr_raw, when a match is found, always returns a valid |
29 | 0 | // pointer between start and end. |
30 | 0 | unsafe { |
31 | 0 | generic::search_slice_with_raw(haystack, |start, end| { |
32 | 0 | memchr_raw(needle, start, end) |
33 | 0 | }) |
34 | 0 | } |
35 | 0 | } |
36 | | |
37 | | /// Search for the last occurrence of a byte in a slice. |
38 | | /// |
39 | | /// This returns the index corresponding to the last occurrence of `needle` in |
40 | | /// `haystack`, or `None` if one is not found. If an index is returned, it is |
41 | | /// guaranteed to be less than `haystack.len()`. |
42 | | /// |
43 | | /// While this is semantically the same as something like |
44 | | /// `haystack.iter().rposition(|&b| b == needle)`, this routine will attempt to |
45 | | /// use highly optimized vector operations that can be an order of magnitude |
46 | | /// faster (or more). |
47 | | /// |
48 | | /// # Example |
49 | | /// |
50 | | /// This shows how to find the last position of a byte in a byte string. |
51 | | /// |
52 | | /// ``` |
53 | | /// use memchr::memrchr; |
54 | | /// |
55 | | /// let haystack = b"the quick brown fox"; |
56 | | /// assert_eq!(memrchr(b'o', haystack), Some(17)); |
57 | | /// ``` |
58 | | #[inline] |
59 | 0 | pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> { |
60 | 0 | // SAFETY: memrchr_raw, when a match is found, always returns a valid |
61 | 0 | // pointer between start and end. |
62 | 0 | unsafe { |
63 | 0 | generic::search_slice_with_raw(haystack, |start, end| { |
64 | 0 | memrchr_raw(needle, start, end) |
65 | 0 | }) |
66 | 0 | } |
67 | 0 | } |
68 | | |
69 | | /// Search for the first occurrence of two possible bytes in a haystack. |
70 | | /// |
71 | | /// This returns the index corresponding to the first occurrence of one of the |
72 | | /// needle bytes in `haystack`, or `None` if one is not found. If an index is |
73 | | /// returned, it is guaranteed to be less than `haystack.len()`. |
74 | | /// |
75 | | /// While this is semantically the same as something like |
76 | | /// `haystack.iter().position(|&b| b == needle1 || b == needle2)`, this routine |
77 | | /// will attempt to use highly optimized vector operations that can be an order |
78 | | /// of magnitude faster (or more). |
79 | | /// |
80 | | /// # Example |
81 | | /// |
82 | | /// This shows how to find the first position of one of two possible bytes in a |
83 | | /// haystack. |
84 | | /// |
85 | | /// ``` |
86 | | /// use memchr::memchr2; |
87 | | /// |
88 | | /// let haystack = b"the quick brown fox"; |
89 | | /// assert_eq!(memchr2(b'k', b'q', haystack), Some(4)); |
90 | | /// ``` |
91 | | #[inline] |
92 | 0 | pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> { |
93 | 0 | // SAFETY: memchr2_raw, when a match is found, always returns a valid |
94 | 0 | // pointer between start and end. |
95 | 0 | unsafe { |
96 | 0 | generic::search_slice_with_raw(haystack, |start, end| { |
97 | 0 | memchr2_raw(needle1, needle2, start, end) |
98 | 0 | }) |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | /// Search for the last occurrence of two possible bytes in a haystack. |
103 | | /// |
104 | | /// This returns the index corresponding to the last occurrence of one of the |
105 | | /// needle bytes in `haystack`, or `None` if one is not found. If an index is |
106 | | /// returned, it is guaranteed to be less than `haystack.len()`. |
107 | | /// |
108 | | /// While this is semantically the same as something like |
109 | | /// `haystack.iter().rposition(|&b| b == needle1 || b == needle2)`, this |
110 | | /// routine will attempt to use highly optimized vector operations that can be |
111 | | /// an order of magnitude faster (or more). |
112 | | /// |
113 | | /// # Example |
114 | | /// |
115 | | /// This shows how to find the last position of one of two possible bytes in a |
116 | | /// haystack. |
117 | | /// |
118 | | /// ``` |
119 | | /// use memchr::memrchr2; |
120 | | /// |
121 | | /// let haystack = b"the quick brown fox"; |
122 | | /// assert_eq!(memrchr2(b'k', b'o', haystack), Some(17)); |
123 | | /// ``` |
124 | | #[inline] |
125 | 0 | pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> { |
126 | 0 | // SAFETY: memrchr2_raw, when a match is found, always returns a valid |
127 | 0 | // pointer between start and end. |
128 | 0 | unsafe { |
129 | 0 | generic::search_slice_with_raw(haystack, |start, end| { |
130 | 0 | memrchr2_raw(needle1, needle2, start, end) |
131 | 0 | }) |
132 | 0 | } |
133 | 0 | } |
134 | | |
135 | | /// Search for the first occurrence of three possible bytes in a haystack. |
136 | | /// |
137 | | /// This returns the index corresponding to the first occurrence of one of the |
138 | | /// needle bytes in `haystack`, or `None` if one is not found. If an index is |
139 | | /// returned, it is guaranteed to be less than `haystack.len()`. |
140 | | /// |
141 | | /// While this is semantically the same as something like |
142 | | /// `haystack.iter().position(|&b| b == needle1 || b == needle2 || b == needle3)`, |
143 | | /// this routine will attempt to use highly optimized vector operations that |
144 | | /// can be an order of magnitude faster (or more). |
145 | | /// |
146 | | /// # Example |
147 | | /// |
148 | | /// This shows how to find the first position of one of three possible bytes in |
149 | | /// a haystack. |
150 | | /// |
151 | | /// ``` |
152 | | /// use memchr::memchr3; |
153 | | /// |
154 | | /// let haystack = b"the quick brown fox"; |
155 | | /// assert_eq!(memchr3(b'k', b'q', b'u', haystack), Some(4)); |
156 | | /// ``` |
157 | | #[inline] |
158 | 0 | pub fn memchr3( |
159 | 0 | needle1: u8, |
160 | 0 | needle2: u8, |
161 | 0 | needle3: u8, |
162 | 0 | haystack: &[u8], |
163 | 0 | ) -> Option<usize> { |
164 | 0 | // SAFETY: memchr3_raw, when a match is found, always returns a valid |
165 | 0 | // pointer between start and end. |
166 | 0 | unsafe { |
167 | 0 | generic::search_slice_with_raw(haystack, |start, end| { |
168 | 0 | memchr3_raw(needle1, needle2, needle3, start, end) |
169 | 0 | }) |
170 | 0 | } |
171 | 0 | } |
172 | | |
173 | | /// Search for the last occurrence of three possible bytes in a haystack. |
174 | | /// |
175 | | /// This returns the index corresponding to the last occurrence of one of the |
176 | | /// needle bytes in `haystack`, or `None` if one is not found. If an index is |
177 | | /// returned, it is guaranteed to be less than `haystack.len()`. |
178 | | /// |
179 | | /// While this is semantically the same as something like |
180 | | /// `haystack.iter().rposition(|&b| b == needle1 || b == needle2 || b == needle3)`, |
181 | | /// this routine will attempt to use highly optimized vector operations that |
182 | | /// can be an order of magnitude faster (or more). |
183 | | /// |
184 | | /// # Example |
185 | | /// |
186 | | /// This shows how to find the last position of one of three possible bytes in |
187 | | /// a haystack. |
188 | | /// |
189 | | /// ``` |
190 | | /// use memchr::memrchr3; |
191 | | /// |
192 | | /// let haystack = b"the quick brown fox"; |
193 | | /// assert_eq!(memrchr3(b'k', b'o', b'n', haystack), Some(17)); |
194 | | /// ``` |
195 | | #[inline] |
196 | 0 | pub fn memrchr3( |
197 | 0 | needle1: u8, |
198 | 0 | needle2: u8, |
199 | 0 | needle3: u8, |
200 | 0 | haystack: &[u8], |
201 | 0 | ) -> Option<usize> { |
202 | 0 | // SAFETY: memrchr3_raw, when a match is found, always returns a valid |
203 | 0 | // pointer between start and end. |
204 | 0 | unsafe { |
205 | 0 | generic::search_slice_with_raw(haystack, |start, end| { |
206 | 0 | memrchr3_raw(needle1, needle2, needle3, start, end) |
207 | 0 | }) |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | /// Returns an iterator over all occurrences of the needle in a haystack. |
212 | | /// |
213 | | /// The iterator returned implements `DoubleEndedIterator`. This means it |
214 | | /// can also be used to find occurrences in reverse order. |
215 | | #[inline] |
216 | 0 | pub fn memchr_iter<'h>(needle: u8, haystack: &'h [u8]) -> Memchr<'h> { |
217 | 0 | Memchr::new(needle, haystack) |
218 | 0 | } |
219 | | |
220 | | /// Returns an iterator over all occurrences of the needle in a haystack, in |
221 | | /// reverse. |
222 | | #[inline] |
223 | 0 | pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>> { |
224 | 0 | Memchr::new(needle, haystack).rev() |
225 | 0 | } |
226 | | |
227 | | /// Returns an iterator over all occurrences of the needles in a haystack. |
228 | | /// |
229 | | /// The iterator returned implements `DoubleEndedIterator`. This means it |
230 | | /// can also be used to find occurrences in reverse order. |
231 | | #[inline] |
232 | 0 | pub fn memchr2_iter<'h>( |
233 | 0 | needle1: u8, |
234 | 0 | needle2: u8, |
235 | 0 | haystack: &'h [u8], |
236 | 0 | ) -> Memchr2<'h> { |
237 | 0 | Memchr2::new(needle1, needle2, haystack) |
238 | 0 | } |
239 | | |
240 | | /// Returns an iterator over all occurrences of the needles in a haystack, in |
241 | | /// reverse. |
242 | | #[inline] |
243 | 0 | pub fn memrchr2_iter( |
244 | 0 | needle1: u8, |
245 | 0 | needle2: u8, |
246 | 0 | haystack: &[u8], |
247 | 0 | ) -> Rev<Memchr2<'_>> { |
248 | 0 | Memchr2::new(needle1, needle2, haystack).rev() |
249 | 0 | } |
250 | | |
251 | | /// Returns an iterator over all occurrences of the needles in a haystack. |
252 | | /// |
253 | | /// The iterator returned implements `DoubleEndedIterator`. This means it |
254 | | /// can also be used to find occurrences in reverse order. |
255 | | #[inline] |
256 | 0 | pub fn memchr3_iter<'h>( |
257 | 0 | needle1: u8, |
258 | 0 | needle2: u8, |
259 | 0 | needle3: u8, |
260 | 0 | haystack: &'h [u8], |
261 | 0 | ) -> Memchr3<'h> { |
262 | 0 | Memchr3::new(needle1, needle2, needle3, haystack) |
263 | 0 | } |
264 | | |
265 | | /// Returns an iterator over all occurrences of the needles in a haystack, in |
266 | | /// reverse. |
267 | | #[inline] |
268 | 0 | pub fn memrchr3_iter( |
269 | 0 | needle1: u8, |
270 | 0 | needle2: u8, |
271 | 0 | needle3: u8, |
272 | 0 | haystack: &[u8], |
273 | 0 | ) -> Rev<Memchr3<'_>> { |
274 | 0 | Memchr3::new(needle1, needle2, needle3, haystack).rev() |
275 | 0 | } |
276 | | |
277 | | /// An iterator over all occurrences of a single byte in a haystack. |
278 | | /// |
279 | | /// This iterator implements `DoubleEndedIterator`, which means it can also be |
280 | | /// used to find occurrences in reverse order. |
281 | | /// |
282 | | /// This iterator is created by the [`memchr_iter`] or `[memrchr_iter`] |
283 | | /// functions. It can also be created with the [`Memchr::new`] method. |
284 | | /// |
285 | | /// The lifetime parameter `'h` refers to the lifetime of the haystack being |
286 | | /// searched. |
287 | | #[derive(Clone, Debug)] |
288 | | pub struct Memchr<'h> { |
289 | | needle1: u8, |
290 | | it: crate::arch::generic::memchr::Iter<'h>, |
291 | | } |
292 | | |
293 | | impl<'h> Memchr<'h> { |
294 | | /// Returns an iterator over all occurrences of the needle byte in the |
295 | | /// given haystack. |
296 | | /// |
297 | | /// The iterator returned implements `DoubleEndedIterator`. This means it |
298 | | /// can also be used to find occurrences in reverse order. |
299 | | #[inline] |
300 | 0 | pub fn new(needle1: u8, haystack: &'h [u8]) -> Memchr<'h> { |
301 | 0 | Memchr { |
302 | 0 | needle1, |
303 | 0 | it: crate::arch::generic::memchr::Iter::new(haystack), |
304 | 0 | } |
305 | 0 | } |
306 | | } |
307 | | |
308 | | impl<'h> Iterator for Memchr<'h> { |
309 | | type Item = usize; |
310 | | |
311 | | #[inline] |
312 | 0 | fn next(&mut self) -> Option<usize> { |
313 | 0 | // SAFETY: All of our implementations of memchr ensure that any |
314 | 0 | // pointers returns will fall within the start and end bounds, and this |
315 | 0 | // upholds the safety contract of `self.it.next`. |
316 | 0 | unsafe { |
317 | 0 | // NOTE: I attempted to define an enum of previously created |
318 | 0 | // searchers and then switch on those here instead of just |
319 | 0 | // calling `memchr_raw` (or `One::new(..).find_raw(..)`). But |
320 | 0 | // that turned out to have a fair bit of extra overhead when |
321 | 0 | // searching very small haystacks. |
322 | 0 | self.it.next(|s, e| memchr_raw(self.needle1, s, e)) |
323 | 0 | } |
324 | 0 | } |
325 | | |
326 | | #[inline] |
327 | 0 | fn count(self) -> usize { |
328 | 0 | self.it.count(|s, e| { |
329 | 0 | // SAFETY: We rely on our generic iterator to return valid start |
330 | 0 | // and end pointers. |
331 | 0 | unsafe { count_raw(self.needle1, s, e) } |
332 | 0 | }) |
333 | 0 | } |
334 | | |
335 | | #[inline] |
336 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
337 | 0 | self.it.size_hint() |
338 | 0 | } |
339 | | } |
340 | | |
341 | | impl<'h> DoubleEndedIterator for Memchr<'h> { |
342 | | #[inline] |
343 | 0 | fn next_back(&mut self) -> Option<usize> { |
344 | 0 | // SAFETY: All of our implementations of memchr ensure that any |
345 | 0 | // pointers returns will fall within the start and end bounds, and this |
346 | 0 | // upholds the safety contract of `self.it.next_back`. |
347 | 0 | unsafe { self.it.next_back(|s, e| memrchr_raw(self.needle1, s, e)) } |
348 | 0 | } |
349 | | } |
350 | | |
351 | | impl<'h> core::iter::FusedIterator for Memchr<'h> {} |
352 | | |
353 | | /// An iterator over all occurrences of two possible bytes in a haystack. |
354 | | /// |
355 | | /// This iterator implements `DoubleEndedIterator`, which means it can also be |
356 | | /// used to find occurrences in reverse order. |
357 | | /// |
358 | | /// This iterator is created by the [`memchr2_iter`] or `[memrchr2_iter`] |
359 | | /// functions. It can also be created with the [`Memchr2::new`] method. |
360 | | /// |
361 | | /// The lifetime parameter `'h` refers to the lifetime of the haystack being |
362 | | /// searched. |
363 | | #[derive(Clone, Debug)] |
364 | | pub struct Memchr2<'h> { |
365 | | needle1: u8, |
366 | | needle2: u8, |
367 | | it: crate::arch::generic::memchr::Iter<'h>, |
368 | | } |
369 | | |
370 | | impl<'h> Memchr2<'h> { |
371 | | /// Returns an iterator over all occurrences of the needle bytes in the |
372 | | /// given haystack. |
373 | | /// |
374 | | /// The iterator returned implements `DoubleEndedIterator`. This means it |
375 | | /// can also be used to find occurrences in reverse order. |
376 | | #[inline] |
377 | 0 | pub fn new(needle1: u8, needle2: u8, haystack: &'h [u8]) -> Memchr2<'h> { |
378 | 0 | Memchr2 { |
379 | 0 | needle1, |
380 | 0 | needle2, |
381 | 0 | it: crate::arch::generic::memchr::Iter::new(haystack), |
382 | 0 | } |
383 | 0 | } |
384 | | } |
385 | | |
386 | | impl<'h> Iterator for Memchr2<'h> { |
387 | | type Item = usize; |
388 | | |
389 | | #[inline] |
390 | 0 | fn next(&mut self) -> Option<usize> { |
391 | 0 | // SAFETY: All of our implementations of memchr ensure that any |
392 | 0 | // pointers returns will fall within the start and end bounds, and this |
393 | 0 | // upholds the safety contract of `self.it.next`. |
394 | 0 | unsafe { |
395 | 0 | self.it.next(|s, e| memchr2_raw(self.needle1, self.needle2, s, e)) |
396 | 0 | } |
397 | 0 | } |
398 | | |
399 | | #[inline] |
400 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
401 | 0 | self.it.size_hint() |
402 | 0 | } |
403 | | } |
404 | | |
405 | | impl<'h> DoubleEndedIterator for Memchr2<'h> { |
406 | | #[inline] |
407 | 0 | fn next_back(&mut self) -> Option<usize> { |
408 | 0 | // SAFETY: All of our implementations of memchr ensure that any |
409 | 0 | // pointers returns will fall within the start and end bounds, and this |
410 | 0 | // upholds the safety contract of `self.it.next_back`. |
411 | 0 | unsafe { |
412 | 0 | self.it.next_back(|s, e| { |
413 | 0 | memrchr2_raw(self.needle1, self.needle2, s, e) |
414 | 0 | }) |
415 | 0 | } |
416 | 0 | } |
417 | | } |
418 | | |
419 | | impl<'h> core::iter::FusedIterator for Memchr2<'h> {} |
420 | | |
421 | | /// An iterator over all occurrences of three possible bytes in a haystack. |
422 | | /// |
423 | | /// This iterator implements `DoubleEndedIterator`, which means it can also be |
424 | | /// used to find occurrences in reverse order. |
425 | | /// |
426 | | /// This iterator is created by the [`memchr2_iter`] or `[memrchr2_iter`] |
427 | | /// functions. It can also be created with the [`Memchr3::new`] method. |
428 | | /// |
429 | | /// The lifetime parameter `'h` refers to the lifetime of the haystack being |
430 | | /// searched. |
431 | | #[derive(Clone, Debug)] |
432 | | pub struct Memchr3<'h> { |
433 | | needle1: u8, |
434 | | needle2: u8, |
435 | | needle3: u8, |
436 | | it: crate::arch::generic::memchr::Iter<'h>, |
437 | | } |
438 | | |
439 | | impl<'h> Memchr3<'h> { |
440 | | /// Returns an iterator over all occurrences of the needle bytes in the |
441 | | /// given haystack. |
442 | | /// |
443 | | /// The iterator returned implements `DoubleEndedIterator`. This means it |
444 | | /// can also be used to find occurrences in reverse order. |
445 | | #[inline] |
446 | 0 | pub fn new( |
447 | 0 | needle1: u8, |
448 | 0 | needle2: u8, |
449 | 0 | needle3: u8, |
450 | 0 | haystack: &'h [u8], |
451 | 0 | ) -> Memchr3<'h> { |
452 | 0 | Memchr3 { |
453 | 0 | needle1, |
454 | 0 | needle2, |
455 | 0 | needle3, |
456 | 0 | it: crate::arch::generic::memchr::Iter::new(haystack), |
457 | 0 | } |
458 | 0 | } |
459 | | } |
460 | | |
461 | | impl<'h> Iterator for Memchr3<'h> { |
462 | | type Item = usize; |
463 | | |
464 | | #[inline] |
465 | 0 | fn next(&mut self) -> Option<usize> { |
466 | 0 | // SAFETY: All of our implementations of memchr ensure that any |
467 | 0 | // pointers returns will fall within the start and end bounds, and this |
468 | 0 | // upholds the safety contract of `self.it.next`. |
469 | 0 | unsafe { |
470 | 0 | self.it.next(|s, e| { |
471 | 0 | memchr3_raw(self.needle1, self.needle2, self.needle3, s, e) |
472 | 0 | }) |
473 | 0 | } |
474 | 0 | } |
475 | | |
476 | | #[inline] |
477 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
478 | 0 | self.it.size_hint() |
479 | 0 | } |
480 | | } |
481 | | |
482 | | impl<'h> DoubleEndedIterator for Memchr3<'h> { |
483 | | #[inline] |
484 | 0 | fn next_back(&mut self) -> Option<usize> { |
485 | 0 | // SAFETY: All of our implementations of memchr ensure that any |
486 | 0 | // pointers returns will fall within the start and end bounds, and this |
487 | 0 | // upholds the safety contract of `self.it.next_back`. |
488 | 0 | unsafe { |
489 | 0 | self.it.next_back(|s, e| { |
490 | 0 | memrchr3_raw(self.needle1, self.needle2, self.needle3, s, e) |
491 | 0 | }) |
492 | 0 | } |
493 | 0 | } |
494 | | } |
495 | | |
496 | | impl<'h> core::iter::FusedIterator for Memchr3<'h> {} |
497 | | |
498 | | /// memchr, but using raw pointers to represent the haystack. |
499 | | /// |
500 | | /// # Safety |
501 | | /// |
502 | | /// Pointers must be valid. See `One::find_raw`. |
503 | | #[inline] |
504 | 0 | unsafe fn memchr_raw( |
505 | 0 | needle: u8, |
506 | 0 | start: *const u8, |
507 | 0 | end: *const u8, |
508 | 0 | ) -> Option<*const u8> { |
509 | 0 | #[cfg(target_arch = "x86_64")] |
510 | 0 | { |
511 | 0 | // x86_64 does CPU feature detection at runtime in order to use AVX2 |
512 | 0 | // instructions even when the `avx2` feature isn't enabled at compile |
513 | 0 | // time. This function also handles using a fallback if neither AVX2 |
514 | 0 | // nor SSE2 (unusual) are available. |
515 | 0 | crate::arch::x86_64::memchr::memchr_raw(needle, start, end) |
516 | 0 | } |
517 | 0 | #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] |
518 | 0 | { |
519 | 0 | crate::arch::wasm32::memchr::memchr_raw(needle, start, end) |
520 | 0 | } |
521 | 0 | #[cfg(target_arch = "aarch64")] |
522 | 0 | { |
523 | 0 | crate::arch::aarch64::memchr::memchr_raw(needle, start, end) |
524 | 0 | } |
525 | 0 | #[cfg(not(any( |
526 | 0 | target_arch = "x86_64", |
527 | 0 | all(target_arch = "wasm32", target_feature = "simd128"), |
528 | 0 | target_arch = "aarch64" |
529 | 0 | )))] |
530 | 0 | { |
531 | 0 | crate::arch::all::memchr::One::new(needle).find_raw(start, end) |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | | /// memrchr, but using raw pointers to represent the haystack. |
536 | | /// |
537 | | /// # Safety |
538 | | /// |
539 | | /// Pointers must be valid. See `One::rfind_raw`. |
540 | | #[inline] |
541 | 0 | unsafe fn memrchr_raw( |
542 | 0 | needle: u8, |
543 | 0 | start: *const u8, |
544 | 0 | end: *const u8, |
545 | 0 | ) -> Option<*const u8> { |
546 | 0 | #[cfg(target_arch = "x86_64")] |
547 | 0 | { |
548 | 0 | crate::arch::x86_64::memchr::memrchr_raw(needle, start, end) |
549 | 0 | } |
550 | 0 | #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] |
551 | 0 | { |
552 | 0 | crate::arch::wasm32::memchr::memrchr_raw(needle, start, end) |
553 | 0 | } |
554 | 0 | #[cfg(target_arch = "aarch64")] |
555 | 0 | { |
556 | 0 | crate::arch::aarch64::memchr::memrchr_raw(needle, start, end) |
557 | 0 | } |
558 | 0 | #[cfg(not(any( |
559 | 0 | target_arch = "x86_64", |
560 | 0 | all(target_arch = "wasm32", target_feature = "simd128"), |
561 | 0 | target_arch = "aarch64" |
562 | 0 | )))] |
563 | 0 | { |
564 | 0 | crate::arch::all::memchr::One::new(needle).rfind_raw(start, end) |
565 | 0 | } |
566 | 0 | } |
567 | | |
568 | | /// memchr2, but using raw pointers to represent the haystack. |
569 | | /// |
570 | | /// # Safety |
571 | | /// |
572 | | /// Pointers must be valid. See `Two::find_raw`. |
573 | | #[inline] |
574 | 0 | unsafe fn memchr2_raw( |
575 | 0 | needle1: u8, |
576 | 0 | needle2: u8, |
577 | 0 | start: *const u8, |
578 | 0 | end: *const u8, |
579 | 0 | ) -> Option<*const u8> { |
580 | 0 | #[cfg(target_arch = "x86_64")] |
581 | 0 | { |
582 | 0 | crate::arch::x86_64::memchr::memchr2_raw(needle1, needle2, start, end) |
583 | 0 | } |
584 | 0 | #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] |
585 | 0 | { |
586 | 0 | crate::arch::wasm32::memchr::memchr2_raw(needle1, needle2, start, end) |
587 | 0 | } |
588 | 0 | #[cfg(target_arch = "aarch64")] |
589 | 0 | { |
590 | 0 | crate::arch::aarch64::memchr::memchr2_raw(needle1, needle2, start, end) |
591 | 0 | } |
592 | 0 | #[cfg(not(any( |
593 | 0 | target_arch = "x86_64", |
594 | 0 | all(target_arch = "wasm32", target_feature = "simd128"), |
595 | 0 | target_arch = "aarch64" |
596 | 0 | )))] |
597 | 0 | { |
598 | 0 | crate::arch::all::memchr::Two::new(needle1, needle2) |
599 | 0 | .find_raw(start, end) |
600 | 0 | } |
601 | 0 | } |
602 | | |
603 | | /// memrchr2, but using raw pointers to represent the haystack. |
604 | | /// |
605 | | /// # Safety |
606 | | /// |
607 | | /// Pointers must be valid. See `Two::rfind_raw`. |
608 | | #[inline] |
609 | 0 | unsafe fn memrchr2_raw( |
610 | 0 | needle1: u8, |
611 | 0 | needle2: u8, |
612 | 0 | start: *const u8, |
613 | 0 | end: *const u8, |
614 | 0 | ) -> Option<*const u8> { |
615 | 0 | #[cfg(target_arch = "x86_64")] |
616 | 0 | { |
617 | 0 | crate::arch::x86_64::memchr::memrchr2_raw(needle1, needle2, start, end) |
618 | 0 | } |
619 | 0 | #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] |
620 | 0 | { |
621 | 0 | crate::arch::wasm32::memchr::memrchr2_raw(needle1, needle2, start, end) |
622 | 0 | } |
623 | 0 | #[cfg(target_arch = "aarch64")] |
624 | 0 | { |
625 | 0 | crate::arch::aarch64::memchr::memrchr2_raw( |
626 | 0 | needle1, needle2, start, end, |
627 | 0 | ) |
628 | 0 | } |
629 | 0 | #[cfg(not(any( |
630 | 0 | target_arch = "x86_64", |
631 | 0 | all(target_arch = "wasm32", target_feature = "simd128"), |
632 | 0 | target_arch = "aarch64" |
633 | 0 | )))] |
634 | 0 | { |
635 | 0 | crate::arch::all::memchr::Two::new(needle1, needle2) |
636 | 0 | .rfind_raw(start, end) |
637 | 0 | } |
638 | 0 | } |
639 | | |
640 | | /// memchr3, but using raw pointers to represent the haystack. |
641 | | /// |
642 | | /// # Safety |
643 | | /// |
644 | | /// Pointers must be valid. See `Three::find_raw`. |
645 | | #[inline] |
646 | 0 | unsafe fn memchr3_raw( |
647 | 0 | needle1: u8, |
648 | 0 | needle2: u8, |
649 | 0 | needle3: u8, |
650 | 0 | start: *const u8, |
651 | 0 | end: *const u8, |
652 | 0 | ) -> Option<*const u8> { |
653 | 0 | #[cfg(target_arch = "x86_64")] |
654 | 0 | { |
655 | 0 | crate::arch::x86_64::memchr::memchr3_raw( |
656 | 0 | needle1, needle2, needle3, start, end, |
657 | 0 | ) |
658 | 0 | } |
659 | 0 | #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] |
660 | 0 | { |
661 | 0 | crate::arch::wasm32::memchr::memchr3_raw( |
662 | 0 | needle1, needle2, needle3, start, end, |
663 | 0 | ) |
664 | 0 | } |
665 | 0 | #[cfg(target_arch = "aarch64")] |
666 | 0 | { |
667 | 0 | crate::arch::aarch64::memchr::memchr3_raw( |
668 | 0 | needle1, needle2, needle3, start, end, |
669 | 0 | ) |
670 | 0 | } |
671 | 0 | #[cfg(not(any( |
672 | 0 | target_arch = "x86_64", |
673 | 0 | all(target_arch = "wasm32", target_feature = "simd128"), |
674 | 0 | target_arch = "aarch64" |
675 | 0 | )))] |
676 | 0 | { |
677 | 0 | crate::arch::all::memchr::Three::new(needle1, needle2, needle3) |
678 | 0 | .find_raw(start, end) |
679 | 0 | } |
680 | 0 | } |
681 | | |
682 | | /// memrchr3, but using raw pointers to represent the haystack. |
683 | | /// |
684 | | /// # Safety |
685 | | /// |
686 | | /// Pointers must be valid. See `Three::rfind_raw`. |
687 | | #[inline] |
688 | 0 | unsafe fn memrchr3_raw( |
689 | 0 | needle1: u8, |
690 | 0 | needle2: u8, |
691 | 0 | needle3: u8, |
692 | 0 | start: *const u8, |
693 | 0 | end: *const u8, |
694 | 0 | ) -> Option<*const u8> { |
695 | 0 | #[cfg(target_arch = "x86_64")] |
696 | 0 | { |
697 | 0 | crate::arch::x86_64::memchr::memrchr3_raw( |
698 | 0 | needle1, needle2, needle3, start, end, |
699 | 0 | ) |
700 | 0 | } |
701 | 0 | #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] |
702 | 0 | { |
703 | 0 | crate::arch::wasm32::memchr::memrchr3_raw( |
704 | 0 | needle1, needle2, needle3, start, end, |
705 | 0 | ) |
706 | 0 | } |
707 | 0 | #[cfg(target_arch = "aarch64")] |
708 | 0 | { |
709 | 0 | crate::arch::aarch64::memchr::memrchr3_raw( |
710 | 0 | needle1, needle2, needle3, start, end, |
711 | 0 | ) |
712 | 0 | } |
713 | 0 | #[cfg(not(any( |
714 | 0 | target_arch = "x86_64", |
715 | 0 | all(target_arch = "wasm32", target_feature = "simd128"), |
716 | 0 | target_arch = "aarch64" |
717 | 0 | )))] |
718 | 0 | { |
719 | 0 | crate::arch::all::memchr::Three::new(needle1, needle2, needle3) |
720 | 0 | .rfind_raw(start, end) |
721 | 0 | } |
722 | 0 | } |
723 | | |
724 | | /// Count all matching bytes, but using raw pointers to represent the haystack. |
725 | | /// |
726 | | /// # Safety |
727 | | /// |
728 | | /// Pointers must be valid. See `One::count_raw`. |
729 | | #[inline] |
730 | 0 | unsafe fn count_raw(needle: u8, start: *const u8, end: *const u8) -> usize { |
731 | 0 | #[cfg(target_arch = "x86_64")] |
732 | 0 | { |
733 | 0 | crate::arch::x86_64::memchr::count_raw(needle, start, end) |
734 | 0 | } |
735 | 0 | #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] |
736 | 0 | { |
737 | 0 | crate::arch::wasm32::memchr::count_raw(needle, start, end) |
738 | 0 | } |
739 | 0 | #[cfg(target_arch = "aarch64")] |
740 | 0 | { |
741 | 0 | crate::arch::aarch64::memchr::count_raw(needle, start, end) |
742 | 0 | } |
743 | 0 | #[cfg(not(any( |
744 | 0 | target_arch = "x86_64", |
745 | 0 | all(target_arch = "wasm32", target_feature = "simd128"), |
746 | 0 | target_arch = "aarch64" |
747 | 0 | )))] |
748 | 0 | { |
749 | 0 | crate::arch::all::memchr::One::new(needle).count_raw(start, end) |
750 | 0 | } |
751 | 0 | } |
752 | | |
753 | | #[cfg(test)] |
754 | | mod tests { |
755 | | use super::*; |
756 | | |
757 | | #[test] |
758 | | fn forward1_iter() { |
759 | | crate::tests::memchr::Runner::new(1).forward_iter( |
760 | | |haystack, needles| { |
761 | | Some(memchr_iter(needles[0], haystack).collect()) |
762 | | }, |
763 | | ) |
764 | | } |
765 | | |
766 | | #[test] |
767 | | fn forward1_oneshot() { |
768 | | crate::tests::memchr::Runner::new(1).forward_oneshot( |
769 | | |haystack, needles| Some(memchr(needles[0], haystack)), |
770 | | ) |
771 | | } |
772 | | |
773 | | #[test] |
774 | | fn reverse1_iter() { |
775 | | crate::tests::memchr::Runner::new(1).reverse_iter( |
776 | | |haystack, needles| { |
777 | | Some(memrchr_iter(needles[0], haystack).collect()) |
778 | | }, |
779 | | ) |
780 | | } |
781 | | |
782 | | #[test] |
783 | | fn reverse1_oneshot() { |
784 | | crate::tests::memchr::Runner::new(1).reverse_oneshot( |
785 | | |haystack, needles| Some(memrchr(needles[0], haystack)), |
786 | | ) |
787 | | } |
788 | | |
789 | | #[test] |
790 | | fn count1_iter() { |
791 | | crate::tests::memchr::Runner::new(1).count_iter(|haystack, needles| { |
792 | | Some(memchr_iter(needles[0], haystack).count()) |
793 | | }) |
794 | | } |
795 | | |
796 | | #[test] |
797 | | fn forward2_iter() { |
798 | | crate::tests::memchr::Runner::new(2).forward_iter( |
799 | | |haystack, needles| { |
800 | | let n1 = needles.get(0).copied()?; |
801 | | let n2 = needles.get(1).copied()?; |
802 | | Some(memchr2_iter(n1, n2, haystack).collect()) |
803 | | }, |
804 | | ) |
805 | | } |
806 | | |
807 | | #[test] |
808 | | fn forward2_oneshot() { |
809 | | crate::tests::memchr::Runner::new(2).forward_oneshot( |
810 | | |haystack, needles| { |
811 | | let n1 = needles.get(0).copied()?; |
812 | | let n2 = needles.get(1).copied()?; |
813 | | Some(memchr2(n1, n2, haystack)) |
814 | | }, |
815 | | ) |
816 | | } |
817 | | |
818 | | #[test] |
819 | | fn reverse2_iter() { |
820 | | crate::tests::memchr::Runner::new(2).reverse_iter( |
821 | | |haystack, needles| { |
822 | | let n1 = needles.get(0).copied()?; |
823 | | let n2 = needles.get(1).copied()?; |
824 | | Some(memrchr2_iter(n1, n2, haystack).collect()) |
825 | | }, |
826 | | ) |
827 | | } |
828 | | |
829 | | #[test] |
830 | | fn reverse2_oneshot() { |
831 | | crate::tests::memchr::Runner::new(2).reverse_oneshot( |
832 | | |haystack, needles| { |
833 | | let n1 = needles.get(0).copied()?; |
834 | | let n2 = needles.get(1).copied()?; |
835 | | Some(memrchr2(n1, n2, haystack)) |
836 | | }, |
837 | | ) |
838 | | } |
839 | | |
840 | | #[test] |
841 | | fn forward3_iter() { |
842 | | crate::tests::memchr::Runner::new(3).forward_iter( |
843 | | |haystack, needles| { |
844 | | let n1 = needles.get(0).copied()?; |
845 | | let n2 = needles.get(1).copied()?; |
846 | | let n3 = needles.get(2).copied()?; |
847 | | Some(memchr3_iter(n1, n2, n3, haystack).collect()) |
848 | | }, |
849 | | ) |
850 | | } |
851 | | |
852 | | #[test] |
853 | | fn forward3_oneshot() { |
854 | | crate::tests::memchr::Runner::new(3).forward_oneshot( |
855 | | |haystack, needles| { |
856 | | let n1 = needles.get(0).copied()?; |
857 | | let n2 = needles.get(1).copied()?; |
858 | | let n3 = needles.get(2).copied()?; |
859 | | Some(memchr3(n1, n2, n3, haystack)) |
860 | | }, |
861 | | ) |
862 | | } |
863 | | |
864 | | #[test] |
865 | | fn reverse3_iter() { |
866 | | crate::tests::memchr::Runner::new(3).reverse_iter( |
867 | | |haystack, needles| { |
868 | | let n1 = needles.get(0).copied()?; |
869 | | let n2 = needles.get(1).copied()?; |
870 | | let n3 = needles.get(2).copied()?; |
871 | | Some(memrchr3_iter(n1, n2, n3, haystack).collect()) |
872 | | }, |
873 | | ) |
874 | | } |
875 | | |
876 | | #[test] |
877 | | fn reverse3_oneshot() { |
878 | | crate::tests::memchr::Runner::new(3).reverse_oneshot( |
879 | | |haystack, needles| { |
880 | | let n1 = needles.get(0).copied()?; |
881 | | let n2 = needles.get(1).copied()?; |
882 | | let n3 = needles.get(2).copied()?; |
883 | | Some(memrchr3(n1, n2, n3, haystack)) |
884 | | }, |
885 | | ) |
886 | | } |
887 | | |
888 | | // Prior to memchr 2.6, the memchr iterators both implemented Send and |
889 | | // Sync. But in memchr 2.6, the iterator changed to use raw pointers |
890 | | // internally and I didn't add explicit Send/Sync impls. This ended up |
891 | | // regressing the API. This test ensures we don't do that again. |
892 | | // |
893 | | // See: https://github.com/BurntSushi/memchr/issues/133 |
894 | | #[test] |
895 | | fn sync_regression() { |
896 | | use core::panic::{RefUnwindSafe, UnwindSafe}; |
897 | | |
898 | | fn assert_send_sync<T: Send + Sync + UnwindSafe + RefUnwindSafe>() {} |
899 | | assert_send_sync::<Memchr>(); |
900 | | assert_send_sync::<Memchr2>(); |
901 | | assert_send_sync::<Memchr3>() |
902 | | } |
903 | | } |