tokio/util/
memchr.rs

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