Coverage Report

Created: 2025-07-18 06:51

/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
}