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]
memchr(needle: u8, haystack: &[u8]) -> Option<usize>27 pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
28 // SAFETY: memchr_raw, when a match is found, always returns a valid
29 // pointer between start and end.
30 unsafe {
31 generic::search_slice_with_raw(haystack, |start, end| {
32 memchr_raw(needle, start, end)
33 })
34 }
35 }
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]
memrchr(needle: u8, haystack: &[u8]) -> Option<usize>59 pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
60 // SAFETY: memrchr_raw, when a match is found, always returns a valid
61 // pointer between start and end.
62 unsafe {
63 generic::search_slice_with_raw(haystack, |start, end| {
64 memrchr_raw(needle, start, end)
65 })
66 }
67 }
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]
memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize>92 pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
93 // SAFETY: memchr2_raw, when a match is found, always returns a valid
94 // pointer between start and end.
95 unsafe {
96 generic::search_slice_with_raw(haystack, |start, end| {
97 memchr2_raw(needle1, needle2, start, end)
98 })
99 }
100 }
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]
memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize>125 pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
126 // SAFETY: memrchr2_raw, when a match is found, always returns a valid
127 // pointer between start and end.
128 unsafe {
129 generic::search_slice_with_raw(haystack, |start, end| {
130 memrchr2_raw(needle1, needle2, start, end)
131 })
132 }
133 }
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]
memchr3( needle1: u8, needle2: u8, needle3: u8, haystack: &[u8], ) -> Option<usize>158 pub fn memchr3(
159 needle1: u8,
160 needle2: u8,
161 needle3: u8,
162 haystack: &[u8],
163 ) -> Option<usize> {
164 // SAFETY: memchr3_raw, when a match is found, always returns a valid
165 // pointer between start and end.
166 unsafe {
167 generic::search_slice_with_raw(haystack, |start, end| {
168 memchr3_raw(needle1, needle2, needle3, start, end)
169 })
170 }
171 }
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]
memrchr3( needle1: u8, needle2: u8, needle3: u8, haystack: &[u8], ) -> Option<usize>196 pub fn memrchr3(
197 needle1: u8,
198 needle2: u8,
199 needle3: u8,
200 haystack: &[u8],
201 ) -> Option<usize> {
202 // SAFETY: memrchr3_raw, when a match is found, always returns a valid
203 // pointer between start and end.
204 unsafe {
205 generic::search_slice_with_raw(haystack, |start, end| {
206 memrchr3_raw(needle1, needle2, needle3, start, end)
207 })
208 }
209 }
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]
memchr_iter<'h>(needle: u8, haystack: &'h [u8]) -> Memchr<'h>216 pub fn memchr_iter<'h>(needle: u8, haystack: &'h [u8]) -> Memchr<'h> {
217 Memchr::new(needle, haystack)
218 }
219
220 /// Returns an iterator over all occurrences of the needle in a haystack, in
221 /// reverse.
222 #[inline]
memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>>223 pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>> {
224 Memchr::new(needle, haystack).rev()
225 }
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]
memchr2_iter<'h>( needle1: u8, needle2: u8, haystack: &'h [u8], ) -> Memchr2<'h>232 pub fn memchr2_iter<'h>(
233 needle1: u8,
234 needle2: u8,
235 haystack: &'h [u8],
236 ) -> Memchr2<'h> {
237 Memchr2::new(needle1, needle2, haystack)
238 }
239
240 /// Returns an iterator over all occurrences of the needles in a haystack, in
241 /// reverse.
242 #[inline]
memrchr2_iter( needle1: u8, needle2: u8, haystack: &[u8], ) -> Rev<Memchr2<'_>>243 pub fn memrchr2_iter(
244 needle1: u8,
245 needle2: u8,
246 haystack: &[u8],
247 ) -> Rev<Memchr2<'_>> {
248 Memchr2::new(needle1, needle2, haystack).rev()
249 }
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]
memchr3_iter<'h>( needle1: u8, needle2: u8, needle3: u8, haystack: &'h [u8], ) -> Memchr3<'h>256 pub fn memchr3_iter<'h>(
257 needle1: u8,
258 needle2: u8,
259 needle3: u8,
260 haystack: &'h [u8],
261 ) -> Memchr3<'h> {
262 Memchr3::new(needle1, needle2, needle3, haystack)
263 }
264
265 /// Returns an iterator over all occurrences of the needles in a haystack, in
266 /// reverse.
267 #[inline]
memrchr3_iter( needle1: u8, needle2: u8, needle3: u8, haystack: &[u8], ) -> Rev<Memchr3<'_>>268 pub fn memrchr3_iter(
269 needle1: u8,
270 needle2: u8,
271 needle3: u8,
272 haystack: &[u8],
273 ) -> Rev<Memchr3<'_>> {
274 Memchr3::new(needle1, needle2, needle3, haystack).rev()
275 }
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]
new(needle1: u8, haystack: &'h [u8]) -> Memchr<'h>300 pub fn new(needle1: u8, haystack: &'h [u8]) -> Memchr<'h> {
301 Memchr {
302 needle1,
303 it: crate::arch::generic::memchr::Iter::new(haystack),
304 }
305 }
306 }
307
308 impl<'h> Iterator for Memchr<'h> {
309 type Item = usize;
310
311 #[inline]
next(&mut self) -> Option<usize>312 fn next(&mut self) -> Option<usize> {
313 // SAFETY: All of our implementations of memchr ensure that any
314 // pointers returns will fall within the start and end bounds, and this
315 // upholds the safety contract of `self.it.next`.
316 unsafe {
317 // NOTE: I attempted to define an enum of previously created
318 // searchers and then switch on those here instead of just
319 // calling `memchr_raw` (or `One::new(..).find_raw(..)`). But
320 // that turned out to have a fair bit of extra overhead when
321 // searching very small haystacks.
322 self.it.next(|s, e| memchr_raw(self.needle1, s, e))
323 }
324 }
325
326 #[inline]
count(self) -> usize327 fn count(self) -> usize {
328 self.it.count(|s, e| {
329 // SAFETY: We rely on our generic iterator to return valid start
330 // and end pointers.
331 unsafe { count_raw(self.needle1, s, e) }
332 })
333 }
334
335 #[inline]
size_hint(&self) -> (usize, Option<usize>)336 fn size_hint(&self) -> (usize, Option<usize>) {
337 self.it.size_hint()
338 }
339 }
340
341 impl<'h> DoubleEndedIterator for Memchr<'h> {
342 #[inline]
next_back(&mut self) -> Option<usize>343 fn next_back(&mut self) -> Option<usize> {
344 // SAFETY: All of our implementations of memchr ensure that any
345 // pointers returns will fall within the start and end bounds, and this
346 // upholds the safety contract of `self.it.next_back`.
347 unsafe { self.it.next_back(|s, e| memrchr_raw(self.needle1, s, e)) }
348 }
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]
new(needle1: u8, needle2: u8, haystack: &'h [u8]) -> Memchr2<'h>377 pub fn new(needle1: u8, needle2: u8, haystack: &'h [u8]) -> Memchr2<'h> {
378 Memchr2 {
379 needle1,
380 needle2,
381 it: crate::arch::generic::memchr::Iter::new(haystack),
382 }
383 }
384 }
385
386 impl<'h> Iterator for Memchr2<'h> {
387 type Item = usize;
388
389 #[inline]
next(&mut self) -> Option<usize>390 fn next(&mut self) -> Option<usize> {
391 // SAFETY: All of our implementations of memchr ensure that any
392 // pointers returns will fall within the start and end bounds, and this
393 // upholds the safety contract of `self.it.next`.
394 unsafe {
395 self.it.next(|s, e| memchr2_raw(self.needle1, self.needle2, s, e))
396 }
397 }
398
399 #[inline]
size_hint(&self) -> (usize, Option<usize>)400 fn size_hint(&self) -> (usize, Option<usize>) {
401 self.it.size_hint()
402 }
403 }
404
405 impl<'h> DoubleEndedIterator for Memchr2<'h> {
406 #[inline]
next_back(&mut self) -> Option<usize>407 fn next_back(&mut self) -> Option<usize> {
408 // SAFETY: All of our implementations of memchr ensure that any
409 // pointers returns will fall within the start and end bounds, and this
410 // upholds the safety contract of `self.it.next_back`.
411 unsafe {
412 self.it.next_back(|s, e| {
413 memrchr2_raw(self.needle1, self.needle2, s, e)
414 })
415 }
416 }
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]
new( needle1: u8, needle2: u8, needle3: u8, haystack: &'h [u8], ) -> Memchr3<'h>446 pub fn new(
447 needle1: u8,
448 needle2: u8,
449 needle3: u8,
450 haystack: &'h [u8],
451 ) -> Memchr3<'h> {
452 Memchr3 {
453 needle1,
454 needle2,
455 needle3,
456 it: crate::arch::generic::memchr::Iter::new(haystack),
457 }
458 }
459 }
460
461 impl<'h> Iterator for Memchr3<'h> {
462 type Item = usize;
463
464 #[inline]
next(&mut self) -> Option<usize>465 fn next(&mut self) -> Option<usize> {
466 // SAFETY: All of our implementations of memchr ensure that any
467 // pointers returns will fall within the start and end bounds, and this
468 // upholds the safety contract of `self.it.next`.
469 unsafe {
470 self.it.next(|s, e| {
471 memchr3_raw(self.needle1, self.needle2, self.needle3, s, e)
472 })
473 }
474 }
475
476 #[inline]
size_hint(&self) -> (usize, Option<usize>)477 fn size_hint(&self) -> (usize, Option<usize>) {
478 self.it.size_hint()
479 }
480 }
481
482 impl<'h> DoubleEndedIterator for Memchr3<'h> {
483 #[inline]
next_back(&mut self) -> Option<usize>484 fn next_back(&mut self) -> Option<usize> {
485 // SAFETY: All of our implementations of memchr ensure that any
486 // pointers returns will fall within the start and end bounds, and this
487 // upholds the safety contract of `self.it.next_back`.
488 unsafe {
489 self.it.next_back(|s, e| {
490 memrchr3_raw(self.needle1, self.needle2, self.needle3, s, e)
491 })
492 }
493 }
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]
memchr_raw( needle: u8, start: *const u8, end: *const u8, ) -> Option<*const u8>504 unsafe fn memchr_raw(
505 needle: u8,
506 start: *const u8,
507 end: *const u8,
508 ) -> Option<*const u8> {
509 #[cfg(target_arch = "x86_64")]
510 {
511 // x86_64 does CPU feature detection at runtime in order to use AVX2
512 // instructions even when the `avx2` feature isn't enabled at compile
513 // time. This function also handles using a fallback if neither AVX2
514 // nor SSE2 (unusual) are available.
515 crate::arch::x86_64::memchr::memchr_raw(needle, start, end)
516 }
517 #[cfg(target_arch = "wasm32")]
518 {
519 crate::arch::wasm32::memchr::memchr_raw(needle, start, end)
520 }
521 #[cfg(target_arch = "aarch64")]
522 {
523 crate::arch::aarch64::memchr::memchr_raw(needle, start, end)
524 }
525 #[cfg(not(any(
526 target_arch = "x86_64",
527 target_arch = "wasm32",
528 target_arch = "aarch64"
529 )))]
530 {
531 crate::arch::all::memchr::One::new(needle).find_raw(start, end)
532 }
533 }
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]
memrchr_raw( needle: u8, start: *const u8, end: *const u8, ) -> Option<*const u8>541 unsafe fn memrchr_raw(
542 needle: u8,
543 start: *const u8,
544 end: *const u8,
545 ) -> Option<*const u8> {
546 #[cfg(target_arch = "x86_64")]
547 {
548 crate::arch::x86_64::memchr::memrchr_raw(needle, start, end)
549 }
550 #[cfg(target_arch = "wasm32")]
551 {
552 crate::arch::wasm32::memchr::memrchr_raw(needle, start, end)
553 }
554 #[cfg(target_arch = "aarch64")]
555 {
556 crate::arch::aarch64::memchr::memrchr_raw(needle, start, end)
557 }
558 #[cfg(not(any(
559 target_arch = "x86_64",
560 target_arch = "wasm32",
561 target_arch = "aarch64"
562 )))]
563 {
564 crate::arch::all::memchr::One::new(needle).rfind_raw(start, end)
565 }
566 }
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]
memchr2_raw( needle1: u8, needle2: u8, start: *const u8, end: *const u8, ) -> Option<*const u8>574 unsafe fn memchr2_raw(
575 needle1: u8,
576 needle2: u8,
577 start: *const u8,
578 end: *const u8,
579 ) -> Option<*const u8> {
580 #[cfg(target_arch = "x86_64")]
581 {
582 crate::arch::x86_64::memchr::memchr2_raw(needle1, needle2, start, end)
583 }
584 #[cfg(target_arch = "wasm32")]
585 {
586 crate::arch::wasm32::memchr::memchr2_raw(needle1, needle2, start, end)
587 }
588 #[cfg(target_arch = "aarch64")]
589 {
590 crate::arch::aarch64::memchr::memchr2_raw(needle1, needle2, start, end)
591 }
592 #[cfg(not(any(
593 target_arch = "x86_64",
594 target_arch = "wasm32",
595 target_arch = "aarch64"
596 )))]
597 {
598 crate::arch::all::memchr::Two::new(needle1, needle2)
599 .find_raw(start, end)
600 }
601 }
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]
memrchr2_raw( needle1: u8, needle2: u8, start: *const u8, end: *const u8, ) -> Option<*const u8>609 unsafe fn memrchr2_raw(
610 needle1: u8,
611 needle2: u8,
612 start: *const u8,
613 end: *const u8,
614 ) -> Option<*const u8> {
615 #[cfg(target_arch = "x86_64")]
616 {
617 crate::arch::x86_64::memchr::memrchr2_raw(needle1, needle2, start, end)
618 }
619 #[cfg(target_arch = "wasm32")]
620 {
621 crate::arch::wasm32::memchr::memrchr2_raw(needle1, needle2, start, end)
622 }
623 #[cfg(target_arch = "aarch64")]
624 {
625 crate::arch::aarch64::memchr::memrchr2_raw(
626 needle1, needle2, start, end,
627 )
628 }
629 #[cfg(not(any(
630 target_arch = "x86_64",
631 target_arch = "wasm32",
632 target_arch = "aarch64"
633 )))]
634 {
635 crate::arch::all::memchr::Two::new(needle1, needle2)
636 .rfind_raw(start, end)
637 }
638 }
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]
memchr3_raw( needle1: u8, needle2: u8, needle3: u8, start: *const u8, end: *const u8, ) -> Option<*const u8>646 unsafe fn memchr3_raw(
647 needle1: u8,
648 needle2: u8,
649 needle3: u8,
650 start: *const u8,
651 end: *const u8,
652 ) -> Option<*const u8> {
653 #[cfg(target_arch = "x86_64")]
654 {
655 crate::arch::x86_64::memchr::memchr3_raw(
656 needle1, needle2, needle3, start, end,
657 )
658 }
659 #[cfg(target_arch = "wasm32")]
660 {
661 crate::arch::wasm32::memchr::memchr3_raw(
662 needle1, needle2, needle3, start, end,
663 )
664 }
665 #[cfg(target_arch = "aarch64")]
666 {
667 crate::arch::aarch64::memchr::memchr3_raw(
668 needle1, needle2, needle3, start, end,
669 )
670 }
671 #[cfg(not(any(
672 target_arch = "x86_64",
673 target_arch = "wasm32",
674 target_arch = "aarch64"
675 )))]
676 {
677 crate::arch::all::memchr::Three::new(needle1, needle2, needle3)
678 .find_raw(start, end)
679 }
680 }
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]
memrchr3_raw( needle1: u8, needle2: u8, needle3: u8, start: *const u8, end: *const u8, ) -> Option<*const u8>688 unsafe fn memrchr3_raw(
689 needle1: u8,
690 needle2: u8,
691 needle3: u8,
692 start: *const u8,
693 end: *const u8,
694 ) -> Option<*const u8> {
695 #[cfg(target_arch = "x86_64")]
696 {
697 crate::arch::x86_64::memchr::memrchr3_raw(
698 needle1, needle2, needle3, start, end,
699 )
700 }
701 #[cfg(target_arch = "wasm32")]
702 {
703 crate::arch::wasm32::memchr::memrchr3_raw(
704 needle1, needle2, needle3, start, end,
705 )
706 }
707 #[cfg(target_arch = "aarch64")]
708 {
709 crate::arch::aarch64::memchr::memrchr3_raw(
710 needle1, needle2, needle3, start, end,
711 )
712 }
713 #[cfg(not(any(
714 target_arch = "x86_64",
715 target_arch = "wasm32",
716 target_arch = "aarch64"
717 )))]
718 {
719 crate::arch::all::memchr::Three::new(needle1, needle2, needle3)
720 .rfind_raw(start, end)
721 }
722 }
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]
count_raw(needle: u8, start: *const u8, end: *const u8) -> usize730 unsafe fn count_raw(needle: u8, start: *const u8, end: *const u8) -> usize {
731 #[cfg(target_arch = "x86_64")]
732 {
733 crate::arch::x86_64::memchr::count_raw(needle, start, end)
734 }
735 #[cfg(target_arch = "wasm32")]
736 {
737 crate::arch::wasm32::memchr::count_raw(needle, start, end)
738 }
739 #[cfg(target_arch = "aarch64")]
740 {
741 crate::arch::aarch64::memchr::count_raw(needle, start, end)
742 }
743 #[cfg(not(any(
744 target_arch = "x86_64",
745 target_arch = "wasm32",
746 target_arch = "aarch64"
747 )))]
748 {
749 crate::arch::all::memchr::One::new(needle).count_raw(start, end)
750 }
751 }
752
753 #[cfg(test)]
754 mod tests {
755 use super::*;
756
757 #[test]
forward1_iter()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]
forward1_oneshot()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]
reverse1_iter()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]
reverse1_oneshot()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]
count1_iter()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]
forward2_iter()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]
forward2_oneshot()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]
reverse2_iter()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]
reverse2_oneshot()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]
forward3_iter()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]
forward3_oneshot()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]
reverse3_iter()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]
reverse3_oneshot()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]
sync_regression()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 }
904