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")))]
memchr(needle: u8, haystack: &[u8]) -> Option<usize>7 pub(crate) fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
8     haystack.iter().position(|val| needle == *val)
9 }
10 
11 #[cfg(all(unix, feature = "libc"))]
memchr(needle: u8, haystack: &[u8]) -> Option<usize>12 pub(crate) fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
13     let start = haystack.as_ptr();
14 
15     // SAFETY: `start` is valid for `haystack.len()` bytes.
16     let ptr = unsafe { libc::memchr(start.cast(), needle as _, 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)]
26 mod tests {
27     use super::memchr;
28 
29     #[test]
memchr_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]
memchr_all()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]
memchr_empty()69     fn memchr_empty() {
70         for b in 0..=255 {
71             assert_eq!(memchr(b, b""), None);
72         }
73     }
74 }
75