1 | // Original implementation taken from rust-memchr. |
2 | // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch |
3 | |
4 | pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> { |
5 | let p = unsafe { |
6 | libc::memchr( |
7 | haystack.as_ptr() as *const libc::c_void, |
8 | needle as libc::c_int, |
9 | haystack.len(), |
10 | ) |
11 | }; |
12 | if p.is_null() { None } else { Some(p.addr() - haystack.as_ptr().addr()) } |
13 | } |
14 | |
15 | pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> { |
16 | #[cfg (target_os = "linux" )] |
17 | fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> { |
18 | // GNU's memrchr() will - unlike memchr() - error if haystack is empty. |
19 | if haystack.is_empty() { |
20 | return None; |
21 | } |
22 | let p = unsafe { |
23 | libc::memrchr( |
24 | haystack.as_ptr() as *const libc::c_void, |
25 | needle as libc::c_int, |
26 | haystack.len(), |
27 | ) |
28 | }; |
29 | // FIXME: this should *likely* use `offset_from`, but more |
30 | // investigation is needed (including running tests in miri). |
31 | if p.is_null() { None } else { Some(p.addr() - haystack.as_ptr().addr()) } |
32 | } |
33 | |
34 | #[cfg (not(target_os = "linux" ))] |
35 | fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> { |
36 | core::slice::memchr::memrchr(needle, haystack) |
37 | } |
38 | |
39 | memrchr_specific(needle, haystack) |
40 | } |
41 | |