|
| 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 = 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] |
| 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 | +} |
0 commit comments