1use core::iter::Rev;
2
3pub use self::iter::{Memchr, Memchr2, Memchr3};
4
5// N.B. If you're looking for the cfg knobs for libc, see build.rs.
6#[cfg(memchr_libc)]
7mod c;
8#[allow(dead_code)]
9pub mod fallback;
10mod iter;
11pub mod naive;
12#[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))]
13mod x86;
14
15/// An iterator over all occurrences of the needle in a haystack.
16#[inline]
17pub fn memchr_iter(needle: u8, haystack: &[u8]) -> Memchr<'_> {
18 Memchr::new(needle, haystack)
19}
20
21/// An iterator over all occurrences of the needles in a haystack.
22#[inline]
23pub fn memchr2_iter(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2<'_> {
24 Memchr2::new(needle1, needle2, haystack)
25}
26
27/// An iterator over all occurrences of the needles in a haystack.
28#[inline]
29pub fn memchr3_iter(
30 needle1: u8,
31 needle2: u8,
32 needle3: u8,
33 haystack: &[u8],
34) -> Memchr3<'_> {
35 Memchr3::new(needle1, needle2, needle3, haystack)
36}
37
38/// An iterator over all occurrences of the needle in a haystack, in reverse.
39#[inline]
40pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>> {
41 Memchr::new(needle, haystack).rev()
42}
43
44/// An iterator over all occurrences of the needles in a haystack, in reverse.
45#[inline]
46pub fn memrchr2_iter(
47 needle1: u8,
48 needle2: u8,
49 haystack: &[u8],
50) -> Rev<Memchr2<'_>> {
51 Memchr2::new(needle1, needle2, haystack).rev()
52}
53
54/// An iterator over all occurrences of the needles in a haystack, in reverse.
55#[inline]
56pub fn memrchr3_iter(
57 needle1: u8,
58 needle2: u8,
59 needle3: u8,
60 haystack: &[u8],
61) -> Rev<Memchr3<'_>> {
62 Memchr3::new(needle1, needle2, needle3, haystack).rev()
63}
64
65/// Search for the first occurrence of a byte in a slice.
66///
67/// This returns the index corresponding to the first occurrence of `needle` in
68/// `haystack`, or `None` if one is not found. If an index is returned, it is
69/// guaranteed to be less than `usize::MAX`.
70///
71/// While this is operationally the same as something like
72/// `haystack.iter().position(|&b| b == needle)`, `memchr` will use a highly
73/// optimized routine that can be up to an order of magnitude faster in some
74/// cases.
75///
76/// # Example
77///
78/// This shows how to find the first position of a byte in a byte string.
79///
80/// ```
81/// use memchr::memchr;
82///
83/// let haystack = b"the quick brown fox";
84/// assert_eq!(memchr(b'k', haystack), Some(8));
85/// ```
86#[inline]
87pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
88 #[cfg(miri)]
89 #[inline(always)]
90 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
91 naive::memchr(n1, haystack)
92 }
93
94 #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))]
95 #[inline(always)]
96 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
97 x86::memchr(n1, haystack)
98 }
99
100 #[cfg(all(
101 memchr_libc,
102 not(all(target_arch = "x86_64", memchr_runtime_simd)),
103 not(miri),
104 ))]
105 #[inline(always)]
106 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
107 c::memchr(n1, haystack)
108 }
109
110 #[cfg(all(
111 not(memchr_libc),
112 not(all(target_arch = "x86_64", memchr_runtime_simd)),
113 not(miri),
114 ))]
115 #[inline(always)]
116 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
117 fallback::memchr(n1, haystack)
118 }
119
120 if haystack.is_empty() {
121 None
122 } else {
123 imp(needle, haystack)
124 }
125}
126
127/// Like `memchr`, but searches for either of two bytes instead of just one.
128///
129/// This returns the index corresponding to the first occurrence of `needle1`
130/// or the first occurrence of `needle2` in `haystack` (whichever occurs
131/// earlier), or `None` if neither one is found. If an index is returned, it is
132/// guaranteed to be less than `usize::MAX`.
133///
134/// While this is operationally the same as something like
135/// `haystack.iter().position(|&b| b == needle1 || b == needle2)`, `memchr2`
136/// will use a highly optimized routine that can be up to an order of magnitude
137/// faster in some cases.
138///
139/// # Example
140///
141/// This shows how to find the first position of either of two bytes in a byte
142/// string.
143///
144/// ```
145/// use memchr::memchr2;
146///
147/// let haystack = b"the quick brown fox";
148/// assert_eq!(memchr2(b'k', b'q', haystack), Some(4));
149/// ```
150#[inline]
151pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
152 #[cfg(miri)]
153 #[inline(always)]
154 fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
155 naive::memchr2(n1, n2, haystack)
156 }
157
158 #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))]
159 #[inline(always)]
160 fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
161 x86::memchr2(n1, n2, haystack)
162 }
163
164 #[cfg(all(
165 not(all(target_arch = "x86_64", memchr_runtime_simd)),
166 not(miri),
167 ))]
168 #[inline(always)]
169 fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
170 fallback::memchr2(n1, n2, haystack)
171 }
172
173 if haystack.is_empty() {
174 None
175 } else {
176 imp(needle1, needle2, haystack)
177 }
178}
179
180/// Like `memchr`, but searches for any of three bytes instead of just one.
181///
182/// This returns the index corresponding to the first occurrence of `needle1`,
183/// the first occurrence of `needle2`, or the first occurrence of `needle3` in
184/// `haystack` (whichever occurs earliest), or `None` if none are found. If an
185/// index is returned, it is guaranteed to be less than `usize::MAX`.
186///
187/// While this is operationally the same as something like
188/// `haystack.iter().position(|&b| b == needle1 || b == needle2 ||
189/// b == needle3)`, `memchr3` will use a highly optimized routine that can be
190/// up to an order of magnitude faster in some cases.
191///
192/// # Example
193///
194/// This shows how to find the first position of any of three bytes in a byte
195/// string.
196///
197/// ```
198/// use memchr::memchr3;
199///
200/// let haystack = b"the quick brown fox";
201/// assert_eq!(memchr3(b'k', b'q', b'e', haystack), Some(2));
202/// ```
203#[inline]
204pub fn memchr3(
205 needle1: u8,
206 needle2: u8,
207 needle3: u8,
208 haystack: &[u8],
209) -> Option<usize> {
210 #[cfg(miri)]
211 #[inline(always)]
212 fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
213 naive::memchr3(n1, n2, n3, haystack)
214 }
215
216 #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))]
217 #[inline(always)]
218 fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
219 x86::memchr3(n1, n2, n3, haystack)
220 }
221
222 #[cfg(all(
223 not(all(target_arch = "x86_64", memchr_runtime_simd)),
224 not(miri),
225 ))]
226 #[inline(always)]
227 fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
228 fallback::memchr3(n1, n2, n3, haystack)
229 }
230
231 if haystack.is_empty() {
232 None
233 } else {
234 imp(needle1, needle2, needle3, haystack)
235 }
236}
237
238/// Search for the last occurrence of a byte in a slice.
239///
240/// This returns the index corresponding to the last occurrence of `needle` in
241/// `haystack`, or `None` if one is not found. If an index is returned, it is
242/// guaranteed to be less than `usize::MAX`.
243///
244/// While this is operationally the same as something like
245/// `haystack.iter().rposition(|&b| b == needle)`, `memrchr` will use a highly
246/// optimized routine that can be up to an order of magnitude faster in some
247/// cases.
248///
249/// # Example
250///
251/// This shows how to find the last position of a byte in a byte string.
252///
253/// ```
254/// use memchr::memrchr;
255///
256/// let haystack = b"the quick brown fox";
257/// assert_eq!(memrchr(b'o', haystack), Some(17));
258/// ```
259#[inline]
260pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
261 #[cfg(miri)]
262 #[inline(always)]
263 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
264 naive::memrchr(n1, haystack)
265 }
266
267 #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))]
268 #[inline(always)]
269 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
270 x86::memrchr(n1, haystack)
271 }
272
273 #[cfg(all(
274 memchr_libc,
275 target_os = "linux",
276 not(all(target_arch = "x86_64", memchr_runtime_simd)),
277 not(miri)
278 ))]
279 #[inline(always)]
280 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
281 c::memrchr(n1, haystack)
282 }
283
284 #[cfg(all(
285 not(all(memchr_libc, target_os = "linux")),
286 not(all(target_arch = "x86_64", memchr_runtime_simd)),
287 not(miri),
288 ))]
289 #[inline(always)]
290 fn imp(n1: u8, haystack: &[u8]) -> Option<usize> {
291 fallback::memrchr(n1, haystack)
292 }
293
294 if haystack.is_empty() {
295 None
296 } else {
297 imp(needle, haystack)
298 }
299}
300
301/// Like `memrchr`, but searches for either of two bytes instead of just one.
302///
303/// This returns the index corresponding to the last occurrence of `needle1` or
304/// the last occurrence of `needle2` in `haystack` (whichever occurs later), or
305/// `None` if neither one is found. If an index is returned, it is guaranteed
306/// to be less than `usize::MAX`.
307///
308/// While this is operationally the same as something like
309/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2)`, `memrchr2`
310/// will use a highly optimized routine that can be up to an order of magnitude
311/// faster in some cases.
312///
313/// # Example
314///
315/// This shows how to find the last position of either of two bytes in a byte
316/// string.
317///
318/// ```
319/// use memchr::memrchr2;
320///
321/// let haystack = b"the quick brown fox";
322/// assert_eq!(memrchr2(b'k', b'q', haystack), Some(8));
323/// ```
324#[inline]
325pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
326 #[cfg(miri)]
327 #[inline(always)]
328 fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
329 naive::memrchr2(n1, n2, haystack)
330 }
331
332 #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))]
333 #[inline(always)]
334 fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
335 x86::memrchr2(n1, n2, haystack)
336 }
337
338 #[cfg(all(
339 not(all(target_arch = "x86_64", memchr_runtime_simd)),
340 not(miri),
341 ))]
342 #[inline(always)]
343 fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
344 fallback::memrchr2(n1, n2, haystack)
345 }
346
347 if haystack.is_empty() {
348 None
349 } else {
350 imp(needle1, needle2, haystack)
351 }
352}
353
354/// Like `memrchr`, but searches for any of three bytes instead of just one.
355///
356/// This returns the index corresponding to the last occurrence of `needle1`,
357/// the last occurrence of `needle2`, or the last occurrence of `needle3` in
358/// `haystack` (whichever occurs later), or `None` if none are found. If an
359/// index is returned, it is guaranteed to be less than `usize::MAX`.
360///
361/// While this is operationally the same as something like
362/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2 ||
363/// b == needle3)`, `memrchr3` will use a highly optimized routine that can be
364/// up to an order of magnitude faster in some cases.
365///
366/// # Example
367///
368/// This shows how to find the last position of any of three bytes in a byte
369/// string.
370///
371/// ```
372/// use memchr::memrchr3;
373///
374/// let haystack = b"the quick brown fox";
375/// assert_eq!(memrchr3(b'k', b'q', b'e', haystack), Some(8));
376/// ```
377#[inline]
378pub fn memrchr3(
379 needle1: u8,
380 needle2: u8,
381 needle3: u8,
382 haystack: &[u8],
383) -> Option<usize> {
384 #[cfg(miri)]
385 #[inline(always)]
386 fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
387 naive::memrchr3(n1, n2, n3, haystack)
388 }
389
390 #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))]
391 #[inline(always)]
392 fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
393 x86::memrchr3(n1, n2, n3, haystack)
394 }
395
396 #[cfg(all(
397 not(all(target_arch = "x86_64", memchr_runtime_simd)),
398 not(miri),
399 ))]
400 #[inline(always)]
401 fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
402 fallback::memrchr3(n1, n2, n3, haystack)
403 }
404
405 if haystack.is_empty() {
406 None
407 } else {
408 imp(needle1, needle2, needle3, haystack)
409 }
410}
411