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" )))] |
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" ))] |
12 | pub(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 {unknown} = 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)] |
26 | mod 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 | |