1//! Search for a byte in a byte array using libc.
2//!
3//! When nothing pulls in libc, then just use a trivial implementation. Note
4//! that we only depend on libc on unix.
5
6#[cfg(not(all(unix, feature = "libc")))]
7pub(crate) fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
8 haystack.iter().position(|val| needle == *val)
9}
10
11#[cfg(all(unix, feature = "libc"))]
12pub(crate) fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
13 let start: *const u8 = haystack.as_ptr();
14
15 // SAFETY: `start` is valid for `haystack.len()` bytes.
16 let ptr: *mut c_void = unsafe { libc::memchr(cx:start.cast(), c:needle as _, n:haystack.len()) };
17
18 if ptr.is_null() {
19 None
20 } else {
21 Some(ptr as usize - start as usize)
22 }
23}
24
25#[cfg(test)]
26mod tests {
27 use super::memchr;
28
29 #[test]
30 fn memchr_test() {
31 let haystack = b"123abc456\0\xffabc\n";
32
33 assert_eq!(memchr(b'1', haystack), Some(0));
34 assert_eq!(memchr(b'2', haystack), Some(1));
35 assert_eq!(memchr(b'3', haystack), Some(2));
36 assert_eq!(memchr(b'4', haystack), Some(6));
37 assert_eq!(memchr(b'5', haystack), Some(7));
38 assert_eq!(memchr(b'6', haystack), Some(8));
39 assert_eq!(memchr(b'7', haystack), None);
40 assert_eq!(memchr(b'a', haystack), Some(3));
41 assert_eq!(memchr(b'b', haystack), Some(4));
42 assert_eq!(memchr(b'c', haystack), Some(5));
43 assert_eq!(memchr(b'd', haystack), None);
44 assert_eq!(memchr(b'A', haystack), None);
45 assert_eq!(memchr(0, haystack), Some(9));
46 assert_eq!(memchr(0xff, haystack), Some(10));
47 assert_eq!(memchr(0xfe, haystack), None);
48 assert_eq!(memchr(1, haystack), None);
49 assert_eq!(memchr(b'\n', haystack), Some(14));
50 assert_eq!(memchr(b'\r', haystack), None);
51 }
52
53 #[test]
54 fn memchr_all() {
55 let mut arr = Vec::new();
56 for b in 0..=255 {
57 arr.push(b);
58 }
59 for b in 0..=255 {
60 assert_eq!(memchr(b, &arr), Some(b as usize));
61 }
62 arr.reverse();
63 for b in 0..=255 {
64 assert_eq!(memchr(b, &arr), Some(255 - b as usize));
65 }
66 }
67
68 #[test]
69 fn memchr_empty() {
70 for b in 0..=255 {
71 assert_eq!(memchr(b, b""), None);
72 }
73 }
74}
75