| 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 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)] |
| 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 | |