use core::iter::Rev;
use crate::arch::generic::memchr as generic;
#[inline]
pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memchr_raw(needle, start, end)
})
}
}
#[inline]
pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memrchr_raw(needle, start, end)
})
}
}
#[inline]
pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memchr2_raw(needle1, needle2, start, end)
})
}
}
#[inline]
pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memrchr2_raw(needle1, needle2, start, end)
})
}
}
#[inline]
pub fn memchr3(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &[u8],
) -> Option<usize> {
unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memchr3_raw(needle1, needle2, needle3, start, end)
})
}
}
#[inline]
pub fn memrchr3(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &[u8],
) -> Option<usize> {
unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memrchr3_raw(needle1, needle2, needle3, start, end)
})
}
}
#[inline]
pub fn memchr_iter<'h>(needle: u8, haystack: &'h [u8]) -> Memchr<'h> {
Memchr::new(needle, haystack)
}
#[inline]
pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>> {
Memchr::new(needle, haystack).rev()
}
#[inline]
pub fn memchr2_iter<'h>(
needle1: u8,
needle2: u8,
haystack: &'h [u8],
) -> Memchr2<'h> {
Memchr2::new(needle1, needle2, haystack)
}
#[inline]
pub fn memrchr2_iter(
needle1: u8,
needle2: u8,
haystack: &[u8],
) -> Rev<Memchr2<'_>> {
Memchr2::new(needle1, needle2, haystack).rev()
}
#[inline]
pub fn memchr3_iter<'h>(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &'h [u8],
) -> Memchr3<'h> {
Memchr3::new(needle1, needle2, needle3, haystack)
}
#[inline]
pub fn memrchr3_iter(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &[u8],
) -> Rev<Memchr3<'_>> {
Memchr3::new(needle1, needle2, needle3, haystack).rev()
}
#[derive(Clone, Debug)]
pub struct Memchr<'h> {
needle1: u8,
it: crate::arch::generic::memchr::Iter<'h>,
}
impl<'h> Memchr<'h> {
#[inline]
pub fn new(needle1: u8, haystack: &'h [u8]) -> Memchr<'h> {
Memchr {
needle1,
it: crate::arch::generic::memchr::Iter::new(haystack),
}
}
}
impl<'h> Iterator for Memchr<'h> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
unsafe {
self.it.next(|s, e| memchr_raw(self.needle1, s, e))
}
}
#[inline]
fn count(self) -> usize {
self.it.count(|s, e| {
unsafe { count_raw(self.needle1, s, e) }
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
}
impl<'h> DoubleEndedIterator for Memchr<'h> {
#[inline]
fn next_back(&mut self) -> Option<usize> {
unsafe { self.it.next_back(|s, e| memrchr_raw(self.needle1, s, e)) }
}
}
impl<'h> core::iter::FusedIterator for Memchr<'h> {}
#[derive(Clone, Debug)]
pub struct Memchr2<'h> {
needle1: u8,
needle2: u8,
it: crate::arch::generic::memchr::Iter<'h>,
}
impl<'h> Memchr2<'h> {
#[inline]
pub fn new(needle1: u8, needle2: u8, haystack: &'h [u8]) -> Memchr2<'h> {
Memchr2 {
needle1,
needle2,
it: crate::arch::generic::memchr::Iter::new(haystack),
}
}
}
impl<'h> Iterator for Memchr2<'h> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
unsafe {
self.it.next(|s, e| memchr2_raw(self.needle1, self.needle2, s, e))
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
}
impl<'h> DoubleEndedIterator for Memchr2<'h> {
#[inline]
fn next_back(&mut self) -> Option<usize> {
unsafe {
self.it.next_back(|s, e| {
memrchr2_raw(self.needle1, self.needle2, s, e)
})
}
}
}
impl<'h> core::iter::FusedIterator for Memchr2<'h> {}
#[derive(Clone, Debug)]
pub struct Memchr3<'h> {
needle1: u8,
needle2: u8,
needle3: u8,
it: crate::arch::generic::memchr::Iter<'h>,
}
impl<'h> Memchr3<'h> {
#[inline]
pub fn new(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &'h [u8],
) -> Memchr3<'h> {
Memchr3 {
needle1,
needle2,
needle3,
it: crate::arch::generic::memchr::Iter::new(haystack),
}
}
}
impl<'h> Iterator for Memchr3<'h> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
unsafe {
self.it.next(|s, e| {
memchr3_raw(self.needle1, self.needle2, self.needle3, s, e)
})
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
}
impl<'h> DoubleEndedIterator for Memchr3<'h> {
#[inline]
fn next_back(&mut self) -> Option<usize> {
unsafe {
self.it.next_back(|s, e| {
memrchr3_raw(self.needle1, self.needle2, self.needle3, s, e)
})
}
}
}
impl<'h> core::iter::FusedIterator for Memchr3<'h> {}
#[inline]
unsafe fn memchr_raw(
needle: u8,
start: *const u8,
end: *const u8,
) -> Option<*const u8> {
#[cfg(target_arch = "x86_64")]
{
crate::arch::x86_64::memchr::memchr_raw(needle, start, end)
}
#[cfg(target_arch = "wasm32")]
{
crate::arch::wasm32::memchr::memchr_raw(needle, start, end)
}
#[cfg(target_arch = "aarch64")]
{
crate::arch::aarch64::memchr::memchr_raw(needle, start, end)
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "wasm32",
target_arch = "aarch64"
)))]
{
crate::arch::all::memchr::One::new(needle).find_raw(start, end)
}
}
#[inline]
unsafe fn memrchr_raw(
needle: u8,
start: *const u8,
end: *const u8,
) -> Option<*const u8> {
#[cfg(target_arch = "x86_64")]
{
crate::arch::x86_64::memchr::memrchr_raw(needle, start, end)
}
#[cfg(target_arch = "wasm32")]
{
crate::arch::wasm32::memchr::memrchr_raw(needle, start, end)
}
#[cfg(target_arch = "aarch64")]
{
crate::arch::aarch64::memchr::memrchr_raw(needle, start, end)
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "wasm32",
target_arch = "aarch64"
)))]
{
crate::arch::all::memchr::One::new(needle).rfind_raw(start, end)
}
}
#[inline]
unsafe fn memchr2_raw(
needle1: u8,
needle2: u8,
start: *const u8,
end: *const u8,
) -> Option<*const u8> {
#[cfg(target_arch = "x86_64")]
{
crate::arch::x86_64::memchr::memchr2_raw(needle1, needle2, start, end)
}
#[cfg(target_arch = "wasm32")]
{
crate::arch::wasm32::memchr::memchr2_raw(needle1, needle2, start, end)
}
#[cfg(target_arch = "aarch64")]
{
crate::arch::aarch64::memchr::memchr2_raw(needle1, needle2, start, end)
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "wasm32",
target_arch = "aarch64"
)))]
{
crate::arch::all::memchr::Two::new(needle1, needle2)
.find_raw(start, end)
}
}
#[inline]
unsafe fn memrchr2_raw(
needle1: u8,
needle2: u8,
start: *const u8,
end: *const u8,
) -> Option<*const u8> {
#[cfg(target_arch = "x86_64")]
{
crate::arch::x86_64::memchr::memrchr2_raw(needle1, needle2, start, end)
}
#[cfg(target_arch = "wasm32")]
{
crate::arch::wasm32::memchr::memrchr2_raw(needle1, needle2, start, end)
}
#[cfg(target_arch = "aarch64")]
{
crate::arch::aarch64::memchr::memrchr2_raw(
needle1, needle2, start, end,
)
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "wasm32",
target_arch = "aarch64"
)))]
{
crate::arch::all::memchr::Two::new(needle1, needle2)
.rfind_raw(start, end)
}
}
#[inline]
unsafe fn memchr3_raw(
needle1: u8,
needle2: u8,
needle3: u8,
start: *const u8,
end: *const u8,
) -> Option<*const u8> {
#[cfg(target_arch = "x86_64")]
{
crate::arch::x86_64::memchr::memchr3_raw(
needle1, needle2, needle3, start, end,
)
}
#[cfg(target_arch = "wasm32")]
{
crate::arch::wasm32::memchr::memchr3_raw(
needle1, needle2, needle3, start, end,
)
}
#[cfg(target_arch = "aarch64")]
{
crate::arch::aarch64::memchr::memchr3_raw(
needle1, needle2, needle3, start, end,
)
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "wasm32",
target_arch = "aarch64"
)))]
{
crate::arch::all::memchr::Three::new(needle1, needle2, needle3)
.find_raw(start, end)
}
}
#[inline]
unsafe fn memrchr3_raw(
needle1: u8,
needle2: u8,
needle3: u8,
start: *const u8,
end: *const u8,
) -> Option<*const u8> {
#[cfg(target_arch = "x86_64")]
{
crate::arch::x86_64::memchr::memrchr3_raw(
needle1, needle2, needle3, start, end,
)
}
#[cfg(target_arch = "wasm32")]
{
crate::arch::wasm32::memchr::memrchr3_raw(
needle1, needle2, needle3, start, end,
)
}
#[cfg(target_arch = "aarch64")]
{
crate::arch::aarch64::memchr::memrchr3_raw(
needle1, needle2, needle3, start, end,
)
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "wasm32",
target_arch = "aarch64"
)))]
{
crate::arch::all::memchr::Three::new(needle1, needle2, needle3)
.rfind_raw(start, end)
}
}
#[inline]
unsafe fn count_raw(needle: u8, start: *const u8, end: *const u8) -> usize {
#[cfg(target_arch = "x86_64")]
{
crate::arch::x86_64::memchr::count_raw(needle, start, end)
}
#[cfg(target_arch = "wasm32")]
{
crate::arch::wasm32::memchr::count_raw(needle, start, end)
}
#[cfg(target_arch = "aarch64")]
{
crate::arch::aarch64::memchr::count_raw(needle, start, end)
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "wasm32",
target_arch = "aarch64"
)))]
{
crate::arch::all::memchr::One::new(needle).count_raw(start, end)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn forward1_iter() {
crate::tests::memchr::Runner::new(1).forward_iter(
|haystack, needles| {
Some(memchr_iter(needles[0], haystack).collect())
},
)
}
#[test]
fn forward1_oneshot() {
crate::tests::memchr::Runner::new(1).forward_oneshot(
|haystack, needles| Some(memchr(needles[0], haystack)),
)
}
#[test]
fn reverse1_iter() {
crate::tests::memchr::Runner::new(1).reverse_iter(
|haystack, needles| {
Some(memrchr_iter(needles[0], haystack).collect())
},
)
}
#[test]
fn reverse1_oneshot() {
crate::tests::memchr::Runner::new(1).reverse_oneshot(
|haystack, needles| Some(memrchr(needles[0], haystack)),
)
}
#[test]
fn count1_iter() {
crate::tests::memchr::Runner::new(1).count_iter(|haystack, needles| {
Some(memchr_iter(needles[0], haystack).count())
})
}
#[test]
fn forward2_iter() {
crate::tests::memchr::Runner::new(2).forward_iter(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
Some(memchr2_iter(n1, n2, haystack).collect())
},
)
}
#[test]
fn forward2_oneshot() {
crate::tests::memchr::Runner::new(2).forward_oneshot(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
Some(memchr2(n1, n2, haystack))
},
)
}
#[test]
fn reverse2_iter() {
crate::tests::memchr::Runner::new(2).reverse_iter(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
Some(memrchr2_iter(n1, n2, haystack).collect())
},
)
}
#[test]
fn reverse2_oneshot() {
crate::tests::memchr::Runner::new(2).reverse_oneshot(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
Some(memrchr2(n1, n2, haystack))
},
)
}
#[test]
fn forward3_iter() {
crate::tests::memchr::Runner::new(3).forward_iter(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
let n3 = needles.get(2).copied()?;
Some(memchr3_iter(n1, n2, n3, haystack).collect())
},
)
}
#[test]
fn forward3_oneshot() {
crate::tests::memchr::Runner::new(3).forward_oneshot(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
let n3 = needles.get(2).copied()?;
Some(memchr3(n1, n2, n3, haystack))
},
)
}
#[test]
fn reverse3_iter() {
crate::tests::memchr::Runner::new(3).reverse_iter(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
let n3 = needles.get(2).copied()?;
Some(memrchr3_iter(n1, n2, n3, haystack).collect())
},
)
}
#[test]
fn reverse3_oneshot() {
crate::tests::memchr::Runner::new(3).reverse_oneshot(
|haystack, needles| {
let n1 = needles.get(0).copied()?;
let n2 = needles.get(1).copied()?;
let n3 = needles.get(2).copied()?;
Some(memrchr3(n1, n2, n3, haystack))
},
)
}
#[test]
fn sync_regression() {
use core::panic::{RefUnwindSafe, UnwindSafe};
fn assert_send_sync<T: Send + Sync + UnwindSafe + RefUnwindSafe>() {}
assert_send_sync::<Memchr>();
assert_send_sync::<Memchr2>();
assert_send_sync::<Memchr3>()
}
}