aboutsummaryrefslogtreecommitdiff
path: root/vendor/memchr/src
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/memchr/src
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/memchr/src')
-rw-r--r--vendor/memchr/src/arch/aarch64/memchr.rs137
-rw-r--r--vendor/memchr/src/arch/aarch64/mod.rs7
-rw-r--r--vendor/memchr/src/arch/aarch64/neon/memchr.rs1031
-rw-r--r--vendor/memchr/src/arch/aarch64/neon/mod.rs6
-rw-r--r--vendor/memchr/src/arch/aarch64/neon/packedpair.rs236
-rw-r--r--vendor/memchr/src/arch/all/memchr.rs996
-rw-r--r--vendor/memchr/src/arch/all/mod.rs234
-rw-r--r--vendor/memchr/src/arch/all/packedpair/default_rank.rs258
-rw-r--r--vendor/memchr/src/arch/all/packedpair/mod.rs359
-rw-r--r--vendor/memchr/src/arch/all/rabinkarp.rs390
-rw-r--r--vendor/memchr/src/arch/all/shiftor.rs89
-rw-r--r--vendor/memchr/src/arch/all/twoway.rs877
-rw-r--r--vendor/memchr/src/arch/generic/memchr.rs1214
-rw-r--r--vendor/memchr/src/arch/generic/mod.rs14
-rw-r--r--vendor/memchr/src/arch/generic/packedpair.rs317
-rw-r--r--vendor/memchr/src/arch/mod.rs16
-rw-r--r--vendor/memchr/src/arch/wasm32/memchr.rs137
-rw-r--r--vendor/memchr/src/arch/wasm32/mod.rs7
-rw-r--r--vendor/memchr/src/arch/wasm32/simd128/memchr.rs1020
-rw-r--r--vendor/memchr/src/arch/wasm32/simd128/mod.rs6
-rw-r--r--vendor/memchr/src/arch/wasm32/simd128/packedpair.rs229
-rw-r--r--vendor/memchr/src/arch/x86_64/avx2/memchr.rs1352
-rw-r--r--vendor/memchr/src/arch/x86_64/avx2/mod.rs6
-rw-r--r--vendor/memchr/src/arch/x86_64/avx2/packedpair.rs272
-rw-r--r--vendor/memchr/src/arch/x86_64/memchr.rs335
-rw-r--r--vendor/memchr/src/arch/x86_64/mod.rs8
-rw-r--r--vendor/memchr/src/arch/x86_64/sse2/memchr.rs1077
-rw-r--r--vendor/memchr/src/arch/x86_64/sse2/mod.rs6
-rw-r--r--vendor/memchr/src/arch/x86_64/sse2/packedpair.rs232
-rw-r--r--vendor/memchr/src/cow.rs107
-rw-r--r--vendor/memchr/src/ext.rs52
-rw-r--r--vendor/memchr/src/lib.rs221
-rw-r--r--vendor/memchr/src/macros.rs20
-rw-r--r--vendor/memchr/src/memchr.rs903
-rw-r--r--vendor/memchr/src/memmem/mod.rs737
-rw-r--r--vendor/memchr/src/memmem/searcher.rs1030
-rw-r--r--vendor/memchr/src/tests/memchr/mod.rs307
-rw-r--r--vendor/memchr/src/tests/memchr/naive.rs33
-rw-r--r--vendor/memchr/src/tests/memchr/prop.rs321
-rw-r--r--vendor/memchr/src/tests/mod.rs15
-rw-r--r--vendor/memchr/src/tests/packedpair.rs216
-rw-r--r--vendor/memchr/src/tests/substring/mod.rs232
-rw-r--r--vendor/memchr/src/tests/substring/naive.rs45
-rw-r--r--vendor/memchr/src/tests/substring/prop.rs126
-rw-r--r--vendor/memchr/src/tests/x86_64-soft_float.json15
-rw-r--r--vendor/memchr/src/vector.rs515
46 files changed, 0 insertions, 15763 deletions
diff --git a/vendor/memchr/src/arch/aarch64/memchr.rs b/vendor/memchr/src/arch/aarch64/memchr.rs
deleted file mode 100644
index e0053b2..0000000
--- a/vendor/memchr/src/arch/aarch64/memchr.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-/*!
-Wrapper routines for `memchr` and friends.
-
-These routines choose the best implementation at compile time. (This is
-different from `x86_64` because it is expected that `neon` is almost always
-available for `aarch64` targets.)
-*/
-
-macro_rules! defraw {
- ($ty:ident, $find:ident, $start:ident, $end:ident, $($needles:ident),+) => {{
- #[cfg(target_feature = "neon")]
- {
- use crate::arch::aarch64::neon::memchr::$ty;
-
- debug!("chose neon for {}", stringify!($ty));
- debug_assert!($ty::is_available());
- // SAFETY: We know that wasm memchr is always available whenever
- // code is compiled for `aarch64` with the `neon` target feature
- // enabled.
- $ty::new_unchecked($($needles),+).$find($start, $end)
- }
- #[cfg(not(target_feature = "neon"))]
- {
- use crate::arch::all::memchr::$ty;
-
- debug!(
- "no neon feature available, using fallback for {}",
- stringify!($ty),
- );
- $ty::new($($needles),+).$find($start, $end)
- }
- }}
-}
-
-/// memchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::find_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memchr_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(One, find_raw, start, end, n1)
-}
-
-/// memrchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::rfind_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memrchr_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(One, rfind_raw, start, end, n1)
-}
-
-/// memchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::find_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memchr2_raw(
- n1: u8,
- n2: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Two, find_raw, start, end, n1, n2)
-}
-
-/// memrchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::rfind_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memrchr2_raw(
- n1: u8,
- n2: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Two, rfind_raw, start, end, n1, n2)
-}
-
-/// memchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::find_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memchr3_raw(
- n1: u8,
- n2: u8,
- n3: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Three, find_raw, start, end, n1, n2, n3)
-}
-
-/// memrchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::rfind_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memrchr3_raw(
- n1: u8,
- n2: u8,
- n3: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Three, rfind_raw, start, end, n1, n2, n3)
-}
-
-/// Count all matching bytes, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::count_raw`.
-#[inline(always)]
-pub(crate) unsafe fn count_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> usize {
- defraw!(One, count_raw, start, end, n1)
-}
diff --git a/vendor/memchr/src/arch/aarch64/mod.rs b/vendor/memchr/src/arch/aarch64/mod.rs
deleted file mode 100644
index 7b32912..0000000
--- a/vendor/memchr/src/arch/aarch64/mod.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
-Vector algorithms for the `aarch64` target.
-*/
-
-pub mod neon;
-
-pub(crate) mod memchr;
diff --git a/vendor/memchr/src/arch/aarch64/neon/memchr.rs b/vendor/memchr/src/arch/aarch64/neon/memchr.rs
deleted file mode 100644
index 5fcc762..0000000
--- a/vendor/memchr/src/arch/aarch64/neon/memchr.rs
+++ /dev/null
@@ -1,1031 +0,0 @@
-/*!
-This module defines 128-bit vector implementations of `memchr` and friends.
-
-The main types in this module are [`One`], [`Two`] and [`Three`]. They are for
-searching for one, two or three distinct bytes, respectively, in a haystack.
-Each type also has corresponding double ended iterators. These searchers are
-typically much faster than scalar routines accomplishing the same task.
-
-The `One` searcher also provides a [`One::count`] routine for efficiently
-counting the number of times a single byte occurs in a haystack. This is
-useful, for example, for counting the number of lines in a haystack. This
-routine exists because it is usually faster, especially with a high match
-count, then using [`One::find`] repeatedly. ([`OneIter`] specializes its
-`Iterator::count` implementation to use this routine.)
-
-Only one, two and three bytes are supported because three bytes is about
-the point where one sees diminishing returns. Beyond this point and it's
-probably (but not necessarily) better to just use a simple `[bool; 256]` array
-or similar. However, it depends mightily on the specific work-load and the
-expected match frequency.
-*/
-
-use core::arch::aarch64::uint8x16_t;
-
-use crate::{arch::generic::memchr as generic, ext::Pointer, vector::Vector};
-
-/// Finds all occurrences of a single byte in a haystack.
-#[derive(Clone, Copy, Debug)]
-pub struct One(generic::One<uint8x16_t>);
-
-impl One {
- /// Create a new searcher that finds occurrences of the needle byte given.
- ///
- /// This particular searcher is specialized to use neon vector instructions
- /// that typically make it quite fast.
- ///
- /// If neon is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle: u8) -> Option<One> {
- if One::is_available() {
- // SAFETY: we check that neon is available above.
- unsafe { Some(One::new_unchecked(needle)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to neon vectors and routines without
- /// checking that neon is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `neon` instructions
- /// in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to neon
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "neon")]
- #[inline]
- pub unsafe fn new_unchecked(needle: u8) -> One {
- One(generic::One::new(needle))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`One::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `One::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "neon")]
- {
- true
- }
- #[cfg(not(target_feature = "neon"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Counts all occurrences of this byte in the given haystack.
- #[inline]
- pub fn count(&self, haystack: &[u8]) -> usize {
- // SAFETY: All of our pointers are derived directly from a borrowed
- // slice, which is guaranteed to be valid.
- unsafe {
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- self.count_raw(start, end)
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < uint8x16_t::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'neon' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < uint8x16_t::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'neon' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.rfind_raw_impl(start, end)
- }
-
- /// Like `count`, but accepts and returns raw pointers.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn count_raw(&self, start: *const u8, end: *const u8) -> usize {
- if start >= end {
- return 0;
- }
- if end.distance(start) < uint8x16_t::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::count_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'neon' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.count_raw_impl(start, end)
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of a neon vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of a neon vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Execute a count using neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::count_raw`], except the distance between `start` and
- /// `end` must be at least the size of a neon vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn count_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> usize {
- self.0.count_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> OneIter<'a, 'h> {
- OneIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of a single byte in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`One::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`One`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct OneIter<'a, 'h> {
- searcher: &'a One,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for OneIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn count(self) -> usize {
- self.it.count(|s, e| {
- // SAFETY: We rely on our generic iterator to return valid start
- // and end pointers.
- unsafe { self.searcher.count_raw(s, e) }
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for OneIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for OneIter<'a, 'h> {}
-
-/// Finds all occurrences of two bytes in a haystack.
-///
-/// That is, this reports matches of one of two possible bytes. For example,
-/// searching for `a` or `b` in `afoobar` would report matches at offsets `0`,
-/// `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Two(generic::Two<uint8x16_t>);
-
-impl Two {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use neon vector instructions
- /// that typically make it quite fast.
- ///
- /// If neon is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8) -> Option<Two> {
- if Two::is_available() {
- // SAFETY: we check that neon is available above.
- unsafe { Some(Two::new_unchecked(needle1, needle2)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to neon vectors and routines without
- /// checking that neon is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `neon` instructions
- /// in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to neon
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "neon")]
- #[inline]
- pub unsafe fn new_unchecked(needle1: u8, needle2: u8) -> Two {
- Two(generic::Two::new(needle1, needle2))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Two::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Two::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "neon")]
- {
- true
- }
- #[cfg(not(target_feature = "neon"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < uint8x16_t::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1() || b == self.0.needle2()
- });
- }
- // SAFETY: Building a `Two` means it's safe to call 'neon' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < uint8x16_t::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1() || b == self.0.needle2()
- });
- }
- // SAFETY: Building a `Two` means it's safe to call 'neon' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.rfind_raw_impl(start, end)
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of a neon vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of a neon vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle bytes in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> TwoIter<'a, 'h> {
- TwoIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of two possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Two::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Two`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct TwoIter<'a, 'h> {
- searcher: &'a Two,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for TwoIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for TwoIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for TwoIter<'a, 'h> {}
-
-/// Finds all occurrences of three bytes in a haystack.
-///
-/// That is, this reports matches of one of three possible bytes. For example,
-/// searching for `a`, `b` or `o` in `afoobar` would report matches at offsets
-/// `0`, `2`, `3`, `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Three(generic::Three<uint8x16_t>);
-
-impl Three {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use neon vector instructions
- /// that typically make it quite fast.
- ///
- /// If neon is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8, needle3: u8) -> Option<Three> {
- if Three::is_available() {
- // SAFETY: we check that neon is available above.
- unsafe { Some(Three::new_unchecked(needle1, needle2, needle3)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to neon vectors and routines without
- /// checking that neon is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `neon` instructions
- /// in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to neon
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "neon")]
- #[inline]
- pub unsafe fn new_unchecked(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- ) -> Three {
- Three(generic::Three::new(needle1, needle2, needle3))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Three::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Three::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "neon")]
- {
- true
- }
- #[cfg(not(target_feature = "neon"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < uint8x16_t::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- || b == self.0.needle2()
- || b == self.0.needle3()
- });
- }
- // SAFETY: Building a `Three` means it's safe to call 'neon' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < uint8x16_t::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- || b == self.0.needle2()
- || b == self.0.needle3()
- });
- }
- // SAFETY: Building a `Three` means it's safe to call 'neon' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.rfind_raw_impl(start, end)
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of a neon vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of a neon vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> ThreeIter<'a, 'h> {
- ThreeIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of three possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Three::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Three`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct ThreeIter<'a, 'h> {
- searcher: &'a Three,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for ThreeIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for ThreeIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for ThreeIter<'a, 'h> {}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_memchr_quickcheck!(super);
-
- #[test]
- fn forward_one() {
- crate::tests::memchr::Runner::new(1).forward_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_one() {
- crate::tests::memchr::Runner::new(1).reverse_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn count_one() {
- crate::tests::memchr::Runner::new(1).count_iter(|haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).count())
- })
- }
-
- #[test]
- fn forward_two() {
- crate::tests::memchr::Runner::new(2).forward_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_two() {
- crate::tests::memchr::Runner::new(2).reverse_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn forward_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).rev().collect())
- },
- )
- }
-}
diff --git a/vendor/memchr/src/arch/aarch64/neon/mod.rs b/vendor/memchr/src/arch/aarch64/neon/mod.rs
deleted file mode 100644
index ccf9cf8..0000000
--- a/vendor/memchr/src/arch/aarch64/neon/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
-Algorithms for the `aarch64` target using 128-bit vectors via NEON.
-*/
-
-pub mod memchr;
-pub mod packedpair;
diff --git a/vendor/memchr/src/arch/aarch64/neon/packedpair.rs b/vendor/memchr/src/arch/aarch64/neon/packedpair.rs
deleted file mode 100644
index 6884882..0000000
--- a/vendor/memchr/src/arch/aarch64/neon/packedpair.rs
+++ /dev/null
@@ -1,236 +0,0 @@
-/*!
-A 128-bit vector implementation of the "packed pair" SIMD algorithm.
-
-The "packed pair" algorithm is based on the [generic SIMD] algorithm. The main
-difference is that it (by default) uses a background distribution of byte
-frequencies to heuristically select the pair of bytes to search for.
-
-[generic SIMD]: http://0x80.pl/articles/simd-strfind.html#first-and-last
-*/
-
-use core::arch::aarch64::uint8x16_t;
-
-use crate::arch::{all::packedpair::Pair, generic::packedpair};
-
-/// A "packed pair" finder that uses 128-bit vector operations.
-///
-/// This finder picks two bytes that it believes have high predictive power
-/// for indicating an overall match of a needle. Depending on whether
-/// `Finder::find` or `Finder::find_prefilter` is used, it reports offsets
-/// where the needle matches or could match. In the prefilter case, candidates
-/// are reported whenever the [`Pair`] of bytes given matches.
-#[derive(Clone, Copy, Debug)]
-pub struct Finder(packedpair::Finder<uint8x16_t>);
-
-/// A "packed pair" finder that uses 128-bit vector operations.
-///
-/// This finder picks two bytes that it believes have high predictive power
-/// for indicating an overall match of a needle. Depending on whether
-/// `Finder::find` or `Finder::find_prefilter` is used, it reports offsets
-/// where the needle matches or could match. In the prefilter case, candidates
-/// are reported whenever the [`Pair`] of bytes given matches.
-impl Finder {
- /// Create a new pair searcher. The searcher returned can either report
- /// exact matches of `needle` or act as a prefilter and report candidate
- /// positions of `needle`.
- ///
- /// If neon is unavailable in the current environment or if a [`Pair`]
- /// could not be constructed from the needle given, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle: &[u8]) -> Option<Finder> {
- Finder::with_pair(needle, Pair::new(needle)?)
- }
-
- /// Create a new "packed pair" finder using the pair of bytes given.
- ///
- /// This constructor permits callers to control precisely which pair of
- /// bytes is used as a predicate.
- ///
- /// If neon is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn with_pair(needle: &[u8], pair: Pair) -> Option<Finder> {
- if Finder::is_available() {
- // SAFETY: we check that sse2 is available above. We are also
- // guaranteed to have needle.len() > 1 because we have a valid
- // Pair.
- unsafe { Some(Finder::with_pair_impl(needle, pair)) }
- } else {
- None
- }
- }
-
- /// Create a new `Finder` specific to neon vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as the safety for `packedpair::Finder::new`, and callers must also
- /// ensure that neon is available.
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn with_pair_impl(needle: &[u8], pair: Pair) -> Finder {
- let finder = packedpair::Finder::<uint8x16_t>::new(needle, pair);
- Finder(finder)
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Finder::with_pair`] will
- /// return a `Some` value. Similarly, when it is false, it is guaranteed
- /// that `Finder::with_pair` will return a `None` value. Notice that this
- /// does not guarantee that [`Finder::new`] will return a `Finder`. Namely,
- /// even when `Finder::is_available` is true, it is not guaranteed that a
- /// valid [`Pair`] can be found from the needle given.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "neon")]
- {
- true
- }
- #[cfg(not(target_feature = "neon"))]
- {
- false
- }
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- // SAFETY: Building a `Finder` means it's safe to call 'neon' routines.
- unsafe { self.find_impl(haystack, needle) }
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find_prefilter(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: Building a `Finder` means it's safe to call 'neon' routines.
- unsafe { self.find_prefilter_impl(haystack) }
- }
-
- /// Execute a search using neon vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn find_impl(
- &self,
- haystack: &[u8],
- needle: &[u8],
- ) -> Option<usize> {
- self.0.find(haystack, needle)
- }
-
- /// Execute a prefilter search using neon vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `neon` routines.)
- #[target_feature(enable = "neon")]
- #[inline]
- unsafe fn find_prefilter_impl(&self, haystack: &[u8]) -> Option<usize> {
- self.0.find_prefilter(haystack)
- }
-
- /// Returns the pair of offsets (into the needle) used to check as a
- /// predicate before confirming whether a needle exists at a particular
- /// position.
- #[inline]
- pub fn pair(&self) -> &Pair {
- self.0.pair()
- }
-
- /// Returns the minimum haystack length that this `Finder` can search.
- ///
- /// Using a haystack with length smaller than this in a search will result
- /// in a panic. The reason for this restriction is that this finder is
- /// meant to be a low-level component that is part of a larger substring
- /// strategy. In that sense, it avoids trying to handle all cases and
- /// instead only handles the cases that it can handle very well.
- #[inline]
- pub fn min_haystack_len(&self) -> usize {
- self.0.min_haystack_len()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- fn find(haystack: &[u8], needle: &[u8]) -> Option<Option<usize>> {
- let f = Finder::new(needle)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
-
- define_substring_forward_quickcheck!(find);
-
- #[test]
- fn forward_substring() {
- crate::tests::substring::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair_prefilter() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find_prefilter(haystack))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-}
diff --git a/vendor/memchr/src/arch/all/memchr.rs b/vendor/memchr/src/arch/all/memchr.rs
deleted file mode 100644
index 435b1be..0000000
--- a/vendor/memchr/src/arch/all/memchr.rs
+++ /dev/null
@@ -1,996 +0,0 @@
-/*!
-Provides architecture independent implementations of `memchr` and friends.
-
-The main types in this module are [`One`], [`Two`] and [`Three`]. They are for
-searching for one, two or three distinct bytes, respectively, in a haystack.
-Each type also has corresponding double ended iterators. These searchers
-are typically slower than hand-coded vector routines accomplishing the same
-task, but are also typically faster than naive scalar code. These routines
-effectively work by treating a `usize` as a vector of 8-bit lanes, and thus
-achieves some level of data parallelism even without explicit vector support.
-
-The `One` searcher also provides a [`One::count`] routine for efficiently
-counting the number of times a single byte occurs in a haystack. This is
-useful, for example, for counting the number of lines in a haystack. This
-routine exists because it is usually faster, especially with a high match
-count, then using [`One::find`] repeatedly. ([`OneIter`] specializes its
-`Iterator::count` implementation to use this routine.)
-
-Only one, two and three bytes are supported because three bytes is about
-the point where one sees diminishing returns. Beyond this point and it's
-probably (but not necessarily) better to just use a simple `[bool; 256]` array
-or similar. However, it depends mightily on the specific work-load and the
-expected match frequency.
-*/
-
-use crate::{arch::generic::memchr as generic, ext::Pointer};
-
-/// The number of bytes in a single `usize` value.
-const USIZE_BYTES: usize = (usize::BITS / 8) as usize;
-/// The bits that must be zero for a `*const usize` to be properly aligned.
-const USIZE_ALIGN: usize = USIZE_BYTES - 1;
-
-/// Finds all occurrences of a single byte in a haystack.
-#[derive(Clone, Copy, Debug)]
-pub struct One {
- s1: u8,
- v1: usize,
-}
-
-impl One {
- /// The number of bytes we examine per each iteration of our search loop.
- const LOOP_BYTES: usize = 2 * USIZE_BYTES;
-
- /// Create a new searcher that finds occurrences of the byte given.
- #[inline]
- pub fn new(needle: u8) -> One {
- One { s1: needle, v1: splat(needle) }
- }
-
- /// A test-only routine so that we can bundle a bunch of quickcheck
- /// properties into a single macro. Basically, this provides a constructor
- /// that makes it identical to most other memchr implementations, which
- /// have fallible constructors.
- #[cfg(test)]
- pub(crate) fn try_new(needle: u8) -> Option<One> {
- Some(One::new(needle))
- }
-
- /// Return the first occurrence of the needle in the given haystack. If no
- /// such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value for a non-empty haystack is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of the needle in the given haystack. If no
- /// such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value for a non-empty haystack is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Counts all occurrences of this byte in the given haystack.
- #[inline]
- pub fn count(&self, haystack: &[u8]) -> usize {
- // SAFETY: All of our pointers are derived directly from a borrowed
- // slice, which is guaranteed to be valid.
- unsafe {
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- self.count_raw(start, end)
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let confirm = |b| self.confirm(b);
- let len = end.distance(start);
- if len < USIZE_BYTES {
- return generic::fwd_byte_by_byte(start, end, confirm);
- }
-
- // The start of the search may not be aligned to `*const usize`,
- // so we do an unaligned load here.
- let chunk = start.cast::<usize>().read_unaligned();
- if self.has_needle(chunk) {
- return generic::fwd_byte_by_byte(start, end, confirm);
- }
-
- // And now we start our search at a guaranteed aligned position.
- // The first iteration of the loop below will overlap with the the
- // unaligned chunk above in cases where the search starts at an
- // unaligned offset, but that's okay as we're only here if that
- // above didn't find a match.
- let mut cur =
- start.add(USIZE_BYTES - (start.as_usize() & USIZE_ALIGN));
- debug_assert!(cur > start);
- if len <= One::LOOP_BYTES {
- return generic::fwd_byte_by_byte(cur, end, confirm);
- }
- debug_assert!(end.sub(One::LOOP_BYTES) >= start);
- while cur <= end.sub(One::LOOP_BYTES) {
- debug_assert_eq!(0, cur.as_usize() % USIZE_BYTES);
-
- let a = cur.cast::<usize>().read();
- let b = cur.add(USIZE_BYTES).cast::<usize>().read();
- if self.has_needle(a) || self.has_needle(b) {
- break;
- }
- cur = cur.add(One::LOOP_BYTES);
- }
- generic::fwd_byte_by_byte(cur, end, confirm)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let confirm = |b| self.confirm(b);
- let len = end.distance(start);
- if len < USIZE_BYTES {
- return generic::rev_byte_by_byte(start, end, confirm);
- }
-
- let chunk = end.sub(USIZE_BYTES).cast::<usize>().read_unaligned();
- if self.has_needle(chunk) {
- return generic::rev_byte_by_byte(start, end, confirm);
- }
-
- let mut cur = end.sub(end.as_usize() & USIZE_ALIGN);
- debug_assert!(start <= cur && cur <= end);
- if len <= One::LOOP_BYTES {
- return generic::rev_byte_by_byte(start, cur, confirm);
- }
- while cur >= start.add(One::LOOP_BYTES) {
- debug_assert_eq!(0, cur.as_usize() % USIZE_BYTES);
-
- let a = cur.sub(2 * USIZE_BYTES).cast::<usize>().read();
- let b = cur.sub(1 * USIZE_BYTES).cast::<usize>().read();
- if self.has_needle(a) || self.has_needle(b) {
- break;
- }
- cur = cur.sub(One::LOOP_BYTES);
- }
- generic::rev_byte_by_byte(start, cur, confirm)
- }
-
- /// Counts all occurrences of this byte in the given haystack represented
- /// by raw pointers.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `0` will always be returned.
- #[inline]
- pub unsafe fn count_raw(&self, start: *const u8, end: *const u8) -> usize {
- if start >= end {
- return 0;
- }
- // Sadly I couldn't get the SWAR approach to work here, so we just do
- // one byte at a time for now. PRs to improve this are welcome.
- let mut ptr = start;
- let mut count = 0;
- while ptr < end {
- count += (ptr.read() == self.s1) as usize;
- ptr = ptr.offset(1);
- }
- count
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> OneIter<'a, 'h> {
- OneIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-
- #[inline(always)]
- fn has_needle(&self, chunk: usize) -> bool {
- has_zero_byte(self.v1 ^ chunk)
- }
-
- #[inline(always)]
- fn confirm(&self, haystack_byte: u8) -> bool {
- self.s1 == haystack_byte
- }
-}
-
-/// An iterator over all occurrences of a single byte in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`One::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`One`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct OneIter<'a, 'h> {
- /// The underlying memchr searcher.
- searcher: &'a One,
- /// Generic iterator implementation.
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for OneIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn count(self) -> usize {
- self.it.count(|s, e| {
- // SAFETY: We rely on our generic iterator to return valid start
- // and end pointers.
- unsafe { self.searcher.count_raw(s, e) }
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for OneIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-/// Finds all occurrences of two bytes in a haystack.
-///
-/// That is, this reports matches of one of two possible bytes. For example,
-/// searching for `a` or `b` in `afoobar` would report matches at offsets `0`,
-/// `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Two {
- s1: u8,
- s2: u8,
- v1: usize,
- v2: usize,
-}
-
-impl Two {
- /// Create a new searcher that finds occurrences of the two needle bytes
- /// given.
- #[inline]
- pub fn new(needle1: u8, needle2: u8) -> Two {
- Two {
- s1: needle1,
- s2: needle2,
- v1: splat(needle1),
- v2: splat(needle2),
- }
- }
-
- /// A test-only routine so that we can bundle a bunch of quickcheck
- /// properties into a single macro. Basically, this provides a constructor
- /// that makes it identical to most other memchr implementations, which
- /// have fallible constructors.
- #[cfg(test)]
- pub(crate) fn try_new(needle1: u8, needle2: u8) -> Option<Two> {
- Some(Two::new(needle1, needle2))
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value for a non-empty haystack is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value for a non-empty haystack is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let confirm = |b| self.confirm(b);
- let len = end.distance(start);
- if len < USIZE_BYTES {
- return generic::fwd_byte_by_byte(start, end, confirm);
- }
-
- // The start of the search may not be aligned to `*const usize`,
- // so we do an unaligned load here.
- let chunk = start.cast::<usize>().read_unaligned();
- if self.has_needle(chunk) {
- return generic::fwd_byte_by_byte(start, end, confirm);
- }
-
- // And now we start our search at a guaranteed aligned position.
- // The first iteration of the loop below will overlap with the the
- // unaligned chunk above in cases where the search starts at an
- // unaligned offset, but that's okay as we're only here if that
- // above didn't find a match.
- let mut cur =
- start.add(USIZE_BYTES - (start.as_usize() & USIZE_ALIGN));
- debug_assert!(cur > start);
- debug_assert!(end.sub(USIZE_BYTES) >= start);
- while cur <= end.sub(USIZE_BYTES) {
- debug_assert_eq!(0, cur.as_usize() % USIZE_BYTES);
-
- let chunk = cur.cast::<usize>().read();
- if self.has_needle(chunk) {
- break;
- }
- cur = cur.add(USIZE_BYTES);
- }
- generic::fwd_byte_by_byte(cur, end, confirm)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let confirm = |b| self.confirm(b);
- let len = end.distance(start);
- if len < USIZE_BYTES {
- return generic::rev_byte_by_byte(start, end, confirm);
- }
-
- let chunk = end.sub(USIZE_BYTES).cast::<usize>().read_unaligned();
- if self.has_needle(chunk) {
- return generic::rev_byte_by_byte(start, end, confirm);
- }
-
- let mut cur = end.sub(end.as_usize() & USIZE_ALIGN);
- debug_assert!(start <= cur && cur <= end);
- while cur >= start.add(USIZE_BYTES) {
- debug_assert_eq!(0, cur.as_usize() % USIZE_BYTES);
-
- let chunk = cur.sub(USIZE_BYTES).cast::<usize>().read();
- if self.has_needle(chunk) {
- break;
- }
- cur = cur.sub(USIZE_BYTES);
- }
- generic::rev_byte_by_byte(start, cur, confirm)
- }
-
- /// Returns an iterator over all occurrences of one of the needle bytes in
- /// the given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> TwoIter<'a, 'h> {
- TwoIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-
- #[inline(always)]
- fn has_needle(&self, chunk: usize) -> bool {
- has_zero_byte(self.v1 ^ chunk) || has_zero_byte(self.v2 ^ chunk)
- }
-
- #[inline(always)]
- fn confirm(&self, haystack_byte: u8) -> bool {
- self.s1 == haystack_byte || self.s2 == haystack_byte
- }
-}
-
-/// An iterator over all occurrences of two possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Two::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Two`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct TwoIter<'a, 'h> {
- /// The underlying memchr searcher.
- searcher: &'a Two,
- /// Generic iterator implementation.
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for TwoIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for TwoIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-/// Finds all occurrences of three bytes in a haystack.
-///
-/// That is, this reports matches of one of three possible bytes. For example,
-/// searching for `a`, `b` or `o` in `afoobar` would report matches at offsets
-/// `0`, `2`, `3`, `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Three {
- s1: u8,
- s2: u8,
- s3: u8,
- v1: usize,
- v2: usize,
- v3: usize,
-}
-
-impl Three {
- /// Create a new searcher that finds occurrences of the three needle bytes
- /// given.
- #[inline]
- pub fn new(needle1: u8, needle2: u8, needle3: u8) -> Three {
- Three {
- s1: needle1,
- s2: needle2,
- s3: needle3,
- v1: splat(needle1),
- v2: splat(needle2),
- v3: splat(needle3),
- }
- }
-
- /// A test-only routine so that we can bundle a bunch of quickcheck
- /// properties into a single macro. Basically, this provides a constructor
- /// that makes it identical to most other memchr implementations, which
- /// have fallible constructors.
- #[cfg(test)]
- pub(crate) fn try_new(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- ) -> Option<Three> {
- Some(Three::new(needle1, needle2, needle3))
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value for a non-empty haystack is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value for a non-empty haystack is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let confirm = |b| self.confirm(b);
- let len = end.distance(start);
- if len < USIZE_BYTES {
- return generic::fwd_byte_by_byte(start, end, confirm);
- }
-
- // The start of the search may not be aligned to `*const usize`,
- // so we do an unaligned load here.
- let chunk = start.cast::<usize>().read_unaligned();
- if self.has_needle(chunk) {
- return generic::fwd_byte_by_byte(start, end, confirm);
- }
-
- // And now we start our search at a guaranteed aligned position.
- // The first iteration of the loop below will overlap with the the
- // unaligned chunk above in cases where the search starts at an
- // unaligned offset, but that's okay as we're only here if that
- // above didn't find a match.
- let mut cur =
- start.add(USIZE_BYTES - (start.as_usize() & USIZE_ALIGN));
- debug_assert!(cur > start);
- debug_assert!(end.sub(USIZE_BYTES) >= start);
- while cur <= end.sub(USIZE_BYTES) {
- debug_assert_eq!(0, cur.as_usize() % USIZE_BYTES);
-
- let chunk = cur.cast::<usize>().read();
- if self.has_needle(chunk) {
- break;
- }
- cur = cur.add(USIZE_BYTES);
- }
- generic::fwd_byte_by_byte(cur, end, confirm)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let confirm = |b| self.confirm(b);
- let len = end.distance(start);
- if len < USIZE_BYTES {
- return generic::rev_byte_by_byte(start, end, confirm);
- }
-
- let chunk = end.sub(USIZE_BYTES).cast::<usize>().read_unaligned();
- if self.has_needle(chunk) {
- return generic::rev_byte_by_byte(start, end, confirm);
- }
-
- let mut cur = end.sub(end.as_usize() & USIZE_ALIGN);
- debug_assert!(start <= cur && cur <= end);
- while cur >= start.add(USIZE_BYTES) {
- debug_assert_eq!(0, cur.as_usize() % USIZE_BYTES);
-
- let chunk = cur.sub(USIZE_BYTES).cast::<usize>().read();
- if self.has_needle(chunk) {
- break;
- }
- cur = cur.sub(USIZE_BYTES);
- }
- generic::rev_byte_by_byte(start, cur, confirm)
- }
-
- /// Returns an iterator over all occurrences of one of the needle bytes in
- /// the given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> ThreeIter<'a, 'h> {
- ThreeIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-
- #[inline(always)]
- fn has_needle(&self, chunk: usize) -> bool {
- has_zero_byte(self.v1 ^ chunk)
- || has_zero_byte(self.v2 ^ chunk)
- || has_zero_byte(self.v3 ^ chunk)
- }
-
- #[inline(always)]
- fn confirm(&self, haystack_byte: u8) -> bool {
- self.s1 == haystack_byte
- || self.s2 == haystack_byte
- || self.s3 == haystack_byte
- }
-}
-
-/// An iterator over all occurrences of three possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Three::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Three`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct ThreeIter<'a, 'h> {
- /// The underlying memchr searcher.
- searcher: &'a Three,
- /// Generic iterator implementation.
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for ThreeIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for ThreeIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-/// Return `true` if `x` contains any zero byte.
-///
-/// That is, this routine treats `x` as a register of 8-bit lanes and returns
-/// true when any of those lanes is `0`.
-///
-/// From "Matters Computational" by J. Arndt.
-#[inline(always)]
-fn has_zero_byte(x: usize) -> bool {
- // "The idea is to subtract one from each of the bytes and then look for
- // bytes where the borrow propagated all the way to the most significant
- // bit."
- const LO: usize = splat(0x01);
- const HI: usize = splat(0x80);
-
- (x.wrapping_sub(LO) & !x & HI) != 0
-}
-
-/// Repeat the given byte into a word size number. That is, every 8 bits
-/// is equivalent to the given byte. For example, if `b` is `\x4E` or
-/// `01001110` in binary, then the returned value on a 32-bit system would be:
-/// `01001110_01001110_01001110_01001110`.
-#[inline(always)]
-const fn splat(b: u8) -> usize {
- // TODO: use `usize::from` once it can be used in const context.
- (b as usize) * (usize::MAX / 255)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_memchr_quickcheck!(super, try_new);
-
- #[test]
- fn forward_one() {
- crate::tests::memchr::Runner::new(1).forward_iter(
- |haystack, needles| {
- Some(One::new(needles[0]).iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_one() {
- crate::tests::memchr::Runner::new(1).reverse_iter(
- |haystack, needles| {
- Some(One::new(needles[0]).iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn count_one() {
- crate::tests::memchr::Runner::new(1).count_iter(|haystack, needles| {
- Some(One::new(needles[0]).iter(haystack).count())
- })
- }
-
- #[test]
- fn forward_two() {
- crate::tests::memchr::Runner::new(2).forward_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2).iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_two() {
- crate::tests::memchr::Runner::new(2).reverse_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2).iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn forward_three() {
- 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(Three::new(n1, n2, n3).iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_three() {
- 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(Three::new(n1, n2, n3).iter(haystack).rev().collect())
- },
- )
- }
-
- // This was found by quickcheck in the course of refactoring this crate
- // after memchr 2.5.0.
- #[test]
- fn regression_double_ended_iterator() {
- let finder = One::new(b'a');
- let haystack = "a";
- let mut it = finder.iter(haystack.as_bytes());
- assert_eq!(Some(0), it.next());
- assert_eq!(None, it.next_back());
- }
-
- // This regression test was caught by ripgrep's test suite on i686 when
- // upgrading to memchr 2.6. Namely, something about the \x0B bytes here
- // screws with the SWAR counting approach I was using. This regression test
- // prompted me to remove the SWAR counting approach and just replace it
- // with a byte-at-a-time loop.
- #[test]
- fn regression_count_new_lines() {
- let haystack = "01234567\x0b\n\x0b\n\x0b\n\x0b\nx";
- let count = One::new(b'\n').count(haystack.as_bytes());
- assert_eq!(4, count);
- }
-}
diff --git a/vendor/memchr/src/arch/all/mod.rs b/vendor/memchr/src/arch/all/mod.rs
deleted file mode 100644
index 559cb75..0000000
--- a/vendor/memchr/src/arch/all/mod.rs
+++ /dev/null
@@ -1,234 +0,0 @@
-/*!
-Contains architecture independent routines.
-
-These routines are often used as a "fallback" implementation when the more
-specialized architecture dependent routines are unavailable.
-*/
-
-pub mod memchr;
-pub mod packedpair;
-pub mod rabinkarp;
-#[cfg(feature = "alloc")]
-pub mod shiftor;
-pub mod twoway;
-
-/// Returns true if and only if `needle` is a prefix of `haystack`.
-///
-/// This uses a latency optimized variant of `memcmp` internally which *might*
-/// make this faster for very short strings.
-///
-/// # Inlining
-///
-/// This routine is marked `inline(always)`. If you want to call this function
-/// in a way that is not always inlined, you'll need to wrap a call to it in
-/// another function that is marked as `inline(never)` or just `inline`.
-#[inline(always)]
-pub fn is_prefix(haystack: &[u8], needle: &[u8]) -> bool {
- needle.len() <= haystack.len()
- && is_equal(&haystack[..needle.len()], needle)
-}
-
-/// Returns true if and only if `needle` is a suffix of `haystack`.
-///
-/// This uses a latency optimized variant of `memcmp` internally which *might*
-/// make this faster for very short strings.
-///
-/// # Inlining
-///
-/// This routine is marked `inline(always)`. If you want to call this function
-/// in a way that is not always inlined, you'll need to wrap a call to it in
-/// another function that is marked as `inline(never)` or just `inline`.
-#[inline(always)]
-pub fn is_suffix(haystack: &[u8], needle: &[u8]) -> bool {
- needle.len() <= haystack.len()
- && is_equal(&haystack[haystack.len() - needle.len()..], needle)
-}
-
-/// Compare corresponding bytes in `x` and `y` for equality.
-///
-/// That is, this returns true if and only if `x.len() == y.len()` and
-/// `x[i] == y[i]` for all `0 <= i < x.len()`.
-///
-/// # Inlining
-///
-/// This routine is marked `inline(always)`. If you want to call this function
-/// in a way that is not always inlined, you'll need to wrap a call to it in
-/// another function that is marked as `inline(never)` or just `inline`.
-///
-/// # Motivation
-///
-/// Why not use slice equality instead? Well, slice equality usually results in
-/// a call out to the current platform's `libc` which might not be inlineable
-/// or have other overhead. This routine isn't guaranteed to be a win, but it
-/// might be in some cases.
-#[inline(always)]
-pub fn is_equal(x: &[u8], y: &[u8]) -> bool {
- if x.len() != y.len() {
- return false;
- }
- // SAFETY: Our pointers are derived directly from borrowed slices which
- // uphold all of our safety guarantees except for length. We account for
- // length with the check above.
- unsafe { is_equal_raw(x.as_ptr(), y.as_ptr(), x.len()) }
-}
-
-/// Compare `n` bytes at the given pointers for equality.
-///
-/// This returns true if and only if `*x.add(i) == *y.add(i)` for all
-/// `0 <= i < n`.
-///
-/// # Inlining
-///
-/// This routine is marked `inline(always)`. If you want to call this function
-/// in a way that is not always inlined, you'll need to wrap a call to it in
-/// another function that is marked as `inline(never)` or just `inline`.
-///
-/// # Motivation
-///
-/// Why not use slice equality instead? Well, slice equality usually results in
-/// a call out to the current platform's `libc` which might not be inlineable
-/// or have other overhead. This routine isn't guaranteed to be a win, but it
-/// might be in some cases.
-///
-/// # Safety
-///
-/// * Both `x` and `y` must be valid for reads of up to `n` bytes.
-/// * Both `x` and `y` must point to an initialized value.
-/// * Both `x` and `y` must each point to an allocated object and
-/// must either be in bounds or at most one byte past the end of the
-/// allocated object. `x` and `y` do not need to point to the same allocated
-/// object, but they may.
-/// * Both `x` and `y` must be _derived from_ a pointer to their respective
-/// allocated objects.
-/// * The distance between `x` and `x+n` must not overflow `isize`. Similarly
-/// for `y` and `y+n`.
-/// * The distance being in bounds must not rely on "wrapping around" the
-/// address space.
-#[inline(always)]
-pub unsafe fn is_equal_raw(
- mut x: *const u8,
- mut y: *const u8,
- mut n: usize,
-) -> bool {
- // When we have 4 or more bytes to compare, then proceed in chunks of 4 at
- // a time using unaligned loads.
- //
- // Also, why do 4 byte loads instead of, say, 8 byte loads? The reason is
- // that this particular version of memcmp is likely to be called with tiny
- // needles. That means that if we do 8 byte loads, then a higher proportion
- // of memcmp calls will use the slower variant above. With that said, this
- // is a hypothesis and is only loosely supported by benchmarks. There's
- // likely some improvement that could be made here. The main thing here
- // though is to optimize for latency, not throughput.
-
- // SAFETY: The caller is responsible for ensuring the pointers we get are
- // valid and readable for at least `n` bytes. We also do unaligned loads,
- // so there's no need to ensure we're aligned. (This is justified by this
- // routine being specifically for short strings.)
- while n >= 4 {
- let vx = x.cast::<u32>().read_unaligned();
- let vy = y.cast::<u32>().read_unaligned();
- if vx != vy {
- return false;
- }
- x = x.add(4);
- y = y.add(4);
- n -= 4;
- }
- // If we don't have enough bytes to do 4-byte at a time loads, then
- // do partial loads. Note that I used to have a byte-at-a-time
- // loop here and that turned out to be quite a bit slower for the
- // memmem/pathological/defeat-simple-vector-alphabet benchmark.
- if n >= 2 {
- let vx = x.cast::<u16>().read_unaligned();
- let vy = y.cast::<u16>().read_unaligned();
- if vx != vy {
- return false;
- }
- x = x.add(2);
- y = y.add(2);
- n -= 2;
- }
- if n > 0 {
- if x.read() != y.read() {
- return false;
- }
- }
- true
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn equals_different_lengths() {
- assert!(!is_equal(b"", b"a"));
- assert!(!is_equal(b"a", b""));
- assert!(!is_equal(b"ab", b"a"));
- assert!(!is_equal(b"a", b"ab"));
- }
-
- #[test]
- fn equals_mismatch() {
- let one_mismatch = [
- (&b"a"[..], &b"x"[..]),
- (&b"ab"[..], &b"ax"[..]),
- (&b"abc"[..], &b"abx"[..]),
- (&b"abcd"[..], &b"abcx"[..]),
- (&b"abcde"[..], &b"abcdx"[..]),
- (&b"abcdef"[..], &b"abcdex"[..]),
- (&b"abcdefg"[..], &b"abcdefx"[..]),
- (&b"abcdefgh"[..], &b"abcdefgx"[..]),
- (&b"abcdefghi"[..], &b"abcdefghx"[..]),
- (&b"abcdefghij"[..], &b"abcdefghix"[..]),
- (&b"abcdefghijk"[..], &b"abcdefghijx"[..]),
- (&b"abcdefghijkl"[..], &b"abcdefghijkx"[..]),
- (&b"abcdefghijklm"[..], &b"abcdefghijklx"[..]),
- (&b"abcdefghijklmn"[..], &b"abcdefghijklmx"[..]),
- ];
- for (x, y) in one_mismatch {
- assert_eq!(x.len(), y.len(), "lengths should match");
- assert!(!is_equal(x, y));
- assert!(!is_equal(y, x));
- }
- }
-
- #[test]
- fn equals_yes() {
- assert!(is_equal(b"", b""));
- assert!(is_equal(b"a", b"a"));
- assert!(is_equal(b"ab", b"ab"));
- assert!(is_equal(b"abc", b"abc"));
- assert!(is_equal(b"abcd", b"abcd"));
- assert!(is_equal(b"abcde", b"abcde"));
- assert!(is_equal(b"abcdef", b"abcdef"));
- assert!(is_equal(b"abcdefg", b"abcdefg"));
- assert!(is_equal(b"abcdefgh", b"abcdefgh"));
- assert!(is_equal(b"abcdefghi", b"abcdefghi"));
- }
-
- #[test]
- fn prefix() {
- assert!(is_prefix(b"", b""));
- assert!(is_prefix(b"a", b""));
- assert!(is_prefix(b"ab", b""));
- assert!(is_prefix(b"foo", b"foo"));
- assert!(is_prefix(b"foobar", b"foo"));
-
- assert!(!is_prefix(b"foo", b"fob"));
- assert!(!is_prefix(b"foobar", b"fob"));
- }
-
- #[test]
- fn suffix() {
- assert!(is_suffix(b"", b""));
- assert!(is_suffix(b"a", b""));
- assert!(is_suffix(b"ab", b""));
- assert!(is_suffix(b"foo", b"foo"));
- assert!(is_suffix(b"foobar", b"bar"));
-
- assert!(!is_suffix(b"foo", b"goo"));
- assert!(!is_suffix(b"foobar", b"gar"));
- }
-}
diff --git a/vendor/memchr/src/arch/all/packedpair/default_rank.rs b/vendor/memchr/src/arch/all/packedpair/default_rank.rs
deleted file mode 100644
index 6aa3895..0000000
--- a/vendor/memchr/src/arch/all/packedpair/default_rank.rs
+++ /dev/null
@@ -1,258 +0,0 @@
-pub(crate) const RANK: [u8; 256] = [
- 55, // '\x00'
- 52, // '\x01'
- 51, // '\x02'
- 50, // '\x03'
- 49, // '\x04'
- 48, // '\x05'
- 47, // '\x06'
- 46, // '\x07'
- 45, // '\x08'
- 103, // '\t'
- 242, // '\n'
- 66, // '\x0b'
- 67, // '\x0c'
- 229, // '\r'
- 44, // '\x0e'
- 43, // '\x0f'
- 42, // '\x10'
- 41, // '\x11'
- 40, // '\x12'
- 39, // '\x13'
- 38, // '\x14'
- 37, // '\x15'
- 36, // '\x16'
- 35, // '\x17'
- 34, // '\x18'
- 33, // '\x19'
- 56, // '\x1a'
- 32, // '\x1b'
- 31, // '\x1c'
- 30, // '\x1d'
- 29, // '\x1e'
- 28, // '\x1f'
- 255, // ' '
- 148, // '!'
- 164, // '"'
- 149, // '#'
- 136, // '$'
- 160, // '%'
- 155, // '&'
- 173, // "'"
- 221, // '('
- 222, // ')'
- 134, // '*'
- 122, // '+'
- 232, // ','
- 202, // '-'
- 215, // '.'
- 224, // '/'
- 208, // '0'
- 220, // '1'
- 204, // '2'
- 187, // '3'
- 183, // '4'
- 179, // '5'
- 177, // '6'
- 168, // '7'
- 178, // '8'
- 200, // '9'
- 226, // ':'
- 195, // ';'
- 154, // '<'
- 184, // '='
- 174, // '>'
- 126, // '?'
- 120, // '@'
- 191, // 'A'
- 157, // 'B'
- 194, // 'C'
- 170, // 'D'
- 189, // 'E'
- 162, // 'F'
- 161, // 'G'
- 150, // 'H'
- 193, // 'I'
- 142, // 'J'
- 137, // 'K'
- 171, // 'L'
- 176, // 'M'
- 185, // 'N'
- 167, // 'O'
- 186, // 'P'
- 112, // 'Q'
- 175, // 'R'
- 192, // 'S'
- 188, // 'T'
- 156, // 'U'
- 140, // 'V'
- 143, // 'W'
- 123, // 'X'
- 133, // 'Y'
- 128, // 'Z'
- 147, // '['
- 138, // '\\'
- 146, // ']'
- 114, // '^'
- 223, // '_'
- 151, // '`'
- 249, // 'a'
- 216, // 'b'
- 238, // 'c'
- 236, // 'd'
- 253, // 'e'
- 227, // 'f'
- 218, // 'g'
- 230, // 'h'
- 247, // 'i'
- 135, // 'j'
- 180, // 'k'
- 241, // 'l'
- 233, // 'm'
- 246, // 'n'
- 244, // 'o'
- 231, // 'p'
- 139, // 'q'
- 245, // 'r'
- 243, // 's'
- 251, // 't'
- 235, // 'u'
- 201, // 'v'
- 196, // 'w'
- 240, // 'x'
- 214, // 'y'
- 152, // 'z'
- 182, // '{'
- 205, // '|'
- 181, // '}'
- 127, // '~'
- 27, // '\x7f'
- 212, // '\x80'
- 211, // '\x81'
- 210, // '\x82'
- 213, // '\x83'
- 228, // '\x84'
- 197, // '\x85'
- 169, // '\x86'
- 159, // '\x87'
- 131, // '\x88'
- 172, // '\x89'
- 105, // '\x8a'
- 80, // '\x8b'
- 98, // '\x8c'
- 96, // '\x8d'
- 97, // '\x8e'
- 81, // '\x8f'
- 207, // '\x90'
- 145, // '\x91'
- 116, // '\x92'
- 115, // '\x93'
- 144, // '\x94'
- 130, // '\x95'
- 153, // '\x96'
- 121, // '\x97'
- 107, // '\x98'
- 132, // '\x99'
- 109, // '\x9a'
- 110, // '\x9b'
- 124, // '\x9c'
- 111, // '\x9d'
- 82, // '\x9e'
- 108, // '\x9f'
- 118, // '\xa0'
- 141, // '¡'
- 113, // '¢'
- 129, // '£'
- 119, // '¤'
- 125, // '¥'
- 165, // '¦'
- 117, // '§'
- 92, // '¨'
- 106, // '©'
- 83, // 'ª'
- 72, // '«'
- 99, // '¬'
- 93, // '\xad'
- 65, // '®'
- 79, // '¯'
- 166, // '°'
- 237, // '±'
- 163, // '²'
- 199, // '³'
- 190, // '´'
- 225, // 'µ'
- 209, // '¶'
- 203, // '·'
- 198, // '¸'
- 217, // '¹'
- 219, // 'º'
- 206, // '»'
- 234, // '¼'
- 248, // '½'
- 158, // '¾'
- 239, // '¿'
- 255, // 'À'
- 255, // 'Á'
- 255, // 'Â'
- 255, // 'Ã'
- 255, // 'Ä'
- 255, // 'Å'
- 255, // 'Æ'
- 255, // 'Ç'
- 255, // 'È'
- 255, // 'É'
- 255, // 'Ê'
- 255, // 'Ë'
- 255, // 'Ì'
- 255, // 'Í'
- 255, // 'Î'
- 255, // 'Ï'
- 255, // 'Ð'
- 255, // 'Ñ'
- 255, // 'Ò'
- 255, // 'Ó'
- 255, // 'Ô'
- 255, // 'Õ'
- 255, // 'Ö'
- 255, // '×'
- 255, // 'Ø'
- 255, // 'Ù'
- 255, // 'Ú'
- 255, // 'Û'
- 255, // 'Ü'
- 255, // 'Ý'
- 255, // 'Þ'
- 255, // 'ß'
- 255, // 'à'
- 255, // 'á'
- 255, // 'â'
- 255, // 'ã'
- 255, // 'ä'
- 255, // 'å'
- 255, // 'æ'
- 255, // 'ç'
- 255, // 'è'
- 255, // 'é'
- 255, // 'ê'
- 255, // 'ë'
- 255, // 'ì'
- 255, // 'í'
- 255, // 'î'
- 255, // 'ï'
- 255, // 'ð'
- 255, // 'ñ'
- 255, // 'ò'
- 255, // 'ó'
- 255, // 'ô'
- 255, // 'õ'
- 255, // 'ö'
- 255, // '÷'
- 255, // 'ø'
- 255, // 'ù'
- 255, // 'ú'
- 255, // 'û'
- 255, // 'ü'
- 255, // 'ý'
- 255, // 'þ'
- 255, // 'ÿ'
-];
diff --git a/vendor/memchr/src/arch/all/packedpair/mod.rs b/vendor/memchr/src/arch/all/packedpair/mod.rs
deleted file mode 100644
index 148a985..0000000
--- a/vendor/memchr/src/arch/all/packedpair/mod.rs
+++ /dev/null
@@ -1,359 +0,0 @@
-/*!
-Provides an architecture independent implementation of the "packed pair"
-algorithm.
-
-The "packed pair" algorithm is based on the [generic SIMD] algorithm. The main
-difference is that it (by default) uses a background distribution of byte
-frequencies to heuristically select the pair of bytes to search for. Note that
-this module provides an architecture independent version that doesn't do as
-good of a job keeping the search for candidates inside a SIMD hot path. It
-however can be good enough in many circumstances.
-
-[generic SIMD]: http://0x80.pl/articles/simd-strfind.html#first-and-last
-*/
-
-use crate::memchr;
-
-mod default_rank;
-
-/// An architecture independent "packed pair" finder.
-///
-/// This finder picks two bytes that it believes have high predictive power for
-/// indicating an overall match of a needle. At search time, it reports offsets
-/// where the needle could match based on whether the pair of bytes it chose
-/// match.
-///
-/// This is architecture independent because it utilizes `memchr` to find the
-/// occurrence of one of the bytes in the pair, and then checks whether the
-/// second byte matches. If it does, in the case of [`Finder::find_prefilter`],
-/// the location at which the needle could match is returned.
-///
-/// It is generally preferred to use architecture specific routines for a
-/// "packed pair" prefilter, but this can be a useful fallback when the
-/// architecture independent routines are unavailable.
-#[derive(Clone, Copy, Debug)]
-pub struct Finder {
- pair: Pair,
- byte1: u8,
- byte2: u8,
-}
-
-impl Finder {
- /// Create a new prefilter that reports possible locations where the given
- /// needle matches.
- #[inline]
- pub fn new(needle: &[u8]) -> Option<Finder> {
- Finder::with_pair(needle, Pair::new(needle)?)
- }
-
- /// Create a new prefilter using the pair given.
- ///
- /// If the prefilter could not be constructed, then `None` is returned.
- ///
- /// This constructor permits callers to control precisely which pair of
- /// bytes is used as a predicate.
- #[inline]
- pub fn with_pair(needle: &[u8], pair: Pair) -> Option<Finder> {
- let byte1 = needle[usize::from(pair.index1())];
- let byte2 = needle[usize::from(pair.index2())];
- // Currently this can never fail so we could just return a Finder,
- // but it's conceivable this could change.
- Some(Finder { pair, byte1, byte2 })
- }
-
- /// Run this finder on the given haystack as a prefilter.
- ///
- /// If a candidate match is found, then an offset where the needle *could*
- /// begin in the haystack is returned.
- #[inline]
- pub fn find_prefilter(&self, haystack: &[u8]) -> Option<usize> {
- let mut i = 0;
- let index1 = usize::from(self.pair.index1());
- let index2 = usize::from(self.pair.index2());
- loop {
- // Use a fast vectorized implementation to skip to the next
- // occurrence of the rarest byte (heuristically chosen) in the
- // needle.
- i += memchr(self.byte1, &haystack[i..])?;
- let found = i;
- i += 1;
-
- // If we can't align our first byte match with the haystack, then a
- // match is impossible.
- let aligned1 = match found.checked_sub(index1) {
- None => continue,
- Some(aligned1) => aligned1,
- };
-
- // Now align the second byte match with the haystack. A mismatch
- // means that a match is impossible.
- let aligned2 = match aligned1.checked_add(index2) {
- None => continue,
- Some(aligned_index2) => aligned_index2,
- };
- if haystack.get(aligned2).map_or(true, |&b| b != self.byte2) {
- continue;
- }
-
- // We've done what we can. There might be a match here.
- return Some(aligned1);
- }
- }
-
- /// Returns the pair of offsets (into the needle) used to check as a
- /// predicate before confirming whether a needle exists at a particular
- /// position.
- #[inline]
- pub fn pair(&self) -> &Pair {
- &self.pair
- }
-}
-
-/// A pair of byte offsets into a needle to use as a predicate.
-///
-/// This pair is used as a predicate to quickly filter out positions in a
-/// haystack in which a needle cannot match. In some cases, this pair can even
-/// be used in vector algorithms such that the vector algorithm only switches
-/// over to scalar code once this pair has been found.
-///
-/// A pair of offsets can be used in both substring search implementations and
-/// in prefilters. The former will report matches of a needle in a haystack
-/// where as the latter will only report possible matches of a needle.
-///
-/// The offsets are limited each to a maximum of 255 to keep memory usage low.
-/// Moreover, it's rarely advantageous to create a predicate using offsets
-/// greater than 255 anyway.
-///
-/// The only guarantee enforced on the pair of offsets is that they are not
-/// equivalent. It is not necessarily the case that `index1 < index2` for
-/// example. By convention, `index1` corresponds to the byte in the needle
-/// that is believed to be most the predictive. Note also that because of the
-/// requirement that the indices be both valid for the needle used to build
-/// the pair and not equal, it follows that a pair can only be constructed for
-/// needles with length at least 2.
-#[derive(Clone, Copy, Debug)]
-pub struct Pair {
- index1: u8,
- index2: u8,
-}
-
-impl Pair {
- /// Create a new pair of offsets from the given needle.
- ///
- /// If a pair could not be created (for example, if the needle is too
- /// short), then `None` is returned.
- ///
- /// This chooses the pair in the needle that is believed to be as
- /// predictive of an overall match of the needle as possible.
- #[inline]
- pub fn new(needle: &[u8]) -> Option<Pair> {
- Pair::with_ranker(needle, DefaultFrequencyRank)
- }
-
- /// Create a new pair of offsets from the given needle and ranker.
- ///
- /// This permits the caller to choose a background frequency distribution
- /// with which bytes are selected. The idea is to select a pair of bytes
- /// that is believed to strongly predict a match in the haystack. This
- /// usually means selecting bytes that occur rarely in a haystack.
- ///
- /// If a pair could not be created (for example, if the needle is too
- /// short), then `None` is returned.
- #[inline]
- pub fn with_ranker<R: HeuristicFrequencyRank>(
- needle: &[u8],
- ranker: R,
- ) -> Option<Pair> {
- if needle.len() <= 1 {
- return None;
- }
- // Find the rarest two bytes. We make them distinct indices by
- // construction. (The actual byte value may be the same in degenerate
- // cases, but that's OK.)
- let (mut rare1, mut index1) = (needle[0], 0);
- let (mut rare2, mut index2) = (needle[1], 1);
- if ranker.rank(rare2) < ranker.rank(rare1) {
- core::mem::swap(&mut rare1, &mut rare2);
- core::mem::swap(&mut index1, &mut index2);
- }
- let max = usize::from(core::u8::MAX);
- for (i, &b) in needle.iter().enumerate().take(max).skip(2) {
- if ranker.rank(b) < ranker.rank(rare1) {
- rare2 = rare1;
- index2 = index1;
- rare1 = b;
- index1 = u8::try_from(i).unwrap();
- } else if b != rare1 && ranker.rank(b) < ranker.rank(rare2) {
- rare2 = b;
- index2 = u8::try_from(i).unwrap();
- }
- }
- // While not strictly required for how a Pair is normally used, we
- // really don't want these to be equivalent. If they were, it would
- // reduce the effectiveness of candidate searching using these rare
- // bytes by increasing the rate of false positives.
- assert_ne!(index1, index2);
- Some(Pair { index1, index2 })
- }
-
- /// Create a new pair using the offsets given for the needle given.
- ///
- /// This bypasses any sort of heuristic process for choosing the offsets
- /// and permits the caller to choose the offsets themselves.
- ///
- /// Indices are limited to valid `u8` values so that a `Pair` uses less
- /// memory. It is not possible to create a `Pair` with offsets bigger than
- /// `u8::MAX`. It's likely that such a thing is not needed, but if it is,
- /// it's suggested to build your own bespoke algorithm because you're
- /// likely working on a very niche case. (File an issue if this suggestion
- /// does not make sense to you.)
- ///
- /// If a pair could not be created (for example, if the needle is too
- /// short), then `None` is returned.
- #[inline]
- pub fn with_indices(
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Pair> {
- // While not strictly required for how a Pair is normally used, we
- // really don't want these to be equivalent. If they were, it would
- // reduce the effectiveness of candidate searching using these rare
- // bytes by increasing the rate of false positives.
- if index1 == index2 {
- return None;
- }
- // Similarly, invalid indices means the Pair is invalid too.
- if usize::from(index1) >= needle.len() {
- return None;
- }
- if usize::from(index2) >= needle.len() {
- return None;
- }
- Some(Pair { index1, index2 })
- }
-
- /// Returns the first offset of the pair.
- #[inline]
- pub fn index1(&self) -> u8 {
- self.index1
- }
-
- /// Returns the second offset of the pair.
- #[inline]
- pub fn index2(&self) -> u8 {
- self.index2
- }
-}
-
-/// This trait allows the user to customize the heuristic used to determine the
-/// relative frequency of a given byte in the dataset being searched.
-///
-/// The use of this trait can have a dramatic impact on performance depending
-/// on the type of data being searched. The details of why are explained in the
-/// docs of [`crate::memmem::Prefilter`]. To summarize, the core algorithm uses
-/// a prefilter to quickly identify candidate matches that are later verified
-/// more slowly. This prefilter is implemented in terms of trying to find
-/// `rare` bytes at specific offsets that will occur less frequently in the
-/// dataset. While the concept of a `rare` byte is similar for most datasets,
-/// there are some specific datasets (like binary executables) that have
-/// dramatically different byte distributions. For these datasets customizing
-/// the byte frequency heuristic can have a massive impact on performance, and
-/// might even need to be done at runtime.
-///
-/// The default implementation of `HeuristicFrequencyRank` reads from the
-/// static frequency table defined in `src/memmem/byte_frequencies.rs`. This
-/// is optimal for most inputs, so if you are unsure of the impact of using a
-/// custom `HeuristicFrequencyRank` you should probably just use the default.
-///
-/// # Example
-///
-/// ```
-/// use memchr::{
-/// arch::all::packedpair::HeuristicFrequencyRank,
-/// memmem::FinderBuilder,
-/// };
-///
-/// /// A byte-frequency table that is good for scanning binary executables.
-/// struct Binary;
-///
-/// impl HeuristicFrequencyRank for Binary {
-/// fn rank(&self, byte: u8) -> u8 {
-/// const TABLE: [u8; 256] = [
-/// 255, 128, 61, 43, 50, 41, 27, 28, 57, 15, 21, 13, 24, 17, 17,
-/// 89, 58, 16, 11, 7, 14, 23, 7, 6, 24, 9, 6, 5, 9, 4, 7, 16,
-/// 68, 11, 9, 6, 88, 7, 4, 4, 23, 9, 4, 8, 8, 5, 10, 4, 30, 11,
-/// 9, 24, 11, 5, 5, 5, 19, 11, 6, 17, 9, 9, 6, 8,
-/// 48, 58, 11, 14, 53, 40, 9, 9, 254, 35, 3, 6, 52, 23, 6, 6, 27,
-/// 4, 7, 11, 14, 13, 10, 11, 11, 5, 2, 10, 16, 12, 6, 19,
-/// 19, 20, 5, 14, 16, 31, 19, 7, 14, 20, 4, 4, 19, 8, 18, 20, 24,
-/// 1, 25, 19, 58, 29, 10, 5, 15, 20, 2, 2, 9, 4, 3, 5,
-/// 51, 11, 4, 53, 23, 39, 6, 4, 13, 81, 4, 186, 5, 67, 3, 2, 15,
-/// 0, 0, 1, 3, 2, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0,
-/// 12, 2, 1, 1, 3, 1, 1, 1, 6, 1, 2, 1, 3, 1, 1, 2, 9, 1, 1, 0,
-/// 2, 2, 4, 4, 11, 6, 7, 3, 6, 9, 4, 5,
-/// 46, 18, 8, 18, 17, 3, 8, 20, 16, 10, 3, 7, 175, 4, 6, 7, 13,
-/// 3, 7, 3, 3, 1, 3, 3, 10, 3, 1, 5, 2, 0, 1, 2,
-/// 16, 3, 5, 1, 6, 1, 1, 2, 58, 20, 3, 14, 12, 2, 1, 3, 16, 3, 5,
-/// 8, 3, 1, 8, 6, 17, 6, 5, 3, 8, 6, 13, 175,
-/// ];
-/// TABLE[byte as usize]
-/// }
-/// }
-/// // Create a new finder with the custom heuristic.
-/// let finder = FinderBuilder::new()
-/// .build_forward_with_ranker(Binary, b"\x00\x00\xdd\xdd");
-/// // Find needle with custom heuristic.
-/// assert!(finder.find(b"\x00\x00\x00\xdd\xdd").is_some());
-/// ```
-pub trait HeuristicFrequencyRank {
- /// Return the heuristic frequency rank of the given byte. A lower rank
- /// means the byte is believed to occur less frequently in the haystack.
- ///
- /// Some uses of this heuristic may treat arbitrary absolute rank values as
- /// significant. For example, an implementation detail in this crate may
- /// determine that heuristic prefilters are inappropriate if every byte in
- /// the needle has a "high" rank.
- fn rank(&self, byte: u8) -> u8;
-}
-
-/// The default byte frequency heuristic that is good for most haystacks.
-pub(crate) struct DefaultFrequencyRank;
-
-impl HeuristicFrequencyRank for DefaultFrequencyRank {
- fn rank(&self, byte: u8) -> u8 {
- self::default_rank::RANK[usize::from(byte)]
- }
-}
-
-/// This permits passing any implementation of `HeuristicFrequencyRank` as a
-/// borrowed version of itself.
-impl<'a, R> HeuristicFrequencyRank for &'a R
-where
- R: HeuristicFrequencyRank,
-{
- fn rank(&self, byte: u8) -> u8 {
- (**self).rank(byte)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn forward_packedpair() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- _index1: u8,
- _index2: u8,
- ) -> Option<Option<usize>> {
- // We ignore the index positions requested since it winds up making
- // this test too slow overall.
- let f = Finder::new(needle)?;
- Some(f.find_prefilter(haystack))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-}
diff --git a/vendor/memchr/src/arch/all/rabinkarp.rs b/vendor/memchr/src/arch/all/rabinkarp.rs
deleted file mode 100644
index e0bafba..0000000
--- a/vendor/memchr/src/arch/all/rabinkarp.rs
+++ /dev/null
@@ -1,390 +0,0 @@
-/*!
-An implementation of the [Rabin-Karp substring search algorithm][rabinkarp].
-
-Rabin-Karp works by creating a hash of the needle provided and then computing
-a rolling hash for each needle sized window in the haystack. When the rolling
-hash matches the hash of the needle, a byte-wise comparison is done to check
-if a match exists. The worst case time complexity of Rabin-Karp is `O(m *
-n)` where `m ~ len(needle)` and `n ~ len(haystack)`. Its worst case space
-complexity is constant.
-
-The main utility of Rabin-Karp is that the searcher can be constructed very
-quickly with very little memory. This makes it especially useful when searching
-for small needles in small haystacks, as it might finish its search before a
-beefier algorithm (like Two-Way) even starts.
-
-[rabinkarp]: https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
-*/
-
-/*
-(This was the comment I wrote for this module originally when it was not
-exposed. The comment still looks useful, but it's a bit in the weeds, so it's
-not public itself.)
-
-This module implements the classical Rabin-Karp substring search algorithm,
-with no extra frills. While its use would seem to break our time complexity
-guarantee of O(m+n) (RK's time complexity is O(mn)), we are careful to only
-ever use RK on a constant subset of haystacks. The main point here is that
-RK has good latency properties for small needles/haystacks. It's very quick
-to compute a needle hash and zip through the haystack when compared to
-initializing Two-Way, for example. And this is especially useful for cases
-where the haystack is just too short for vector instructions to do much good.
-
-The hashing function used here is the same one recommended by ESMAJ.
-
-Another choice instead of Rabin-Karp would be Shift-Or. But its latency
-isn't quite as good since its preprocessing time is a bit more expensive
-(both in practice and in theory). However, perhaps Shift-Or has a place
-somewhere else for short patterns. I think the main problem is that it
-requires space proportional to the alphabet and the needle. If we, for
-example, supported needles up to length 16, then the total table size would be
-len(alphabet)*size_of::<u16>()==512 bytes. Which isn't exactly small, and it's
-probably bad to put that on the stack. So ideally, we'd throw it on the heap,
-but we'd really like to write as much code without using alloc/std as possible.
-But maybe it's worth the special casing. It's a TODO to benchmark.
-
-Wikipedia has a decent explanation, if a bit heavy on the theory:
-https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
-
-But ESMAJ provides something a bit more concrete:
-http://www-igm.univ-mlv.fr/~lecroq/string/node5.html
-
-Finally, aho-corasick uses Rabin-Karp for multiple pattern match in some cases:
-https://github.com/BurntSushi/aho-corasick/blob/3852632f10587db0ff72ef29e88d58bf305a0946/src/packed/rabinkarp.rs
-*/
-
-use crate::ext::Pointer;
-
-/// A forward substring searcher using the Rabin-Karp algorithm.
-///
-/// Note that, as a lower level API, a `Finder` does not have access to the
-/// needle it was constructed with. For this reason, executing a search
-/// with a `Finder` requires passing both the needle and the haystack,
-/// where the needle is exactly equivalent to the one given to the `Finder`
-/// at construction time. This design was chosen so that callers can have
-/// more precise control over where and how many times a needle is stored.
-/// For example, in cases where Rabin-Karp is just one of several possible
-/// substring search algorithms.
-#[derive(Clone, Debug)]
-pub struct Finder {
- /// The actual hash.
- hash: Hash,
- /// The factor needed to multiply a byte by in order to subtract it from
- /// the hash. It is defined to be 2^(n-1) (using wrapping exponentiation),
- /// where n is the length of the needle. This is how we "remove" a byte
- /// from the hash once the hash window rolls past it.
- hash_2pow: u32,
-}
-
-impl Finder {
- /// Create a new Rabin-Karp forward searcher for the given `needle`.
- ///
- /// The needle may be empty. The empty needle matches at every byte offset.
- ///
- /// Note that callers must pass the same needle to all search calls using
- /// this `Finder`.
- #[inline]
- pub fn new(needle: &[u8]) -> Finder {
- let mut s = Finder { hash: Hash::new(), hash_2pow: 1 };
- let first_byte = match needle.get(0) {
- None => return s,
- Some(&first_byte) => first_byte,
- };
- s.hash.add(first_byte);
- for b in needle.iter().copied().skip(1) {
- s.hash.add(b);
- s.hash_2pow = s.hash_2pow.wrapping_shl(1);
- }
- s
- }
-
- /// Return the first occurrence of the `needle` in the `haystack`
- /// given. If no such occurrence exists, then `None` is returned.
- ///
- /// The `needle` provided must match the needle given to this finder at
- /// construction time.
- ///
- /// The maximum value this can return is `haystack.len()`, which can only
- /// occur when the needle and haystack both have length zero. Otherwise,
- /// for non-empty haystacks, the maximum value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- unsafe {
- let hstart = haystack.as_ptr();
- let hend = hstart.add(haystack.len());
- let nstart = needle.as_ptr();
- let nend = nstart.add(needle.len());
- let found = self.find_raw(hstart, hend, nstart, nend)?;
- Some(found.distance(hstart))
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `<= end`. The pointer returned is only ever equivalent
- /// to `end` when both the needle and haystack are empty. (That is, the
- /// empty string matches the empty string.)
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// Note that `start` and `end` below refer to both pairs of pointers given
- /// to this routine. That is, the conditions apply to both `hstart`/`hend`
- /// and `nstart`/`nend`.
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- /// * It must be the case that `start <= end`.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- hstart: *const u8,
- hend: *const u8,
- nstart: *const u8,
- nend: *const u8,
- ) -> Option<*const u8> {
- let hlen = hend.distance(hstart);
- let nlen = nend.distance(nstart);
- if nlen > hlen {
- return None;
- }
- let mut cur = hstart;
- let end = hend.sub(nlen);
- let mut hash = Hash::forward(cur, cur.add(nlen));
- loop {
- if self.hash == hash && is_equal_raw(cur, nstart, nlen) {
- return Some(cur);
- }
- if cur >= end {
- return None;
- }
- hash.roll(self, cur.read(), cur.add(nlen).read());
- cur = cur.add(1);
- }
- }
-}
-
-/// A reverse substring searcher using the Rabin-Karp algorithm.
-#[derive(Clone, Debug)]
-pub struct FinderRev(Finder);
-
-impl FinderRev {
- /// Create a new Rabin-Karp reverse searcher for the given `needle`.
- #[inline]
- pub fn new(needle: &[u8]) -> FinderRev {
- let mut s = FinderRev(Finder { hash: Hash::new(), hash_2pow: 1 });
- let last_byte = match needle.last() {
- None => return s,
- Some(&last_byte) => last_byte,
- };
- s.0.hash.add(last_byte);
- for b in needle.iter().rev().copied().skip(1) {
- s.0.hash.add(b);
- s.0.hash_2pow = s.0.hash_2pow.wrapping_shl(1);
- }
- s
- }
-
- /// Return the last occurrence of the `needle` in the `haystack`
- /// given. If no such occurrence exists, then `None` is returned.
- ///
- /// The `needle` provided must match the needle given to this finder at
- /// construction time.
- ///
- /// The maximum value this can return is `haystack.len()`, which can only
- /// occur when the needle and haystack both have length zero. Otherwise,
- /// for non-empty haystacks, the maximum value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- unsafe {
- let hstart = haystack.as_ptr();
- let hend = hstart.add(haystack.len());
- let nstart = needle.as_ptr();
- let nend = nstart.add(needle.len());
- let found = self.rfind_raw(hstart, hend, nstart, nend)?;
- Some(found.distance(hstart))
- }
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `<= end`. The pointer returned is only ever equivalent
- /// to `end` when both the needle and haystack are empty. (That is, the
- /// empty string matches the empty string.)
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// Note that `start` and `end` below refer to both pairs of pointers given
- /// to this routine. That is, the conditions apply to both `hstart`/`hend`
- /// and `nstart`/`nend`.
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- /// * It must be the case that `start <= end`.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- hstart: *const u8,
- hend: *const u8,
- nstart: *const u8,
- nend: *const u8,
- ) -> Option<*const u8> {
- let hlen = hend.distance(hstart);
- let nlen = nend.distance(nstart);
- if nlen > hlen {
- return None;
- }
- let mut cur = hend.sub(nlen);
- let start = hstart;
- let mut hash = Hash::reverse(cur, cur.add(nlen));
- loop {
- if self.0.hash == hash && is_equal_raw(cur, nstart, nlen) {
- return Some(cur);
- }
- if cur <= start {
- return None;
- }
- cur = cur.sub(1);
- hash.roll(&self.0, cur.add(nlen).read(), cur.read());
- }
- }
-}
-
-/// Whether RK is believed to be very fast for the given needle/haystack.
-#[inline]
-pub(crate) fn is_fast(haystack: &[u8], _needle: &[u8]) -> bool {
- haystack.len() < 16
-}
-
-/// A Rabin-Karp hash. This might represent the hash of a needle, or the hash
-/// of a rolling window in the haystack.
-#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
-struct Hash(u32);
-
-impl Hash {
- /// Create a new hash that represents the empty string.
- #[inline(always)]
- fn new() -> Hash {
- Hash(0)
- }
-
- /// Create a new hash from the bytes given for use in forward searches.
- ///
- /// # Safety
- ///
- /// The given pointers must be valid to read from within their range.
- #[inline(always)]
- unsafe fn forward(mut start: *const u8, end: *const u8) -> Hash {
- let mut hash = Hash::new();
- while start < end {
- hash.add(start.read());
- start = start.add(1);
- }
- hash
- }
-
- /// Create a new hash from the bytes given for use in reverse searches.
- ///
- /// # Safety
- ///
- /// The given pointers must be valid to read from within their range.
- #[inline(always)]
- unsafe fn reverse(start: *const u8, mut end: *const u8) -> Hash {
- let mut hash = Hash::new();
- while start < end {
- end = end.sub(1);
- hash.add(end.read());
- }
- hash
- }
-
- /// Add 'new' and remove 'old' from this hash. The given needle hash should
- /// correspond to the hash computed for the needle being searched for.
- ///
- /// This is meant to be used when the rolling window of the haystack is
- /// advanced.
- #[inline(always)]
- fn roll(&mut self, finder: &Finder, old: u8, new: u8) {
- self.del(finder, old);
- self.add(new);
- }
-
- /// Add a byte to this hash.
- #[inline(always)]
- fn add(&mut self, byte: u8) {
- self.0 = self.0.wrapping_shl(1).wrapping_add(u32::from(byte));
- }
-
- /// Remove a byte from this hash. The given needle hash should correspond
- /// to the hash computed for the needle being searched for.
- #[inline(always)]
- fn del(&mut self, finder: &Finder, byte: u8) {
- let factor = finder.hash_2pow;
- self.0 = self.0.wrapping_sub(u32::from(byte).wrapping_mul(factor));
- }
-}
-
-/// Returns true when `x[i] == y[i]` for all `0 <= i < n`.
-///
-/// We forcefully don't inline this to hint at the compiler that it is unlikely
-/// to be called. This causes the inner rabinkarp loop above to be a bit
-/// tighter and leads to some performance improvement. See the
-/// memmem/krate/prebuilt/sliceslice-words/words benchmark.
-///
-/// # Safety
-///
-/// Same as `crate::arch::all::is_equal_raw`.
-#[cold]
-#[inline(never)]
-unsafe fn is_equal_raw(x: *const u8, y: *const u8, n: usize) -> bool {
- crate::arch::all::is_equal_raw(x, y, n)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_substring_forward_quickcheck!(|h, n| Some(
- Finder::new(n).find(h, n)
- ));
- define_substring_reverse_quickcheck!(|h, n| Some(
- FinderRev::new(n).rfind(h, n)
- ));
-
- #[test]
- fn forward() {
- crate::tests::substring::Runner::new()
- .fwd(|h, n| Some(Finder::new(n).find(h, n)))
- .run();
- }
-
- #[test]
- fn reverse() {
- crate::tests::substring::Runner::new()
- .rev(|h, n| Some(FinderRev::new(n).rfind(h, n)))
- .run();
- }
-}
diff --git a/vendor/memchr/src/arch/all/shiftor.rs b/vendor/memchr/src/arch/all/shiftor.rs
deleted file mode 100644
index b690564..0000000
--- a/vendor/memchr/src/arch/all/shiftor.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-/*!
-An implementation of the [Shift-Or substring search algorithm][shiftor].
-
-[shiftor]: https://en.wikipedia.org/wiki/Bitap_algorithm
-*/
-
-use alloc::boxed::Box;
-
-/// The type of our mask.
-///
-/// While we don't expose anyway to configure this in the public API, if one
-/// really needs less memory usage or support for longer needles, then it is
-/// suggested to copy the code from this module and modify it to fit your
-/// needs. The code below is written to be correct regardless of whether Mask
-/// is a u8, u16, u32, u64 or u128.
-type Mask = u16;
-
-/// A forward substring searcher using the Shift-Or algorithm.
-#[derive(Debug)]
-pub struct Finder {
- masks: Box<[Mask; 256]>,
- needle_len: usize,
-}
-
-impl Finder {
- const MAX_NEEDLE_LEN: usize = (Mask::BITS - 1) as usize;
-
- /// Create a new Shift-Or forward searcher for the given `needle`.
- ///
- /// The needle may be empty. The empty needle matches at every byte offset.
- #[inline]
- pub fn new(needle: &[u8]) -> Option<Finder> {
- let needle_len = needle.len();
- if needle_len > Finder::MAX_NEEDLE_LEN {
- // A match is found when bit 7 is set in 'result' in the search
- // routine below. So our needle can't be bigger than 7. We could
- // permit bigger needles by using u16, u32 or u64 for our mask
- // entries. But this is all we need for this example.
- return None;
- }
- let mut searcher = Finder { masks: Box::from([!0; 256]), needle_len };
- for (i, &byte) in needle.iter().enumerate() {
- searcher.masks[usize::from(byte)] &= !(1 << i);
- }
- Some(searcher)
- }
-
- /// Return the first occurrence of the needle given to `Finder::new` in
- /// the `haystack` given. If no such occurrence exists, then `None` is
- /// returned.
- ///
- /// Unlike most other substring search implementations in this crate, this
- /// finder does not require passing the needle at search time. A match can
- /// be determined without the needle at all since the required information
- /// is already encoded into this finder at construction time.
- ///
- /// The maximum value this can return is `haystack.len()`, which can only
- /// occur when the needle and haystack both have length zero. Otherwise,
- /// for non-empty haystacks, the maximum value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- if self.needle_len == 0 {
- return Some(0);
- }
- let mut result = !1;
- for (i, &byte) in haystack.iter().enumerate() {
- result |= self.masks[usize::from(byte)];
- result <<= 1;
- if result & (1 << self.needle_len) == 0 {
- return Some(i + 1 - self.needle_len);
- }
- }
- None
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_substring_forward_quickcheck!(|h, n| Some(Finder::new(n)?.find(h)));
-
- #[test]
- fn forward() {
- crate::tests::substring::Runner::new()
- .fwd(|h, n| Some(Finder::new(n)?.find(h)))
- .run();
- }
-}
diff --git a/vendor/memchr/src/arch/all/twoway.rs b/vendor/memchr/src/arch/all/twoway.rs
deleted file mode 100644
index 0df3b4a..0000000
--- a/vendor/memchr/src/arch/all/twoway.rs
+++ /dev/null
@@ -1,877 +0,0 @@
-/*!
-An implementation of the [Two-Way substring search algorithm][two-way].
-
-[`Finder`] can be built for forward searches, while [`FinderRev`] can be built
-for reverse searches.
-
-Two-Way makes for a nice general purpose substring search algorithm because of
-its time and space complexity properties. It also performs well in practice.
-Namely, with `m = len(needle)` and `n = len(haystack)`, Two-Way takes `O(m)`
-time to create a finder, `O(1)` space and `O(n)` search time. In other words,
-the preprocessing step is quick, doesn't require any heap memory and the worst
-case search time is guaranteed to be linear in the haystack regardless of the
-size of the needle.
-
-While vector algorithms will usually beat Two-Way handedly, vector algorithms
-also usually have pathological or edge cases that are better handled by Two-Way.
-Moreover, not all targets support vector algorithms or implementations for them
-simply may not exist yet.
-
-Two-Way can be found in the `memmem` implementations in at least [GNU libc] and
-[musl].
-
-[two-way]: https://en.wikipedia.org/wiki/Two-way_string-matching_algorithm
-[GNU libc]: https://www.gnu.org/software/libc/
-[musl]: https://www.musl-libc.org/
-*/
-
-use core::cmp;
-
-use crate::{
- arch::all::{is_prefix, is_suffix},
- memmem::Pre,
-};
-
-/// A forward substring searcher that uses the Two-Way algorithm.
-#[derive(Clone, Copy, Debug)]
-pub struct Finder(TwoWay);
-
-/// A reverse substring searcher that uses the Two-Way algorithm.
-#[derive(Clone, Copy, Debug)]
-pub struct FinderRev(TwoWay);
-
-/// An implementation of the TwoWay substring search algorithm.
-///
-/// This searcher supports forward and reverse search, although not
-/// simultaneously. It runs in `O(n + m)` time and `O(1)` space, where
-/// `n ~ len(needle)` and `m ~ len(haystack)`.
-///
-/// The implementation here roughly matches that which was developed by
-/// Crochemore and Perrin in their 1991 paper "Two-way string-matching." The
-/// changes in this implementation are 1) the use of zero-based indices, 2) a
-/// heuristic skip table based on the last byte (borrowed from Rust's standard
-/// library) and 3) the addition of heuristics for a fast skip loop. For (3),
-/// callers can pass any kind of prefilter they want, but usually it's one
-/// based on a heuristic that uses an approximate background frequency of bytes
-/// to choose rare bytes to quickly look for candidate match positions. Note
-/// though that currently, this prefilter functionality is not exposed directly
-/// in the public API. (File an issue if you want it and provide a use case
-/// please.)
-///
-/// The heuristic for fast skipping is automatically shut off if it's
-/// detected to be ineffective at search time. Generally, this only occurs in
-/// pathological cases. But this is generally necessary in order to preserve
-/// a `O(n + m)` time bound.
-///
-/// The code below is fairly complex and not obviously correct at all. It's
-/// likely necessary to read the Two-Way paper cited above in order to fully
-/// grok this code. The essence of it is:
-///
-/// 1. Do something to detect a "critical" position in the needle.
-/// 2. For the current position in the haystack, look if `needle[critical..]`
-/// matches at that position.
-/// 3. If so, look if `needle[..critical]` matches.
-/// 4. If a mismatch occurs, shift the search by some amount based on the
-/// critical position and a pre-computed shift.
-///
-/// This type is wrapped in the forward and reverse finders that expose
-/// consistent forward or reverse APIs.
-#[derive(Clone, Copy, Debug)]
-struct TwoWay {
- /// A small bitset used as a quick prefilter (in addition to any prefilter
- /// given by the caller). Namely, a bit `i` is set if and only if `b%64==i`
- /// for any `b == needle[i]`.
- ///
- /// When used as a prefilter, if the last byte at the current candidate
- /// position is NOT in this set, then we can skip that entire candidate
- /// position (the length of the needle). This is essentially the shift
- /// trick found in Boyer-Moore, but only applied to bytes that don't appear
- /// in the needle.
- ///
- /// N.B. This trick was inspired by something similar in std's
- /// implementation of Two-Way.
- byteset: ApproximateByteSet,
- /// A critical position in needle. Specifically, this position corresponds
- /// to beginning of either the minimal or maximal suffix in needle. (N.B.
- /// See SuffixType below for why "minimal" isn't quite the correct word
- /// here.)
- ///
- /// This is the position at which every search begins. Namely, search
- /// starts by scanning text to the right of this position, and only if
- /// there's a match does the text to the left of this position get scanned.
- critical_pos: usize,
- /// The amount we shift by in the Two-Way search algorithm. This
- /// corresponds to the "small period" and "large period" cases.
- shift: Shift,
-}
-
-impl Finder {
- /// Create a searcher that finds occurrences of the given `needle`.
- ///
- /// An empty `needle` results in a match at every position in a haystack,
- /// including at `haystack.len()`.
- #[inline]
- pub fn new(needle: &[u8]) -> Finder {
- let byteset = ApproximateByteSet::new(needle);
- let min_suffix = Suffix::forward(needle, SuffixKind::Minimal);
- let max_suffix = Suffix::forward(needle, SuffixKind::Maximal);
- let (period_lower_bound, critical_pos) =
- if min_suffix.pos > max_suffix.pos {
- (min_suffix.period, min_suffix.pos)
- } else {
- (max_suffix.period, max_suffix.pos)
- };
- let shift = Shift::forward(needle, period_lower_bound, critical_pos);
- Finder(TwoWay { byteset, critical_pos, shift })
- }
-
- /// Returns the first occurrence of `needle` in the given `haystack`, or
- /// `None` if no such occurrence could be found.
- ///
- /// The `needle` given must be the same as the `needle` provided to
- /// [`Finder::new`].
- ///
- /// An empty `needle` results in a match at every position in a haystack,
- /// including at `haystack.len()`.
- #[inline]
- pub fn find(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- self.find_with_prefilter(None, haystack, needle)
- }
-
- /// This is like [`Finder::find`], but it accepts a prefilter for
- /// accelerating searches.
- ///
- /// Currently this is not exposed in the public API because, at the time
- /// of writing, I didn't want to spend time thinking about how to expose
- /// the prefilter infrastructure (if at all). If you have a compelling use
- /// case for exposing this routine, please create an issue. Do *not* open
- /// a PR that just exposes `Pre` and friends. Exporting this routine will
- /// require API design.
- #[inline(always)]
- pub(crate) fn find_with_prefilter(
- &self,
- pre: Option<Pre<'_>>,
- haystack: &[u8],
- needle: &[u8],
- ) -> Option<usize> {
- match self.0.shift {
- Shift::Small { period } => {
- self.find_small_imp(pre, haystack, needle, period)
- }
- Shift::Large { shift } => {
- self.find_large_imp(pre, haystack, needle, shift)
- }
- }
- }
-
- // Each of the two search implementations below can be accelerated by a
- // prefilter, but it is not always enabled. To avoid its overhead when
- // its disabled, we explicitly inline each search implementation based on
- // whether a prefilter will be used or not. The decision on which to use
- // is made in the parent meta searcher.
-
- #[inline(always)]
- fn find_small_imp(
- &self,
- mut pre: Option<Pre<'_>>,
- haystack: &[u8],
- needle: &[u8],
- period: usize,
- ) -> Option<usize> {
- let mut pos = 0;
- let mut shift = 0;
- let last_byte_pos = match needle.len().checked_sub(1) {
- None => return Some(pos),
- Some(last_byte) => last_byte,
- };
- while pos + needle.len() <= haystack.len() {
- let mut i = cmp::max(self.0.critical_pos, shift);
- if let Some(pre) = pre.as_mut() {
- if pre.is_effective() {
- pos += pre.find(&haystack[pos..])?;
- shift = 0;
- i = self.0.critical_pos;
- if pos + needle.len() > haystack.len() {
- return None;
- }
- }
- }
- if !self.0.byteset.contains(haystack[pos + last_byte_pos]) {
- pos += needle.len();
- shift = 0;
- continue;
- }
- while i < needle.len() && needle[i] == haystack[pos + i] {
- i += 1;
- }
- if i < needle.len() {
- pos += i - self.0.critical_pos + 1;
- shift = 0;
- } else {
- let mut j = self.0.critical_pos;
- while j > shift && needle[j] == haystack[pos + j] {
- j -= 1;
- }
- if j <= shift && needle[shift] == haystack[pos + shift] {
- return Some(pos);
- }
- pos += period;
- shift = needle.len() - period;
- }
- }
- None
- }
-
- #[inline(always)]
- fn find_large_imp(
- &self,
- mut pre: Option<Pre<'_>>,
- haystack: &[u8],
- needle: &[u8],
- shift: usize,
- ) -> Option<usize> {
- let mut pos = 0;
- let last_byte_pos = match needle.len().checked_sub(1) {
- None => return Some(pos),
- Some(last_byte) => last_byte,
- };
- 'outer: while pos + needle.len() <= haystack.len() {
- if let Some(pre) = pre.as_mut() {
- if pre.is_effective() {
- pos += pre.find(&haystack[pos..])?;
- if pos + needle.len() > haystack.len() {
- return None;
- }
- }
- }
-
- if !self.0.byteset.contains(haystack[pos + last_byte_pos]) {
- pos += needle.len();
- continue;
- }
- let mut i = self.0.critical_pos;
- while i < needle.len() && needle[i] == haystack[pos + i] {
- i += 1;
- }
- if i < needle.len() {
- pos += i - self.0.critical_pos + 1;
- } else {
- for j in (0..self.0.critical_pos).rev() {
- if needle[j] != haystack[pos + j] {
- pos += shift;
- continue 'outer;
- }
- }
- return Some(pos);
- }
- }
- None
- }
-}
-
-impl FinderRev {
- /// Create a searcher that finds occurrences of the given `needle`.
- ///
- /// An empty `needle` results in a match at every position in a haystack,
- /// including at `haystack.len()`.
- #[inline]
- pub fn new(needle: &[u8]) -> FinderRev {
- let byteset = ApproximateByteSet::new(needle);
- let min_suffix = Suffix::reverse(needle, SuffixKind::Minimal);
- let max_suffix = Suffix::reverse(needle, SuffixKind::Maximal);
- let (period_lower_bound, critical_pos) =
- if min_suffix.pos < max_suffix.pos {
- (min_suffix.period, min_suffix.pos)
- } else {
- (max_suffix.period, max_suffix.pos)
- };
- let shift = Shift::reverse(needle, period_lower_bound, critical_pos);
- FinderRev(TwoWay { byteset, critical_pos, shift })
- }
-
- /// Returns the last occurrence of `needle` in the given `haystack`, or
- /// `None` if no such occurrence could be found.
- ///
- /// The `needle` given must be the same as the `needle` provided to
- /// [`FinderRev::new`].
- ///
- /// An empty `needle` results in a match at every position in a haystack,
- /// including at `haystack.len()`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- // For the reverse case, we don't use a prefilter. It's plausible that
- // perhaps we should, but it's a lot of additional code to do it, and
- // it's not clear that it's actually worth it. If you have a really
- // compelling use case for this, please file an issue.
- match self.0.shift {
- Shift::Small { period } => {
- self.rfind_small_imp(haystack, needle, period)
- }
- Shift::Large { shift } => {
- self.rfind_large_imp(haystack, needle, shift)
- }
- }
- }
-
- #[inline(always)]
- fn rfind_small_imp(
- &self,
- haystack: &[u8],
- needle: &[u8],
- period: usize,
- ) -> Option<usize> {
- let nlen = needle.len();
- let mut pos = haystack.len();
- let mut shift = nlen;
- let first_byte = match needle.get(0) {
- None => return Some(pos),
- Some(&first_byte) => first_byte,
- };
- while pos >= nlen {
- if !self.0.byteset.contains(haystack[pos - nlen]) {
- pos -= nlen;
- shift = nlen;
- continue;
- }
- let mut i = cmp::min(self.0.critical_pos, shift);
- while i > 0 && needle[i - 1] == haystack[pos - nlen + i - 1] {
- i -= 1;
- }
- if i > 0 || first_byte != haystack[pos - nlen] {
- pos -= self.0.critical_pos - i + 1;
- shift = nlen;
- } else {
- let mut j = self.0.critical_pos;
- while j < shift && needle[j] == haystack[pos - nlen + j] {
- j += 1;
- }
- if j >= shift {
- return Some(pos - nlen);
- }
- pos -= period;
- shift = period;
- }
- }
- None
- }
-
- #[inline(always)]
- fn rfind_large_imp(
- &self,
- haystack: &[u8],
- needle: &[u8],
- shift: usize,
- ) -> Option<usize> {
- let nlen = needle.len();
- let mut pos = haystack.len();
- let first_byte = match needle.get(0) {
- None => return Some(pos),
- Some(&first_byte) => first_byte,
- };
- while pos >= nlen {
- if !self.0.byteset.contains(haystack[pos - nlen]) {
- pos -= nlen;
- continue;
- }
- let mut i = self.0.critical_pos;
- while i > 0 && needle[i - 1] == haystack[pos - nlen + i - 1] {
- i -= 1;
- }
- if i > 0 || first_byte != haystack[pos - nlen] {
- pos -= self.0.critical_pos - i + 1;
- } else {
- let mut j = self.0.critical_pos;
- while j < nlen && needle[j] == haystack[pos - nlen + j] {
- j += 1;
- }
- if j == nlen {
- return Some(pos - nlen);
- }
- pos -= shift;
- }
- }
- None
- }
-}
-
-/// A representation of the amount we're allowed to shift by during Two-Way
-/// search.
-///
-/// When computing a critical factorization of the needle, we find the position
-/// of the critical factorization by finding the needle's maximal (or minimal)
-/// suffix, along with the period of that suffix. It turns out that the period
-/// of that suffix is a lower bound on the period of the needle itself.
-///
-/// This lower bound is equivalent to the actual period of the needle in
-/// some cases. To describe that case, we denote the needle as `x` where
-/// `x = uv` and `v` is the lexicographic maximal suffix of `v`. The lower
-/// bound given here is always the period of `v`, which is `<= period(x)`. The
-/// case where `period(v) == period(x)` occurs when `len(u) < (len(x) / 2)` and
-/// where `u` is a suffix of `v[0..period(v)]`.
-///
-/// This case is important because the search algorithm for when the
-/// periods are equivalent is slightly different than the search algorithm
-/// for when the periods are not equivalent. In particular, when they aren't
-/// equivalent, we know that the period of the needle is no less than half its
-/// length. In this case, we shift by an amount less than or equal to the
-/// period of the needle (determined by the maximum length of the components
-/// of the critical factorization of `x`, i.e., `max(len(u), len(v))`)..
-///
-/// The above two cases are represented by the variants below. Each entails
-/// a different instantiation of the Two-Way search algorithm.
-///
-/// N.B. If we could find a way to compute the exact period in all cases,
-/// then we could collapse this case analysis and simplify the algorithm. The
-/// Two-Way paper suggests this is possible, but more reading is required to
-/// grok why the authors didn't pursue that path.
-#[derive(Clone, Copy, Debug)]
-enum Shift {
- Small { period: usize },
- Large { shift: usize },
-}
-
-impl Shift {
- /// Compute the shift for a given needle in the forward direction.
- ///
- /// This requires a lower bound on the period and a critical position.
- /// These can be computed by extracting both the minimal and maximal
- /// lexicographic suffixes, and choosing the right-most starting position.
- /// The lower bound on the period is then the period of the chosen suffix.
- fn forward(
- needle: &[u8],
- period_lower_bound: usize,
- critical_pos: usize,
- ) -> Shift {
- let large = cmp::max(critical_pos, needle.len() - critical_pos);
- if critical_pos * 2 >= needle.len() {
- return Shift::Large { shift: large };
- }
-
- let (u, v) = needle.split_at(critical_pos);
- if !is_suffix(&v[..period_lower_bound], u) {
- return Shift::Large { shift: large };
- }
- Shift::Small { period: period_lower_bound }
- }
-
- /// Compute the shift for a given needle in the reverse direction.
- ///
- /// This requires a lower bound on the period and a critical position.
- /// These can be computed by extracting both the minimal and maximal
- /// lexicographic suffixes, and choosing the left-most starting position.
- /// The lower bound on the period is then the period of the chosen suffix.
- fn reverse(
- needle: &[u8],
- period_lower_bound: usize,
- critical_pos: usize,
- ) -> Shift {
- let large = cmp::max(critical_pos, needle.len() - critical_pos);
- if (needle.len() - critical_pos) * 2 >= needle.len() {
- return Shift::Large { shift: large };
- }
-
- let (v, u) = needle.split_at(critical_pos);
- if !is_prefix(&v[v.len() - period_lower_bound..], u) {
- return Shift::Large { shift: large };
- }
- Shift::Small { period: period_lower_bound }
- }
-}
-
-/// A suffix extracted from a needle along with its period.
-#[derive(Debug)]
-struct Suffix {
- /// The starting position of this suffix.
- ///
- /// If this is a forward suffix, then `&bytes[pos..]` can be used. If this
- /// is a reverse suffix, then `&bytes[..pos]` can be used. That is, for
- /// forward suffixes, this is an inclusive starting position, where as for
- /// reverse suffixes, this is an exclusive ending position.
- pos: usize,
- /// The period of this suffix.
- ///
- /// Note that this is NOT necessarily the period of the string from which
- /// this suffix comes from. (It is always less than or equal to the period
- /// of the original string.)
- period: usize,
-}
-
-impl Suffix {
- fn forward(needle: &[u8], kind: SuffixKind) -> Suffix {
- // suffix represents our maximal (or minimal) suffix, along with
- // its period.
- let mut suffix = Suffix { pos: 0, period: 1 };
- // The start of a suffix in `needle` that we are considering as a
- // more maximal (or minimal) suffix than what's in `suffix`.
- let mut candidate_start = 1;
- // The current offset of our suffixes that we're comparing.
- //
- // When the characters at this offset are the same, then we mush on
- // to the next position since no decision is possible. When the
- // candidate's character is greater (or lesser) than the corresponding
- // character than our current maximal (or minimal) suffix, then the
- // current suffix is changed over to the candidate and we restart our
- // search. Otherwise, the candidate suffix is no good and we restart
- // our search on the next candidate.
- //
- // The three cases above correspond to the three cases in the loop
- // below.
- let mut offset = 0;
-
- while candidate_start + offset < needle.len() {
- let current = needle[suffix.pos + offset];
- let candidate = needle[candidate_start + offset];
- match kind.cmp(current, candidate) {
- SuffixOrdering::Accept => {
- suffix = Suffix { pos: candidate_start, period: 1 };
- candidate_start += 1;
- offset = 0;
- }
- SuffixOrdering::Skip => {
- candidate_start += offset + 1;
- offset = 0;
- suffix.period = candidate_start - suffix.pos;
- }
- SuffixOrdering::Push => {
- if offset + 1 == suffix.period {
- candidate_start += suffix.period;
- offset = 0;
- } else {
- offset += 1;
- }
- }
- }
- }
- suffix
- }
-
- fn reverse(needle: &[u8], kind: SuffixKind) -> Suffix {
- // See the comments in `forward` for how this works.
- let mut suffix = Suffix { pos: needle.len(), period: 1 };
- if needle.len() == 1 {
- return suffix;
- }
- let mut candidate_start = match needle.len().checked_sub(1) {
- None => return suffix,
- Some(candidate_start) => candidate_start,
- };
- let mut offset = 0;
-
- while offset < candidate_start {
- let current = needle[suffix.pos - offset - 1];
- let candidate = needle[candidate_start - offset - 1];
- match kind.cmp(current, candidate) {
- SuffixOrdering::Accept => {
- suffix = Suffix { pos: candidate_start, period: 1 };
- candidate_start -= 1;
- offset = 0;
- }
- SuffixOrdering::Skip => {
- candidate_start -= offset + 1;
- offset = 0;
- suffix.period = suffix.pos - candidate_start;
- }
- SuffixOrdering::Push => {
- if offset + 1 == suffix.period {
- candidate_start -= suffix.period;
- offset = 0;
- } else {
- offset += 1;
- }
- }
- }
- }
- suffix
- }
-}
-
-/// The kind of suffix to extract.
-#[derive(Clone, Copy, Debug)]
-enum SuffixKind {
- /// Extract the smallest lexicographic suffix from a string.
- ///
- /// Technically, this doesn't actually pick the smallest lexicographic
- /// suffix. e.g., Given the choice between `a` and `aa`, this will choose
- /// the latter over the former, even though `a < aa`. The reasoning for
- /// this isn't clear from the paper, but it still smells like a minimal
- /// suffix.
- Minimal,
- /// Extract the largest lexicographic suffix from a string.
- ///
- /// Unlike `Minimal`, this really does pick the maximum suffix. e.g., Given
- /// the choice between `z` and `zz`, this will choose the latter over the
- /// former.
- Maximal,
-}
-
-/// The result of comparing corresponding bytes between two suffixes.
-#[derive(Clone, Copy, Debug)]
-enum SuffixOrdering {
- /// This occurs when the given candidate byte indicates that the candidate
- /// suffix is better than the current maximal (or minimal) suffix. That is,
- /// the current candidate suffix should supplant the current maximal (or
- /// minimal) suffix.
- Accept,
- /// This occurs when the given candidate byte excludes the candidate suffix
- /// from being better than the current maximal (or minimal) suffix. That
- /// is, the current candidate suffix should be dropped and the next one
- /// should be considered.
- Skip,
- /// This occurs when no decision to accept or skip the candidate suffix
- /// can be made, e.g., when corresponding bytes are equivalent. In this
- /// case, the next corresponding bytes should be compared.
- Push,
-}
-
-impl SuffixKind {
- /// Returns true if and only if the given candidate byte indicates that
- /// it should replace the current suffix as the maximal (or minimal)
- /// suffix.
- fn cmp(self, current: u8, candidate: u8) -> SuffixOrdering {
- use self::SuffixOrdering::*;
-
- match self {
- SuffixKind::Minimal if candidate < current => Accept,
- SuffixKind::Minimal if candidate > current => Skip,
- SuffixKind::Minimal => Push,
- SuffixKind::Maximal if candidate > current => Accept,
- SuffixKind::Maximal if candidate < current => Skip,
- SuffixKind::Maximal => Push,
- }
- }
-}
-
-/// A bitset used to track whether a particular byte exists in a needle or not.
-///
-/// Namely, bit 'i' is set if and only if byte%64==i for any byte in the
-/// needle. If a particular byte in the haystack is NOT in this set, then one
-/// can conclude that it is also not in the needle, and thus, one can advance
-/// in the haystack by needle.len() bytes.
-#[derive(Clone, Copy, Debug)]
-struct ApproximateByteSet(u64);
-
-impl ApproximateByteSet {
- /// Create a new set from the given needle.
- fn new(needle: &[u8]) -> ApproximateByteSet {
- let mut bits = 0;
- for &b in needle {
- bits |= 1 << (b % 64);
- }
- ApproximateByteSet(bits)
- }
-
- /// Return true if and only if the given byte might be in this set. This
- /// may return a false positive, but will never return a false negative.
- #[inline(always)]
- fn contains(&self, byte: u8) -> bool {
- self.0 & (1 << (byte % 64)) != 0
- }
-}
-
-#[cfg(test)]
-mod tests {
- use alloc::vec::Vec;
-
- use super::*;
-
- /// Convenience wrapper for computing the suffix as a byte string.
- fn get_suffix_forward(needle: &[u8], kind: SuffixKind) -> (&[u8], usize) {
- let s = Suffix::forward(needle, kind);
- (&needle[s.pos..], s.period)
- }
-
- /// Convenience wrapper for computing the reverse suffix as a byte string.
- fn get_suffix_reverse(needle: &[u8], kind: SuffixKind) -> (&[u8], usize) {
- let s = Suffix::reverse(needle, kind);
- (&needle[..s.pos], s.period)
- }
-
- /// Return all of the non-empty suffixes in the given byte string.
- fn suffixes(bytes: &[u8]) -> Vec<&[u8]> {
- (0..bytes.len()).map(|i| &bytes[i..]).collect()
- }
-
- /// Return the lexicographically maximal suffix of the given byte string.
- fn naive_maximal_suffix_forward(needle: &[u8]) -> &[u8] {
- let mut sufs = suffixes(needle);
- sufs.sort();
- sufs.pop().unwrap()
- }
-
- /// Return the lexicographically maximal suffix of the reverse of the given
- /// byte string.
- fn naive_maximal_suffix_reverse(needle: &[u8]) -> Vec<u8> {
- let mut reversed = needle.to_vec();
- reversed.reverse();
- let mut got = naive_maximal_suffix_forward(&reversed).to_vec();
- got.reverse();
- got
- }
-
- define_substring_forward_quickcheck!(|h, n| Some(
- Finder::new(n).find(h, n)
- ));
- define_substring_reverse_quickcheck!(|h, n| Some(
- FinderRev::new(n).rfind(h, n)
- ));
-
- #[test]
- fn forward() {
- crate::tests::substring::Runner::new()
- .fwd(|h, n| Some(Finder::new(n).find(h, n)))
- .run();
- }
-
- #[test]
- fn reverse() {
- crate::tests::substring::Runner::new()
- .rev(|h, n| Some(FinderRev::new(n).rfind(h, n)))
- .run();
- }
-
- #[test]
- fn suffix_forward() {
- macro_rules! assert_suffix_min {
- ($given:expr, $expected:expr, $period:expr) => {
- let (got_suffix, got_period) =
- get_suffix_forward($given.as_bytes(), SuffixKind::Minimal);
- let got_suffix = core::str::from_utf8(got_suffix).unwrap();
- assert_eq!(($expected, $period), (got_suffix, got_period));
- };
- }
-
- macro_rules! assert_suffix_max {
- ($given:expr, $expected:expr, $period:expr) => {
- let (got_suffix, got_period) =
- get_suffix_forward($given.as_bytes(), SuffixKind::Maximal);
- let got_suffix = core::str::from_utf8(got_suffix).unwrap();
- assert_eq!(($expected, $period), (got_suffix, got_period));
- };
- }
-
- assert_suffix_min!("a", "a", 1);
- assert_suffix_max!("a", "a", 1);
-
- assert_suffix_min!("ab", "ab", 2);
- assert_suffix_max!("ab", "b", 1);
-
- assert_suffix_min!("ba", "a", 1);
- assert_suffix_max!("ba", "ba", 2);
-
- assert_suffix_min!("abc", "abc", 3);
- assert_suffix_max!("abc", "c", 1);
-
- assert_suffix_min!("acb", "acb", 3);
- assert_suffix_max!("acb", "cb", 2);
-
- assert_suffix_min!("cba", "a", 1);
- assert_suffix_max!("cba", "cba", 3);
-
- assert_suffix_min!("abcabc", "abcabc", 3);
- assert_suffix_max!("abcabc", "cabc", 3);
-
- assert_suffix_min!("abcabcabc", "abcabcabc", 3);
- assert_suffix_max!("abcabcabc", "cabcabc", 3);
-
- assert_suffix_min!("abczz", "abczz", 5);
- assert_suffix_max!("abczz", "zz", 1);
-
- assert_suffix_min!("zzabc", "abc", 3);
- assert_suffix_max!("zzabc", "zzabc", 5);
-
- assert_suffix_min!("aaa", "aaa", 1);
- assert_suffix_max!("aaa", "aaa", 1);
-
- assert_suffix_min!("foobar", "ar", 2);
- assert_suffix_max!("foobar", "r", 1);
- }
-
- #[test]
- fn suffix_reverse() {
- macro_rules! assert_suffix_min {
- ($given:expr, $expected:expr, $period:expr) => {
- let (got_suffix, got_period) =
- get_suffix_reverse($given.as_bytes(), SuffixKind::Minimal);
- let got_suffix = core::str::from_utf8(got_suffix).unwrap();
- assert_eq!(($expected, $period), (got_suffix, got_period));
- };
- }
-
- macro_rules! assert_suffix_max {
- ($given:expr, $expected:expr, $period:expr) => {
- let (got_suffix, got_period) =
- get_suffix_reverse($given.as_bytes(), SuffixKind::Maximal);
- let got_suffix = core::str::from_utf8(got_suffix).unwrap();
- assert_eq!(($expected, $period), (got_suffix, got_period));
- };
- }
-
- assert_suffix_min!("a", "a", 1);
- assert_suffix_max!("a", "a", 1);
-
- assert_suffix_min!("ab", "a", 1);
- assert_suffix_max!("ab", "ab", 2);
-
- assert_suffix_min!("ba", "ba", 2);
- assert_suffix_max!("ba", "b", 1);
-
- assert_suffix_min!("abc", "a", 1);
- assert_suffix_max!("abc", "abc", 3);
-
- assert_suffix_min!("acb", "a", 1);
- assert_suffix_max!("acb", "ac", 2);
-
- assert_suffix_min!("cba", "cba", 3);
- assert_suffix_max!("cba", "c", 1);
-
- assert_suffix_min!("abcabc", "abca", 3);
- assert_suffix_max!("abcabc", "abcabc", 3);
-
- assert_suffix_min!("abcabcabc", "abcabca", 3);
- assert_suffix_max!("abcabcabc", "abcabcabc", 3);
-
- assert_suffix_min!("abczz", "a", 1);
- assert_suffix_max!("abczz", "abczz", 5);
-
- assert_suffix_min!("zzabc", "zza", 3);
- assert_suffix_max!("zzabc", "zz", 1);
-
- assert_suffix_min!("aaa", "aaa", 1);
- assert_suffix_max!("aaa", "aaa", 1);
- }
-
- #[cfg(not(miri))]
- quickcheck::quickcheck! {
- fn qc_suffix_forward_maximal(bytes: Vec<u8>) -> bool {
- if bytes.is_empty() {
- return true;
- }
-
- let (got, _) = get_suffix_forward(&bytes, SuffixKind::Maximal);
- let expected = naive_maximal_suffix_forward(&bytes);
- got == expected
- }
-
- fn qc_suffix_reverse_maximal(bytes: Vec<u8>) -> bool {
- if bytes.is_empty() {
- return true;
- }
-
- let (got, _) = get_suffix_reverse(&bytes, SuffixKind::Maximal);
- let expected = naive_maximal_suffix_reverse(&bytes);
- expected == got
- }
- }
-
- // This is a regression test caught by quickcheck that exercised a bug in
- // the reverse small period handling. The bug was that we were using 'if j
- // == shift' to determine if a match occurred, but the correct guard is 'if
- // j >= shift', which matches the corresponding guard in the forward impl.
- #[test]
- fn regression_rev_small_period() {
- let rfind = |h, n| FinderRev::new(n).rfind(h, n);
- let haystack = "ababaz";
- let needle = "abab";
- assert_eq!(Some(0), rfind(haystack.as_bytes(), needle.as_bytes()));
- }
-}
diff --git a/vendor/memchr/src/arch/generic/memchr.rs b/vendor/memchr/src/arch/generic/memchr.rs
deleted file mode 100644
index 580b3cc..0000000
--- a/vendor/memchr/src/arch/generic/memchr.rs
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*!
-Generic crate-internal routines for the `memchr` family of functions.
-*/
-
-// What follows is a vector algorithm generic over the specific vector
-// type to detect the position of one, two or three needles in a haystack.
-// From what I know, this is a "classic" algorithm, although I don't
-// believe it has been published in any peer reviewed journal. I believe
-// it can be found in places like glibc and Go's standard library. It
-// appears to be well known and is elaborated on in more detail here:
-// https://gms.tf/stdfind-and-memchr-optimizations.html
-//
-// While the routine below is fairly long and perhaps intimidating, the basic
-// idea is actually very simple and can be expressed straight-forwardly in
-// pseudo code. The psuedo code below is written for 128 bit vectors, but the
-// actual code below works for anything that implements the Vector trait.
-//
-// needle = (n1 << 15) | (n1 << 14) | ... | (n1 << 1) | n1
-// // Note: shift amount is in bytes
-//
-// while i <= haystack.len() - 16:
-// // A 16 byte vector. Each byte in chunk corresponds to a byte in
-// // the haystack.
-// chunk = haystack[i:i+16]
-// // Compare bytes in needle with bytes in chunk. The result is a 16
-// // byte chunk where each byte is 0xFF if the corresponding bytes
-// // in needle and chunk were equal, or 0x00 otherwise.
-// eqs = cmpeq(needle, chunk)
-// // Return a 32 bit integer where the most significant 16 bits
-// // are always 0 and the lower 16 bits correspond to whether the
-// // most significant bit in the correspond byte in `eqs` is set.
-// // In other words, `mask as u16` has bit i set if and only if
-// // needle[i] == chunk[i].
-// mask = movemask(eqs)
-//
-// // Mask is 0 if there is no match, and non-zero otherwise.
-// if mask != 0:
-// // trailing_zeros tells us the position of the least significant
-// // bit that is set.
-// return i + trailing_zeros(mask)
-//
-// // haystack length may not be a multiple of 16, so search the rest.
-// while i < haystack.len():
-// if haystack[i] == n1:
-// return i
-//
-// // No match found.
-// return NULL
-//
-// In fact, we could loosely translate the above code to Rust line-for-line
-// and it would be a pretty fast algorithm. But, we pull out all the stops
-// to go as fast as possible:
-//
-// 1. We use aligned loads. That is, we do some finagling to make sure our
-// primary loop not only proceeds in increments of 16 bytes, but that
-// the address of haystack's pointer that we dereference is aligned to
-// 16 bytes. 16 is a magic number here because it is the size of SSE2
-// 128-bit vector. (For the AVX2 algorithm, 32 is the magic number.)
-// Therefore, to get aligned loads, our pointer's address must be evenly
-// divisible by 16.
-// 2. Our primary loop proceeds 64 bytes at a time instead of 16. It's
-// kind of like loop unrolling, but we combine the equality comparisons
-// using a vector OR such that we only need to extract a single mask to
-// determine whether a match exists or not. If so, then we do some
-// book-keeping to determine the precise location but otherwise mush on.
-// 3. We use our "chunk" comparison routine in as many places as possible,
-// even if it means using unaligned loads. In particular, if haystack
-// starts with an unaligned address, then we do an unaligned load to
-// search the first 16 bytes. We then start our primary loop at the
-// smallest subsequent aligned address, which will actually overlap with
-// previously searched bytes. But we're OK with that. We do a similar
-// dance at the end of our primary loop. Finally, to avoid a
-// byte-at-a-time loop at the end, we do a final 16 byte unaligned load
-// that may overlap with a previous load. This is OK because it converts
-// a loop into a small number of very fast vector instructions. The overlap
-// is OK because we know the place where the overlap occurs does not
-// contain a match.
-//
-// And that's pretty all there is to it. Note that since the below is
-// generic and since it's meant to be inlined into routines with a
-// `#[target_feature(enable = "...")]` annotation, we must mark all routines as
-// both unsafe and `#[inline(always)]`.
-//
-// The fact that the code below is generic does somewhat inhibit us. For
-// example, I've noticed that introducing an unlineable `#[cold]` function to
-// handle the match case in the loop generates tighter assembly, but there is
-// no way to do this in the generic code below because the generic code doesn't
-// know what `target_feature` annotation to apply to the unlineable function.
-// We could make such functions part of the `Vector` trait, but we instead live
-// with the slightly sub-optimal codegen for now since it doesn't seem to have
-// a noticeable perf difference.
-
-use crate::{
- ext::Pointer,
- vector::{MoveMask, Vector},
-};
-
-/// Finds all occurrences of a single byte in a haystack.
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct One<V> {
- s1: u8,
- v1: V,
-}
-
-impl<V: Vector> One<V> {
- /// The number of bytes we examine per each iteration of our search loop.
- const LOOP_SIZE: usize = 4 * V::BYTES;
-
- /// Create a new searcher that finds occurrences of the byte given.
- #[inline(always)]
- pub(crate) unsafe fn new(needle: u8) -> One<V> {
- One { s1: needle, v1: V::splat(needle) }
- }
-
- /// Returns the needle given to `One::new`.
- #[inline(always)]
- pub(crate) fn needle1(&self) -> u8 {
- self.s1
- }
-
- /// Return a pointer to the first occurrence of the needle in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// # Safety
- ///
- /// * It must be the case that `start < end` and that the distance between
- /// them is at least equal to `V::BYTES`. That is, it must always be valid
- /// to do at least an unaligned load of `V` at `start`.
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- #[inline(always)]
- pub(crate) unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- // If we want to support vectors bigger than 256 bits, we probably
- // need to move up to using a u64 for the masks used below. Currently
- // they are 32 bits, which means we're SOL for vectors that need masks
- // bigger than 32 bits. Overall unclear until there's a use case.
- debug_assert!(V::BYTES <= 32, "vector cannot be bigger than 32 bytes");
-
- let topos = V::Mask::first_offset;
- let len = end.distance(start);
- debug_assert!(
- len >= V::BYTES,
- "haystack has length {}, but must be at least {}",
- len,
- V::BYTES
- );
-
- // Search a possibly unaligned chunk at `start`. This covers any part
- // of the haystack prior to where aligned loads can start.
- if let Some(cur) = self.search_chunk(start, topos) {
- return Some(cur);
- }
- // Set `cur` to the first V-aligned pointer greater than `start`.
- let mut cur = start.add(V::BYTES - (start.as_usize() & V::ALIGN));
- debug_assert!(cur > start && end.sub(V::BYTES) >= start);
- if len >= Self::LOOP_SIZE {
- while cur <= end.sub(Self::LOOP_SIZE) {
- debug_assert_eq!(0, cur.as_usize() % V::BYTES);
-
- let a = V::load_aligned(cur);
- let b = V::load_aligned(cur.add(1 * V::BYTES));
- let c = V::load_aligned(cur.add(2 * V::BYTES));
- let d = V::load_aligned(cur.add(3 * V::BYTES));
- let eqa = self.v1.cmpeq(a);
- let eqb = self.v1.cmpeq(b);
- let eqc = self.v1.cmpeq(c);
- let eqd = self.v1.cmpeq(d);
- let or1 = eqa.or(eqb);
- let or2 = eqc.or(eqd);
- let or3 = or1.or(or2);
- if or3.movemask_will_have_non_zero() {
- let mask = eqa.movemask();
- if mask.has_non_zero() {
- return Some(cur.add(topos(mask)));
- }
-
- let mask = eqb.movemask();
- if mask.has_non_zero() {
- return Some(cur.add(1 * V::BYTES).add(topos(mask)));
- }
-
- let mask = eqc.movemask();
- if mask.has_non_zero() {
- return Some(cur.add(2 * V::BYTES).add(topos(mask)));
- }
-
- let mask = eqd.movemask();
- debug_assert!(mask.has_non_zero());
- return Some(cur.add(3 * V::BYTES).add(topos(mask)));
- }
- cur = cur.add(Self::LOOP_SIZE);
- }
- }
- // Handle any leftovers after the aligned loop above. We use unaligned
- // loads here, but I believe we are guaranteed that they are aligned
- // since `cur` is aligned.
- while cur <= end.sub(V::BYTES) {
- debug_assert!(end.distance(cur) >= V::BYTES);
- if let Some(cur) = self.search_chunk(cur, topos) {
- return Some(cur);
- }
- cur = cur.add(V::BYTES);
- }
- // Finally handle any remaining bytes less than the size of V. In this
- // case, our pointer may indeed be unaligned and the load may overlap
- // with the previous one. But that's okay since we know the previous
- // load didn't lead to a match (otherwise we wouldn't be here).
- if cur < end {
- debug_assert!(end.distance(cur) < V::BYTES);
- cur = cur.sub(V::BYTES - end.distance(cur));
- debug_assert_eq!(end.distance(cur), V::BYTES);
- return self.search_chunk(cur, topos);
- }
- None
- }
-
- /// Return a pointer to the last occurrence of the needle in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// # Safety
- ///
- /// * It must be the case that `start < end` and that the distance between
- /// them is at least equal to `V::BYTES`. That is, it must always be valid
- /// to do at least an unaligned load of `V` at `start`.
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- #[inline(always)]
- pub(crate) unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- // If we want to support vectors bigger than 256 bits, we probably
- // need to move up to using a u64 for the masks used below. Currently
- // they are 32 bits, which means we're SOL for vectors that need masks
- // bigger than 32 bits. Overall unclear until there's a use case.
- debug_assert!(V::BYTES <= 32, "vector cannot be bigger than 32 bytes");
-
- let topos = V::Mask::last_offset;
- let len = end.distance(start);
- debug_assert!(
- len >= V::BYTES,
- "haystack has length {}, but must be at least {}",
- len,
- V::BYTES
- );
-
- if let Some(cur) = self.search_chunk(end.sub(V::BYTES), topos) {
- return Some(cur);
- }
- let mut cur = end.sub(end.as_usize() & V::ALIGN);
- debug_assert!(start <= cur && cur <= end);
- if len >= Self::LOOP_SIZE {
- while cur >= start.add(Self::LOOP_SIZE) {
- debug_assert_eq!(0, cur.as_usize() % V::BYTES);
-
- cur = cur.sub(Self::LOOP_SIZE);
- let a = V::load_aligned(cur);
- let b = V::load_aligned(cur.add(1 * V::BYTES));
- let c = V::load_aligned(cur.add(2 * V::BYTES));
- let d = V::load_aligned(cur.add(3 * V::BYTES));
- let eqa = self.v1.cmpeq(a);
- let eqb = self.v1.cmpeq(b);
- let eqc = self.v1.cmpeq(c);
- let eqd = self.v1.cmpeq(d);
- let or1 = eqa.or(eqb);
- let or2 = eqc.or(eqd);
- let or3 = or1.or(or2);
- if or3.movemask_will_have_non_zero() {
- let mask = eqd.movemask();
- if mask.has_non_zero() {
- return Some(cur.add(3 * V::BYTES).add(topos(mask)));
- }
-
- let mask = eqc.movemask();
- if mask.has_non_zero() {
- return Some(cur.add(2 * V::BYTES).add(topos(mask)));
- }
-
- let mask = eqb.movemask();
- if mask.has_non_zero() {
- return Some(cur.add(1 * V::BYTES).add(topos(mask)));
- }
-
- let mask = eqa.movemask();
- debug_assert!(mask.has_non_zero());
- return Some(cur.add(topos(mask)));
- }
- }
- }
- while cur >= start.add(V::BYTES) {
- debug_assert!(cur.distance(start) >= V::BYTES);
- cur = cur.sub(V::BYTES);
- if let Some(cur) = self.search_chunk(cur, topos) {
- return Some(cur);
- }
- }
- if cur > start {
- debug_assert!(cur.distance(start) < V::BYTES);
- return self.search_chunk(start, topos);
- }
- None
- }
-
- /// Return a count of all matching bytes in the given haystack.
- ///
- /// # Safety
- ///
- /// * It must be the case that `start < end` and that the distance between
- /// them is at least equal to `V::BYTES`. That is, it must always be valid
- /// to do at least an unaligned load of `V` at `start`.
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- #[inline(always)]
- pub(crate) unsafe fn count_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> usize {
- debug_assert!(V::BYTES <= 32, "vector cannot be bigger than 32 bytes");
-
- let confirm = |b| b == self.needle1();
- let len = end.distance(start);
- debug_assert!(
- len >= V::BYTES,
- "haystack has length {}, but must be at least {}",
- len,
- V::BYTES
- );
-
- // Set `cur` to the first V-aligned pointer greater than `start`.
- let mut cur = start.add(V::BYTES - (start.as_usize() & V::ALIGN));
- // Count any matching bytes before we start our aligned loop.
- let mut count = count_byte_by_byte(start, cur, confirm);
- debug_assert!(cur > start && end.sub(V::BYTES) >= start);
- if len >= Self::LOOP_SIZE {
- while cur <= end.sub(Self::LOOP_SIZE) {
- debug_assert_eq!(0, cur.as_usize() % V::BYTES);
-
- let a = V::load_aligned(cur);
- let b = V::load_aligned(cur.add(1 * V::BYTES));
- let c = V::load_aligned(cur.add(2 * V::BYTES));
- let d = V::load_aligned(cur.add(3 * V::BYTES));
- let eqa = self.v1.cmpeq(a);
- let eqb = self.v1.cmpeq(b);
- let eqc = self.v1.cmpeq(c);
- let eqd = self.v1.cmpeq(d);
- count += eqa.movemask().count_ones();
- count += eqb.movemask().count_ones();
- count += eqc.movemask().count_ones();
- count += eqd.movemask().count_ones();
- cur = cur.add(Self::LOOP_SIZE);
- }
- }
- // Handle any leftovers after the aligned loop above. We use unaligned
- // loads here, but I believe we are guaranteed that they are aligned
- // since `cur` is aligned.
- while cur <= end.sub(V::BYTES) {
- debug_assert!(end.distance(cur) >= V::BYTES);
- let chunk = V::load_unaligned(cur);
- count += self.v1.cmpeq(chunk).movemask().count_ones();
- cur = cur.add(V::BYTES);
- }
- // And finally count any leftovers that weren't caught above.
- count += count_byte_by_byte(cur, end, confirm);
- count
- }
-
- /// Search `V::BYTES` starting at `cur` via an unaligned load.
- ///
- /// `mask_to_offset` should be a function that converts a `movemask` to
- /// an offset such that `cur.add(offset)` corresponds to a pointer to the
- /// match location if one is found. Generally it is expected to use either
- /// `mask_to_first_offset` or `mask_to_last_offset`, depending on whether
- /// one is implementing a forward or reverse search, respectively.
- ///
- /// # Safety
- ///
- /// `cur` must be a valid pointer and it must be valid to do an unaligned
- /// load of size `V::BYTES` at `cur`.
- #[inline(always)]
- unsafe fn search_chunk(
- &self,
- cur: *const u8,
- mask_to_offset: impl Fn(V::Mask) -> usize,
- ) -> Option<*const u8> {
- let chunk = V::load_unaligned(cur);
- let mask = self.v1.cmpeq(chunk).movemask();
- if mask.has_non_zero() {
- Some(cur.add(mask_to_offset(mask)))
- } else {
- None
- }
- }
-}
-
-/// Finds all occurrences of two bytes in a haystack.
-///
-/// That is, this reports matches of one of two possible bytes. For example,
-/// searching for `a` or `b` in `afoobar` would report matches at offsets `0`,
-/// `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct Two<V> {
- s1: u8,
- s2: u8,
- v1: V,
- v2: V,
-}
-
-impl<V: Vector> Two<V> {
- /// The number of bytes we examine per each iteration of our search loop.
- const LOOP_SIZE: usize = 2 * V::BYTES;
-
- /// Create a new searcher that finds occurrences of the byte given.
- #[inline(always)]
- pub(crate) unsafe fn new(needle1: u8, needle2: u8) -> Two<V> {
- Two {
- s1: needle1,
- s2: needle2,
- v1: V::splat(needle1),
- v2: V::splat(needle2),
- }
- }
-
- /// Returns the first needle given to `Two::new`.
- #[inline(always)]
- pub(crate) fn needle1(&self) -> u8 {
- self.s1
- }
-
- /// Returns the second needle given to `Two::new`.
- #[inline(always)]
- pub(crate) fn needle2(&self) -> u8 {
- self.s2
- }
-
- /// Return a pointer to the first occurrence of one of the needles in the
- /// given haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// # Safety
- ///
- /// * It must be the case that `start < end` and that the distance between
- /// them is at least equal to `V::BYTES`. That is, it must always be valid
- /// to do at least an unaligned load of `V` at `start`.
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- #[inline(always)]
- pub(crate) unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- // If we want to support vectors bigger than 256 bits, we probably
- // need to move up to using a u64 for the masks used below. Currently
- // they are 32 bits, which means we're SOL for vectors that need masks
- // bigger than 32 bits. Overall unclear until there's a use case.
- debug_assert!(V::BYTES <= 32, "vector cannot be bigger than 32 bytes");
-
- let topos = V::Mask::first_offset;
- let len = end.distance(start);
- debug_assert!(
- len >= V::BYTES,
- "haystack has length {}, but must be at least {}",
- len,
- V::BYTES
- );
-
- // Search a possibly unaligned chunk at `start`. This covers any part
- // of the haystack prior to where aligned loads can start.
- if let Some(cur) = self.search_chunk(start, topos) {
- return Some(cur);
- }
- // Set `cur` to the first V-aligned pointer greater than `start`.
- let mut cur = start.add(V::BYTES - (start.as_usize() & V::ALIGN));
- debug_assert!(cur > start && end.sub(V::BYTES) >= start);
- if len >= Self::LOOP_SIZE {
- while cur <= end.sub(Self::LOOP_SIZE) {
- debug_assert_eq!(0, cur.as_usize() % V::BYTES);
-
- let a = V::load_aligned(cur);
- let b = V::load_aligned(cur.add(V::BYTES));
- let eqa1 = self.v1.cmpeq(a);
- let eqb1 = self.v1.cmpeq(b);
- let eqa2 = self.v2.cmpeq(a);
- let eqb2 = self.v2.cmpeq(b);
- let or1 = eqa1.or(eqb1);
- let or2 = eqa2.or(eqb2);
- let or3 = or1.or(or2);
- if or3.movemask_will_have_non_zero() {
- let mask = eqa1.movemask().or(eqa2.movemask());
- if mask.has_non_zero() {
- return Some(cur.add(topos(mask)));
- }
-
- let mask = eqb1.movemask().or(eqb2.movemask());
- debug_assert!(mask.has_non_zero());
- return Some(cur.add(V::BYTES).add(topos(mask)));
- }
- cur = cur.add(Self::LOOP_SIZE);
- }
- }
- // Handle any leftovers after the aligned loop above. We use unaligned
- // loads here, but I believe we are guaranteed that they are aligned
- // since `cur` is aligned.
- while cur <= end.sub(V::BYTES) {
- debug_assert!(end.distance(cur) >= V::BYTES);
- if let Some(cur) = self.search_chunk(cur, topos) {
- return Some(cur);
- }
- cur = cur.add(V::BYTES);
- }
- // Finally handle any remaining bytes less than the size of V. In this
- // case, our pointer may indeed be unaligned and the load may overlap
- // with the previous one. But that's okay since we know the previous
- // load didn't lead to a match (otherwise we wouldn't be here).
- if cur < end {
- debug_assert!(end.distance(cur) < V::BYTES);
- cur = cur.sub(V::BYTES - end.distance(cur));
- debug_assert_eq!(end.distance(cur), V::BYTES);
- return self.search_chunk(cur, topos);
- }
- None
- }
-
- /// Return a pointer to the last occurrence of the needle in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// # Safety
- ///
- /// * It must be the case that `start < end` and that the distance between
- /// them is at least equal to `V::BYTES`. That is, it must always be valid
- /// to do at least an unaligned load of `V` at `start`.
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- #[inline(always)]
- pub(crate) unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- // If we want to support vectors bigger than 256 bits, we probably
- // need to move up to using a u64 for the masks used below. Currently
- // they are 32 bits, which means we're SOL for vectors that need masks
- // bigger than 32 bits. Overall unclear until there's a use case.
- debug_assert!(V::BYTES <= 32, "vector cannot be bigger than 32 bytes");
-
- let topos = V::Mask::last_offset;
- let len = end.distance(start);
- debug_assert!(
- len >= V::BYTES,
- "haystack has length {}, but must be at least {}",
- len,
- V::BYTES
- );
-
- if let Some(cur) = self.search_chunk(end.sub(V::BYTES), topos) {
- return Some(cur);
- }
- let mut cur = end.sub(end.as_usize() & V::ALIGN);
- debug_assert!(start <= cur && cur <= end);
- if len >= Self::LOOP_SIZE {
- while cur >= start.add(Self::LOOP_SIZE) {
- debug_assert_eq!(0, cur.as_usize() % V::BYTES);
-
- cur = cur.sub(Self::LOOP_SIZE);
- let a = V::load_aligned(cur);
- let b = V::load_aligned(cur.add(V::BYTES));
- let eqa1 = self.v1.cmpeq(a);
- let eqb1 = self.v1.cmpeq(b);
- let eqa2 = self.v2.cmpeq(a);
- let eqb2 = self.v2.cmpeq(b);
- let or1 = eqa1.or(eqb1);
- let or2 = eqa2.or(eqb2);
- let or3 = or1.or(or2);
- if or3.movemask_will_have_non_zero() {
- let mask = eqb1.movemask().or(eqb2.movemask());
- if mask.has_non_zero() {
- return Some(cur.add(V::BYTES).add(topos(mask)));
- }
-
- let mask = eqa1.movemask().or(eqa2.movemask());
- debug_assert!(mask.has_non_zero());
- return Some(cur.add(topos(mask)));
- }
- }
- }
- while cur >= start.add(V::BYTES) {
- debug_assert!(cur.distance(start) >= V::BYTES);
- cur = cur.sub(V::BYTES);
- if let Some(cur) = self.search_chunk(cur, topos) {
- return Some(cur);
- }
- }
- if cur > start {
- debug_assert!(cur.distance(start) < V::BYTES);
- return self.search_chunk(start, topos);
- }
- None
- }
-
- /// Search `V::BYTES` starting at `cur` via an unaligned load.
- ///
- /// `mask_to_offset` should be a function that converts a `movemask` to
- /// an offset such that `cur.add(offset)` corresponds to a pointer to the
- /// match location if one is found. Generally it is expected to use either
- /// `mask_to_first_offset` or `mask_to_last_offset`, depending on whether
- /// one is implementing a forward or reverse search, respectively.
- ///
- /// # Safety
- ///
- /// `cur` must be a valid pointer and it must be valid to do an unaligned
- /// load of size `V::BYTES` at `cur`.
- #[inline(always)]
- unsafe fn search_chunk(
- &self,
- cur: *const u8,
- mask_to_offset: impl Fn(V::Mask) -> usize,
- ) -> Option<*const u8> {
- let chunk = V::load_unaligned(cur);
- let eq1 = self.v1.cmpeq(chunk);
- let eq2 = self.v2.cmpeq(chunk);
- let mask = eq1.or(eq2).movemask();
- if mask.has_non_zero() {
- let mask1 = eq1.movemask();
- let mask2 = eq2.movemask();
- Some(cur.add(mask_to_offset(mask1.or(mask2))))
- } else {
- None
- }
- }
-}
-
-/// Finds all occurrences of two bytes in a haystack.
-///
-/// That is, this reports matches of one of two possible bytes. For example,
-/// searching for `a` or `b` in `afoobar` would report matches at offsets `0`,
-/// `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct Three<V> {
- s1: u8,
- s2: u8,
- s3: u8,
- v1: V,
- v2: V,
- v3: V,
-}
-
-impl<V: Vector> Three<V> {
- /// The number of bytes we examine per each iteration of our search loop.
- const LOOP_SIZE: usize = 2 * V::BYTES;
-
- /// Create a new searcher that finds occurrences of the byte given.
- #[inline(always)]
- pub(crate) unsafe fn new(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- ) -> Three<V> {
- Three {
- s1: needle1,
- s2: needle2,
- s3: needle3,
- v1: V::splat(needle1),
- v2: V::splat(needle2),
- v3: V::splat(needle3),
- }
- }
-
- /// Returns the first needle given to `Three::new`.
- #[inline(always)]
- pub(crate) fn needle1(&self) -> u8 {
- self.s1
- }
-
- /// Returns the second needle given to `Three::new`.
- #[inline(always)]
- pub(crate) fn needle2(&self) -> u8 {
- self.s2
- }
-
- /// Returns the third needle given to `Three::new`.
- #[inline(always)]
- pub(crate) fn needle3(&self) -> u8 {
- self.s3
- }
-
- /// Return a pointer to the first occurrence of one of the needles in the
- /// given haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// # Safety
- ///
- /// * It must be the case that `start < end` and that the distance between
- /// them is at least equal to `V::BYTES`. That is, it must always be valid
- /// to do at least an unaligned load of `V` at `start`.
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- #[inline(always)]
- pub(crate) unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- // If we want to support vectors bigger than 256 bits, we probably
- // need to move up to using a u64 for the masks used below. Currently
- // they are 32 bits, which means we're SOL for vectors that need masks
- // bigger than 32 bits. Overall unclear until there's a use case.
- debug_assert!(V::BYTES <= 32, "vector cannot be bigger than 32 bytes");
-
- let topos = V::Mask::first_offset;
- let len = end.distance(start);
- debug_assert!(
- len >= V::BYTES,
- "haystack has length {}, but must be at least {}",
- len,
- V::BYTES
- );
-
- // Search a possibly unaligned chunk at `start`. This covers any part
- // of the haystack prior to where aligned loads can start.
- if let Some(cur) = self.search_chunk(start, topos) {
- return Some(cur);
- }
- // Set `cur` to the first V-aligned pointer greater than `start`.
- let mut cur = start.add(V::BYTES - (start.as_usize() & V::ALIGN));
- debug_assert!(cur > start && end.sub(V::BYTES) >= start);
- if len >= Self::LOOP_SIZE {
- while cur <= end.sub(Self::LOOP_SIZE) {
- debug_assert_eq!(0, cur.as_usize() % V::BYTES);
-
- let a = V::load_aligned(cur);
- let b = V::load_aligned(cur.add(V::BYTES));
- let eqa1 = self.v1.cmpeq(a);
- let eqb1 = self.v1.cmpeq(b);
- let eqa2 = self.v2.cmpeq(a);
- let eqb2 = self.v2.cmpeq(b);
- let eqa3 = self.v3.cmpeq(a);
- let eqb3 = self.v3.cmpeq(b);
- let or1 = eqa1.or(eqb1);
- let or2 = eqa2.or(eqb2);
- let or3 = eqa3.or(eqb3);
- let or4 = or1.or(or2);
- let or5 = or3.or(or4);
- if or5.movemask_will_have_non_zero() {
- let mask = eqa1
- .movemask()
- .or(eqa2.movemask())
- .or(eqa3.movemask());
- if mask.has_non_zero() {
- return Some(cur.add(topos(mask)));
- }
-
- let mask = eqb1
- .movemask()
- .or(eqb2.movemask())
- .or(eqb3.movemask());
- debug_assert!(mask.has_non_zero());
- return Some(cur.add(V::BYTES).add(topos(mask)));
- }
- cur = cur.add(Self::LOOP_SIZE);
- }
- }
- // Handle any leftovers after the aligned loop above. We use unaligned
- // loads here, but I believe we are guaranteed that they are aligned
- // since `cur` is aligned.
- while cur <= end.sub(V::BYTES) {
- debug_assert!(end.distance(cur) >= V::BYTES);
- if let Some(cur) = self.search_chunk(cur, topos) {
- return Some(cur);
- }
- cur = cur.add(V::BYTES);
- }
- // Finally handle any remaining bytes less than the size of V. In this
- // case, our pointer may indeed be unaligned and the load may overlap
- // with the previous one. But that's okay since we know the previous
- // load didn't lead to a match (otherwise we wouldn't be here).
- if cur < end {
- debug_assert!(end.distance(cur) < V::BYTES);
- cur = cur.sub(V::BYTES - end.distance(cur));
- debug_assert_eq!(end.distance(cur), V::BYTES);
- return self.search_chunk(cur, topos);
- }
- None
- }
-
- /// Return a pointer to the last occurrence of the needle in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// # Safety
- ///
- /// * It must be the case that `start < end` and that the distance between
- /// them is at least equal to `V::BYTES`. That is, it must always be valid
- /// to do at least an unaligned load of `V` at `start`.
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- #[inline(always)]
- pub(crate) unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- // If we want to support vectors bigger than 256 bits, we probably
- // need to move up to using a u64 for the masks used below. Currently
- // they are 32 bits, which means we're SOL for vectors that need masks
- // bigger than 32 bits. Overall unclear until there's a use case.
- debug_assert!(V::BYTES <= 32, "vector cannot be bigger than 32 bytes");
-
- let topos = V::Mask::last_offset;
- let len = end.distance(start);
- debug_assert!(
- len >= V::BYTES,
- "haystack has length {}, but must be at least {}",
- len,
- V::BYTES
- );
-
- if let Some(cur) = self.search_chunk(end.sub(V::BYTES), topos) {
- return Some(cur);
- }
- let mut cur = end.sub(end.as_usize() & V::ALIGN);
- debug_assert!(start <= cur && cur <= end);
- if len >= Self::LOOP_SIZE {
- while cur >= start.add(Self::LOOP_SIZE) {
- debug_assert_eq!(0, cur.as_usize() % V::BYTES);
-
- cur = cur.sub(Self::LOOP_SIZE);
- let a = V::load_aligned(cur);
- let b = V::load_aligned(cur.add(V::BYTES));
- let eqa1 = self.v1.cmpeq(a);
- let eqb1 = self.v1.cmpeq(b);
- let eqa2 = self.v2.cmpeq(a);
- let eqb2 = self.v2.cmpeq(b);
- let eqa3 = self.v3.cmpeq(a);
- let eqb3 = self.v3.cmpeq(b);
- let or1 = eqa1.or(eqb1);
- let or2 = eqa2.or(eqb2);
- let or3 = eqa3.or(eqb3);
- let or4 = or1.or(or2);
- let or5 = or3.or(or4);
- if or5.movemask_will_have_non_zero() {
- let mask = eqb1
- .movemask()
- .or(eqb2.movemask())
- .or(eqb3.movemask());
- if mask.has_non_zero() {
- return Some(cur.add(V::BYTES).add(topos(mask)));
- }
-
- let mask = eqa1
- .movemask()
- .or(eqa2.movemask())
- .or(eqa3.movemask());
- debug_assert!(mask.has_non_zero());
- return Some(cur.add(topos(mask)));
- }
- }
- }
- while cur >= start.add(V::BYTES) {
- debug_assert!(cur.distance(start) >= V::BYTES);
- cur = cur.sub(V::BYTES);
- if let Some(cur) = self.search_chunk(cur, topos) {
- return Some(cur);
- }
- }
- if cur > start {
- debug_assert!(cur.distance(start) < V::BYTES);
- return self.search_chunk(start, topos);
- }
- None
- }
-
- /// Search `V::BYTES` starting at `cur` via an unaligned load.
- ///
- /// `mask_to_offset` should be a function that converts a `movemask` to
- /// an offset such that `cur.add(offset)` corresponds to a pointer to the
- /// match location if one is found. Generally it is expected to use either
- /// `mask_to_first_offset` or `mask_to_last_offset`, depending on whether
- /// one is implementing a forward or reverse search, respectively.
- ///
- /// # Safety
- ///
- /// `cur` must be a valid pointer and it must be valid to do an unaligned
- /// load of size `V::BYTES` at `cur`.
- #[inline(always)]
- unsafe fn search_chunk(
- &self,
- cur: *const u8,
- mask_to_offset: impl Fn(V::Mask) -> usize,
- ) -> Option<*const u8> {
- let chunk = V::load_unaligned(cur);
- let eq1 = self.v1.cmpeq(chunk);
- let eq2 = self.v2.cmpeq(chunk);
- let eq3 = self.v3.cmpeq(chunk);
- let mask = eq1.or(eq2).or(eq3).movemask();
- if mask.has_non_zero() {
- let mask1 = eq1.movemask();
- let mask2 = eq2.movemask();
- let mask3 = eq3.movemask();
- Some(cur.add(mask_to_offset(mask1.or(mask2).or(mask3))))
- } else {
- None
- }
- }
-}
-
-/// An iterator over all occurrences of a set of bytes in a haystack.
-///
-/// This iterator implements the routines necessary to provide a
-/// `DoubleEndedIterator` impl, which means it can also be used to find
-/// occurrences in reverse order.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'h` refers to the lifetime of the haystack being searched.
-///
-/// This type is intended to be used to implement all iterators for the
-/// `memchr` family of functions. It handles a tiny bit of marginally tricky
-/// raw pointer math, but otherwise expects the caller to provide `find_raw`
-/// and `rfind_raw` routines for each call of `next` and `next_back`,
-/// respectively.
-#[derive(Clone, Debug)]
-pub(crate) struct Iter<'h> {
- /// The original starting point into the haystack. We use this to convert
- /// pointers to offsets.
- original_start: *const u8,
- /// The current starting point into the haystack. That is, where the next
- /// search will begin.
- start: *const u8,
- /// The current ending point into the haystack. That is, where the next
- /// reverse search will begin.
- end: *const u8,
- /// A marker for tracking the lifetime of the start/cur_start/cur_end
- /// pointers above, which all point into the haystack.
- haystack: core::marker::PhantomData<&'h [u8]>,
-}
-
-// SAFETY: Iter contains no shared references to anything that performs any
-// interior mutations. Also, the lifetime guarantees that Iter will not outlive
-// the haystack.
-unsafe impl<'h> Send for Iter<'h> {}
-
-// SAFETY: Iter perform no interior mutations, therefore no explicit
-// synchronization is necessary. Also, the lifetime guarantees that Iter will
-// not outlive the haystack.
-unsafe impl<'h> Sync for Iter<'h> {}
-
-impl<'h> Iter<'h> {
- /// Create a new generic memchr iterator.
- #[inline(always)]
- pub(crate) fn new(haystack: &'h [u8]) -> Iter<'h> {
- Iter {
- original_start: haystack.as_ptr(),
- start: haystack.as_ptr(),
- end: haystack.as_ptr().wrapping_add(haystack.len()),
- haystack: core::marker::PhantomData,
- }
- }
-
- /// Returns the next occurrence in the forward direction.
- ///
- /// # Safety
- ///
- /// Callers must ensure that if a pointer is returned from the closure
- /// provided, then it must be greater than or equal to the start pointer
- /// and less than the end pointer.
- #[inline(always)]
- pub(crate) unsafe fn next(
- &mut self,
- mut find_raw: impl FnMut(*const u8, *const u8) -> Option<*const u8>,
- ) -> Option<usize> {
- // SAFETY: Pointers are derived directly from the same &[u8] haystack.
- // We only ever modify start/end corresponding to a matching offset
- // found between start and end. Thus all changes to start/end maintain
- // our safety requirements.
- //
- // The only other assumption we rely on is that the pointer returned
- // by `find_raw` satisfies `self.start <= found < self.end`, and that
- // safety contract is forwarded to the caller.
- let found = find_raw(self.start, self.end)?;
- let result = found.distance(self.original_start);
- self.start = found.add(1);
- Some(result)
- }
-
- /// Returns the number of remaining elements in this iterator.
- #[inline(always)]
- pub(crate) fn count(
- self,
- mut count_raw: impl FnMut(*const u8, *const u8) -> usize,
- ) -> usize {
- // SAFETY: Pointers are derived directly from the same &[u8] haystack.
- // We only ever modify start/end corresponding to a matching offset
- // found between start and end. Thus all changes to start/end maintain
- // our safety requirements.
- count_raw(self.start, self.end)
- }
-
- /// Returns the next occurrence in reverse.
- ///
- /// # Safety
- ///
- /// Callers must ensure that if a pointer is returned from the closure
- /// provided, then it must be greater than or equal to the start pointer
- /// and less than the end pointer.
- #[inline(always)]
- pub(crate) unsafe fn next_back(
- &mut self,
- mut rfind_raw: impl FnMut(*const u8, *const u8) -> Option<*const u8>,
- ) -> Option<usize> {
- // SAFETY: Pointers are derived directly from the same &[u8] haystack.
- // We only ever modify start/end corresponding to a matching offset
- // found between start and end. Thus all changes to start/end maintain
- // our safety requirements.
- //
- // The only other assumption we rely on is that the pointer returned
- // by `rfind_raw` satisfies `self.start <= found < self.end`, and that
- // safety contract is forwarded to the caller.
- let found = rfind_raw(self.start, self.end)?;
- let result = found.distance(self.original_start);
- self.end = found;
- Some(result)
- }
-
- /// Provides an implementation of `Iterator::size_hint`.
- #[inline(always)]
- pub(crate) fn size_hint(&self) -> (usize, Option<usize>) {
- (0, Some(self.end.as_usize().saturating_sub(self.start.as_usize())))
- }
-}
-
-/// Search a slice using a function that operates on raw pointers.
-///
-/// Given a function to search a contiguous sequence of memory for the location
-/// of a non-empty set of bytes, this will execute that search on a slice of
-/// bytes. The pointer returned by the given function will be converted to an
-/// offset relative to the starting point of the given slice. That is, if a
-/// match is found, the offset returned by this routine is guaranteed to be a
-/// valid index into `haystack`.
-///
-/// Callers may use this for a forward or reverse search.
-///
-/// # Safety
-///
-/// Callers must ensure that if a pointer is returned by `find_raw`, then the
-/// pointer must be greater than or equal to the starting pointer and less than
-/// the end pointer.
-#[inline(always)]
-pub(crate) unsafe fn search_slice_with_raw(
- haystack: &[u8],
- mut find_raw: impl FnMut(*const u8, *const u8) -> Option<*const u8>,
-) -> Option<usize> {
- // SAFETY: We rely on `find_raw` to return a correct and valid pointer, but
- // otherwise, `start` and `end` are valid due to the guarantees provided by
- // a &[u8].
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- let found = find_raw(start, end)?;
- Some(found.distance(start))
-}
-
-/// Performs a forward byte-at-a-time loop until either `ptr >= end_ptr` or
-/// until `confirm(*ptr)` returns `true`. If the former occurs, then `None` is
-/// returned. If the latter occurs, then the pointer at which `confirm` returns
-/// `true` is returned.
-///
-/// # Safety
-///
-/// Callers must provide valid pointers and they must satisfy `start_ptr <=
-/// ptr` and `ptr <= end_ptr`.
-#[inline(always)]
-pub(crate) unsafe fn fwd_byte_by_byte<F: Fn(u8) -> bool>(
- start: *const u8,
- end: *const u8,
- confirm: F,
-) -> Option<*const u8> {
- debug_assert!(start <= end);
- let mut ptr = start;
- while ptr < end {
- if confirm(*ptr) {
- return Some(ptr);
- }
- ptr = ptr.offset(1);
- }
- None
-}
-
-/// Performs a reverse byte-at-a-time loop until either `ptr < start_ptr` or
-/// until `confirm(*ptr)` returns `true`. If the former occurs, then `None` is
-/// returned. If the latter occurs, then the pointer at which `confirm` returns
-/// `true` is returned.
-///
-/// # Safety
-///
-/// Callers must provide valid pointers and they must satisfy `start_ptr <=
-/// ptr` and `ptr <= end_ptr`.
-#[inline(always)]
-pub(crate) unsafe fn rev_byte_by_byte<F: Fn(u8) -> bool>(
- start: *const u8,
- end: *const u8,
- confirm: F,
-) -> Option<*const u8> {
- debug_assert!(start <= end);
-
- let mut ptr = end;
- while ptr > start {
- ptr = ptr.offset(-1);
- if confirm(*ptr) {
- return Some(ptr);
- }
- }
- None
-}
-
-/// Performs a forward byte-at-a-time loop until `ptr >= end_ptr` and returns
-/// the number of times `confirm(*ptr)` returns `true`.
-///
-/// # Safety
-///
-/// Callers must provide valid pointers and they must satisfy `start_ptr <=
-/// ptr` and `ptr <= end_ptr`.
-#[inline(always)]
-pub(crate) unsafe fn count_byte_by_byte<F: Fn(u8) -> bool>(
- start: *const u8,
- end: *const u8,
- confirm: F,
-) -> usize {
- debug_assert!(start <= end);
- let mut ptr = start;
- let mut count = 0;
- while ptr < end {
- if confirm(*ptr) {
- count += 1;
- }
- ptr = ptr.offset(1);
- }
- count
-}
diff --git a/vendor/memchr/src/arch/generic/mod.rs b/vendor/memchr/src/arch/generic/mod.rs
deleted file mode 100644
index 63ee3f0..0000000
--- a/vendor/memchr/src/arch/generic/mod.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-/*!
-This module defines "generic" routines that can be specialized to specific
-architectures.
-
-We don't expose this module primarily because it would require exposing all
-of the internal infrastructure required to write these generic routines.
-That infrastructure should be treated as an implementation detail so that
-it is allowed to evolve. Instead, what we expose are architecture specific
-instantiations of these generic implementations. The generic code just lets us
-write the code once (usually).
-*/
-
-pub(crate) mod memchr;
-pub(crate) mod packedpair;
diff --git a/vendor/memchr/src/arch/generic/packedpair.rs b/vendor/memchr/src/arch/generic/packedpair.rs
deleted file mode 100644
index 8d97cf2..0000000
--- a/vendor/memchr/src/arch/generic/packedpair.rs
+++ /dev/null
@@ -1,317 +0,0 @@
-/*!
-Generic crate-internal routines for the "packed pair" SIMD algorithm.
-
-The "packed pair" algorithm is based on the [generic SIMD] algorithm. The main
-difference is that it (by default) uses a background distribution of byte
-frequencies to heuristically select the pair of bytes to search for.
-
-[generic SIMD]: http://0x80.pl/articles/simd-strfind.html#first-and-last
-*/
-
-use crate::{
- arch::all::{is_equal_raw, packedpair::Pair},
- ext::Pointer,
- vector::{MoveMask, Vector},
-};
-
-/// A generic architecture dependent "packed pair" finder.
-///
-/// This finder picks two bytes that it believes have high predictive power
-/// for indicating an overall match of a needle. Depending on whether
-/// `Finder::find` or `Finder::find_prefilter` is used, it reports offsets
-/// where the needle matches or could match. In the prefilter case, candidates
-/// are reported whenever the [`Pair`] of bytes given matches.
-///
-/// This is architecture dependent because it uses specific vector operations
-/// to look for occurrences of the pair of bytes.
-///
-/// This type is not meant to be exported and is instead meant to be used as
-/// the implementation for architecture specific facades. Why? Because it's a
-/// bit of a quirky API that requires `inline(always)` annotations. And pretty
-/// much everything has safety obligations due (at least) to the caller needing
-/// to inline calls into routines marked with
-/// `#[target_feature(enable = "...")]`.
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct Finder<V> {
- pair: Pair,
- v1: V,
- v2: V,
- min_haystack_len: usize,
-}
-
-impl<V: Vector> Finder<V> {
- /// Create a new pair searcher. The searcher returned can either report
- /// exact matches of `needle` or act as a prefilter and report candidate
- /// positions of `needle`.
- ///
- /// # Safety
- ///
- /// Callers must ensure that whatever vector type this routine is called
- /// with is supported by the current environment.
- ///
- /// Callers must also ensure that `needle.len() >= 2`.
- #[inline(always)]
- pub(crate) unsafe fn new(needle: &[u8], pair: Pair) -> Finder<V> {
- let max_index = pair.index1().max(pair.index2());
- let min_haystack_len =
- core::cmp::max(needle.len(), usize::from(max_index) + V::BYTES);
- let v1 = V::splat(needle[usize::from(pair.index1())]);
- let v2 = V::splat(needle[usize::from(pair.index2())]);
- Finder { pair, v1, v2, min_haystack_len }
- }
-
- /// Searches the given haystack for the given needle. The needle given
- /// should be the same as the needle that this finder was initialized
- /// with.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// Since this is meant to be used with vector functions, callers need to
- /// specialize this inside of a function with a `target_feature` attribute.
- /// Therefore, callers must ensure that whatever target feature is being
- /// used supports the vector functions that this function is specialized
- /// for. (For the specific vector functions used, see the Vector trait
- /// implementations.)
- #[inline(always)]
- pub(crate) unsafe fn find(
- &self,
- haystack: &[u8],
- needle: &[u8],
- ) -> Option<usize> {
- assert!(
- haystack.len() >= self.min_haystack_len,
- "haystack too small, should be at least {} but got {}",
- self.min_haystack_len,
- haystack.len(),
- );
-
- let all = V::Mask::all_zeros_except_least_significant(0);
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- let max = end.sub(self.min_haystack_len);
- let mut cur = start;
-
- // N.B. I did experiment with unrolling the loop to deal with size(V)
- // bytes at a time and 2*size(V) bytes at a time. The double unroll
- // was marginally faster while the quadruple unroll was unambiguously
- // slower. In the end, I decided the complexity from unrolling wasn't
- // worth it. I used the memmem/krate/prebuilt/huge-en/ benchmarks to
- // compare.
- while cur <= max {
- if let Some(chunki) = self.find_in_chunk(needle, cur, end, all) {
- return Some(matched(start, cur, chunki));
- }
- cur = cur.add(V::BYTES);
- }
- if cur < end {
- let remaining = end.distance(cur);
- debug_assert!(
- remaining < self.min_haystack_len,
- "remaining bytes should be smaller than the minimum haystack \
- length of {}, but there are {} bytes remaining",
- self.min_haystack_len,
- remaining,
- );
- if remaining < needle.len() {
- return None;
- }
- debug_assert!(
- max < cur,
- "after main loop, cur should have exceeded max",
- );
- let overlap = cur.distance(max);
- debug_assert!(
- overlap > 0,
- "overlap ({}) must always be non-zero",
- overlap,
- );
- debug_assert!(
- overlap < V::BYTES,
- "overlap ({}) cannot possibly be >= than a vector ({})",
- overlap,
- V::BYTES,
- );
- // The mask has all of its bits set except for the first N least
- // significant bits, where N=overlap. This way, any matches that
- // occur in find_in_chunk within the overlap are automatically
- // ignored.
- let mask = V::Mask::all_zeros_except_least_significant(overlap);
- cur = max;
- let m = self.find_in_chunk(needle, cur, end, mask);
- if let Some(chunki) = m {
- return Some(matched(start, cur, chunki));
- }
- }
- None
- }
-
- /// Searches the given haystack for offsets that represent candidate
- /// matches of the `needle` given to this finder's constructor. The offsets
- /// returned, if they are a match, correspond to the starting offset of
- /// `needle` in the given `haystack`.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// Since this is meant to be used with vector functions, callers need to
- /// specialize this inside of a function with a `target_feature` attribute.
- /// Therefore, callers must ensure that whatever target feature is being
- /// used supports the vector functions that this function is specialized
- /// for. (For the specific vector functions used, see the Vector trait
- /// implementations.)
- #[inline(always)]
- pub(crate) unsafe fn find_prefilter(
- &self,
- haystack: &[u8],
- ) -> Option<usize> {
- assert!(
- haystack.len() >= self.min_haystack_len,
- "haystack too small, should be at least {} but got {}",
- self.min_haystack_len,
- haystack.len(),
- );
-
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- let max = end.sub(self.min_haystack_len);
- let mut cur = start;
-
- // N.B. I did experiment with unrolling the loop to deal with size(V)
- // bytes at a time and 2*size(V) bytes at a time. The double unroll
- // was marginally faster while the quadruple unroll was unambiguously
- // slower. In the end, I decided the complexity from unrolling wasn't
- // worth it. I used the memmem/krate/prebuilt/huge-en/ benchmarks to
- // compare.
- while cur <= max {
- if let Some(chunki) = self.find_prefilter_in_chunk(cur) {
- return Some(matched(start, cur, chunki));
- }
- cur = cur.add(V::BYTES);
- }
- if cur < end {
- // This routine immediately quits if a candidate match is found.
- // That means that if we're here, no candidate matches have been
- // found at or before 'ptr'. Thus, we don't need to mask anything
- // out even though we might technically search part of the haystack
- // that we've already searched (because we know it can't match).
- cur = max;
- if let Some(chunki) = self.find_prefilter_in_chunk(cur) {
- return Some(matched(start, cur, chunki));
- }
- }
- None
- }
-
- /// Search for an occurrence of our byte pair from the needle in the chunk
- /// pointed to by cur, with the end of the haystack pointed to by end.
- /// When an occurrence is found, memcmp is run to check if a match occurs
- /// at the corresponding position.
- ///
- /// `mask` should have bits set corresponding the positions in the chunk
- /// in which matches are considered. This is only used for the last vector
- /// load where the beginning of the vector might have overlapped with the
- /// last load in the main loop. The mask lets us avoid visiting positions
- /// that have already been discarded as matches.
- ///
- /// # Safety
- ///
- /// It must be safe to do an unaligned read of size(V) bytes starting at
- /// both (cur + self.index1) and (cur + self.index2). It must also be safe
- /// to do unaligned loads on cur up to (end - needle.len()).
- #[inline(always)]
- unsafe fn find_in_chunk(
- &self,
- needle: &[u8],
- cur: *const u8,
- end: *const u8,
- mask: V::Mask,
- ) -> Option<usize> {
- let index1 = usize::from(self.pair.index1());
- let index2 = usize::from(self.pair.index2());
- let chunk1 = V::load_unaligned(cur.add(index1));
- let chunk2 = V::load_unaligned(cur.add(index2));
- let eq1 = chunk1.cmpeq(self.v1);
- let eq2 = chunk2.cmpeq(self.v2);
-
- let mut offsets = eq1.and(eq2).movemask().and(mask);
- while offsets.has_non_zero() {
- let offset = offsets.first_offset();
- let cur = cur.add(offset);
- if end.sub(needle.len()) < cur {
- return None;
- }
- if is_equal_raw(needle.as_ptr(), cur, needle.len()) {
- return Some(offset);
- }
- offsets = offsets.clear_least_significant_bit();
- }
- None
- }
-
- /// Search for an occurrence of our byte pair from the needle in the chunk
- /// pointed to by cur, with the end of the haystack pointed to by end.
- /// When an occurrence is found, memcmp is run to check if a match occurs
- /// at the corresponding position.
- ///
- /// # Safety
- ///
- /// It must be safe to do an unaligned read of size(V) bytes starting at
- /// both (cur + self.index1) and (cur + self.index2). It must also be safe
- /// to do unaligned reads on cur up to (end - needle.len()).
- #[inline(always)]
- unsafe fn find_prefilter_in_chunk(&self, cur: *const u8) -> Option<usize> {
- let index1 = usize::from(self.pair.index1());
- let index2 = usize::from(self.pair.index2());
- let chunk1 = V::load_unaligned(cur.add(index1));
- let chunk2 = V::load_unaligned(cur.add(index2));
- let eq1 = chunk1.cmpeq(self.v1);
- let eq2 = chunk2.cmpeq(self.v2);
-
- let offsets = eq1.and(eq2).movemask();
- if !offsets.has_non_zero() {
- return None;
- }
- Some(offsets.first_offset())
- }
-
- /// Returns the pair of offsets (into the needle) used to check as a
- /// predicate before confirming whether a needle exists at a particular
- /// position.
- #[inline]
- pub(crate) fn pair(&self) -> &Pair {
- &self.pair
- }
-
- /// Returns the minimum haystack length that this `Finder` can search.
- ///
- /// Providing a haystack to this `Finder` shorter than this length is
- /// guaranteed to result in a panic.
- #[inline(always)]
- pub(crate) fn min_haystack_len(&self) -> usize {
- self.min_haystack_len
- }
-}
-
-/// Accepts a chunk-relative offset and returns a haystack relative offset.
-///
-/// This used to be marked `#[cold]` and `#[inline(never)]`, but I couldn't
-/// observe a consistent measureable difference between that and just inlining
-/// it. So we go with inlining it.
-///
-/// # Safety
-///
-/// Same at `ptr::offset_from` in addition to `cur >= start`.
-#[inline(always)]
-unsafe fn matched(start: *const u8, cur: *const u8, chunki: usize) -> usize {
- cur.distance(start) + chunki
-}
-
-// If you're looking for tests, those are run for each instantiation of the
-// above code. So for example, see arch::x86_64::sse2::packedpair.
diff --git a/vendor/memchr/src/arch/mod.rs b/vendor/memchr/src/arch/mod.rs
deleted file mode 100644
index 2f63a1a..0000000
--- a/vendor/memchr/src/arch/mod.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-/*!
-A module with low-level architecture dependent routines.
-
-These routines are useful as primitives for tasks not covered by the higher
-level crate API.
-*/
-
-pub mod all;
-pub(crate) mod generic;
-
-#[cfg(target_arch = "aarch64")]
-pub mod aarch64;
-#[cfg(target_arch = "wasm32")]
-pub mod wasm32;
-#[cfg(target_arch = "x86_64")]
-pub mod x86_64;
diff --git a/vendor/memchr/src/arch/wasm32/memchr.rs b/vendor/memchr/src/arch/wasm32/memchr.rs
deleted file mode 100644
index b0bbd1c..0000000
--- a/vendor/memchr/src/arch/wasm32/memchr.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-/*!
-Wrapper routines for `memchr` and friends.
-
-These routines choose the best implementation at compile time. (This is
-different from `x86_64` because it is expected that `simd128` is almost always
-available for `wasm32` targets.)
-*/
-
-macro_rules! defraw {
- ($ty:ident, $find:ident, $start:ident, $end:ident, $($needles:ident),+) => {{
- #[cfg(target_feature = "simd128")]
- {
- use crate::arch::wasm32::simd128::memchr::$ty;
-
- debug!("chose simd128 for {}", stringify!($ty));
- debug_assert!($ty::is_available());
- // SAFETY: We know that wasm memchr is always available whenever
- // code is compiled for `wasm32` with the `simd128` target feature
- // enabled.
- $ty::new_unchecked($($needles),+).$find($start, $end)
- }
- #[cfg(not(target_feature = "simd128"))]
- {
- use crate::arch::all::memchr::$ty;
-
- debug!(
- "no simd128 feature available, using fallback for {}",
- stringify!($ty),
- );
- $ty::new($($needles),+).$find($start, $end)
- }
- }}
-}
-
-/// memchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::find_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memchr_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(One, find_raw, start, end, n1)
-}
-
-/// memrchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::rfind_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memrchr_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(One, rfind_raw, start, end, n1)
-}
-
-/// memchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::find_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memchr2_raw(
- n1: u8,
- n2: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Two, find_raw, start, end, n1, n2)
-}
-
-/// memrchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::rfind_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memrchr2_raw(
- n1: u8,
- n2: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Two, rfind_raw, start, end, n1, n2)
-}
-
-/// memchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::find_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memchr3_raw(
- n1: u8,
- n2: u8,
- n3: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Three, find_raw, start, end, n1, n2, n3)
-}
-
-/// memrchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::rfind_raw`.
-#[inline(always)]
-pub(crate) unsafe fn memrchr3_raw(
- n1: u8,
- n2: u8,
- n3: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- defraw!(Three, rfind_raw, start, end, n1, n2, n3)
-}
-
-/// Count all matching bytes, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::count_raw`.
-#[inline(always)]
-pub(crate) unsafe fn count_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> usize {
- defraw!(One, count_raw, start, end, n1)
-}
diff --git a/vendor/memchr/src/arch/wasm32/mod.rs b/vendor/memchr/src/arch/wasm32/mod.rs
deleted file mode 100644
index 209f876..0000000
--- a/vendor/memchr/src/arch/wasm32/mod.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
-Vector algorithms for the `wasm32` target.
-*/
-
-pub mod simd128;
-
-pub(crate) mod memchr;
diff --git a/vendor/memchr/src/arch/wasm32/simd128/memchr.rs b/vendor/memchr/src/arch/wasm32/simd128/memchr.rs
deleted file mode 100644
index fa314c9..0000000
--- a/vendor/memchr/src/arch/wasm32/simd128/memchr.rs
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*!
-This module defines 128-bit vector implementations of `memchr` and friends.
-
-The main types in this module are [`One`], [`Two`] and [`Three`]. They are for
-searching for one, two or three distinct bytes, respectively, in a haystack.
-Each type also has corresponding double ended iterators. These searchers are
-typically much faster than scalar routines accomplishing the same task.
-
-The `One` searcher also provides a [`One::count`] routine for efficiently
-counting the number of times a single byte occurs in a haystack. This is
-useful, for example, for counting the number of lines in a haystack. This
-routine exists because it is usually faster, especially with a high match
-count, then using [`One::find`] repeatedly. ([`OneIter`] specializes its
-`Iterator::count` implementation to use this routine.)
-
-Only one, two and three bytes are supported because three bytes is about
-the point where one sees diminishing returns. Beyond this point and it's
-probably (but not necessarily) better to just use a simple `[bool; 256]` array
-or similar. However, it depends mightily on the specific work-load and the
-expected match frequency.
-*/
-
-use core::arch::wasm32::v128;
-
-use crate::{arch::generic::memchr as generic, ext::Pointer, vector::Vector};
-
-/// Finds all occurrences of a single byte in a haystack.
-#[derive(Clone, Copy, Debug)]
-pub struct One(generic::One<v128>);
-
-impl One {
- /// Create a new searcher that finds occurrences of the needle byte given.
- ///
- /// This particular searcher is specialized to use simd128 vector
- /// instructions that typically make it quite fast.
- ///
- /// If simd128 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle: u8) -> Option<One> {
- if One::is_available() {
- // SAFETY: we check that simd128 is available above.
- unsafe { Some(One::new_unchecked(needle)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to simd128 vectors and routines without
- /// checking that simd128 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `simd128`
- /// instructions in the current environment.
- #[target_feature(enable = "simd128")]
- #[inline]
- pub unsafe fn new_unchecked(needle: u8) -> One {
- One(generic::One::new(needle))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`One::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `One::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "simd128")]
- {
- true
- }
- #[cfg(not(target_feature = "simd128"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Counts all occurrences of this byte in the given haystack.
- #[inline]
- pub fn count(&self, haystack: &[u8]) -> usize {
- // SAFETY: All of our pointers are derived directly from a borrowed
- // slice, which is guaranteed to be valid.
- unsafe {
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- self.count_raw(start, end)
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < v128::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'simd128' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < v128::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'simd128' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.rfind_raw_impl(start, end)
- }
-
- /// Counts all occurrences of this byte in the given haystack represented
- /// by raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn count_raw(&self, start: *const u8, end: *const u8) -> usize {
- if start >= end {
- return 0;
- }
- if end.distance(start) < v128::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::count_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'simd128' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.count_raw_impl(start, end)
- }
-
- /// Execute a search using simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of a simd128 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of a simd128 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Execute a count using simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::count_raw`], except the distance between `start` and
- /// `end` must be at least the size of a simd128 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn count_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> usize {
- self.0.count_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> OneIter<'a, 'h> {
- OneIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of a single byte in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`One::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`One`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct OneIter<'a, 'h> {
- searcher: &'a One,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for OneIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn count(self) -> usize {
- self.it.count(|s, e| {
- // SAFETY: We rely on our generic iterator to return valid start
- // and end pointers.
- unsafe { self.searcher.count_raw(s, e) }
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for OneIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for OneIter<'a, 'h> {}
-
-/// Finds all occurrences of two bytes in a haystack.
-///
-/// That is, this reports matches of one of two possible bytes. For example,
-/// searching for `a` or `b` in `afoobar` would report matches at offsets `0`,
-/// `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Two(generic::Two<v128>);
-
-impl Two {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use simd128 vector
- /// instructions that typically make it quite fast.
- ///
- /// If simd128 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8) -> Option<Two> {
- if Two::is_available() {
- // SAFETY: we check that simd128 is available above.
- unsafe { Some(Two::new_unchecked(needle1, needle2)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to simd128 vectors and routines without
- /// checking that simd128 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `simd128`
- /// instructions in the current environment.
- #[target_feature(enable = "simd128")]
- #[inline]
- pub unsafe fn new_unchecked(needle1: u8, needle2: u8) -> Two {
- Two(generic::Two::new(needle1, needle2))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Two::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Two::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "simd128")]
- {
- true
- }
- #[cfg(not(target_feature = "simd128"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < v128::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1() || b == self.0.needle2()
- });
- }
- // SAFETY: Building a `Two` means it's safe to call 'simd128' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < v128::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1() || b == self.0.needle2()
- });
- }
- // SAFETY: Building a `Two` means it's safe to call 'simd128' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.rfind_raw_impl(start, end)
- }
-
- /// Execute a search using simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of a simd128 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of a simd128 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle bytes in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> TwoIter<'a, 'h> {
- TwoIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of two possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Two::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Two`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct TwoIter<'a, 'h> {
- searcher: &'a Two,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for TwoIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for TwoIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for TwoIter<'a, 'h> {}
-
-/// Finds all occurrences of three bytes in a haystack.
-///
-/// That is, this reports matches of one of three possible bytes. For example,
-/// searching for `a`, `b` or `o` in `afoobar` would report matches at offsets
-/// `0`, `2`, `3`, `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Three(generic::Three<v128>);
-
-impl Three {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use simd128 vector
- /// instructions that typically make it quite fast.
- ///
- /// If simd128 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8, needle3: u8) -> Option<Three> {
- if Three::is_available() {
- // SAFETY: we check that simd128 is available above.
- unsafe { Some(Three::new_unchecked(needle1, needle2, needle3)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to simd128 vectors and routines without
- /// checking that simd128 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `simd128`
- /// instructions in the current environment.
- #[target_feature(enable = "simd128")]
- #[inline]
- pub unsafe fn new_unchecked(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- ) -> Three {
- Three(generic::Three::new(needle1, needle2, needle3))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Three::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Three::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "simd128")]
- {
- true
- }
- #[cfg(not(target_feature = "simd128"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < v128::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- || b == self.0.needle2()
- || b == self.0.needle3()
- });
- }
- // SAFETY: Building a `Three` means it's safe to call 'simd128'
- // routines. Also, we've checked that our haystack is big enough to run
- // on the vector routine. Pointer validity is caller's responsibility.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < v128::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- || b == self.0.needle2()
- || b == self.0.needle3()
- });
- }
- // SAFETY: Building a `Three` means it's safe to call 'simd128'
- // routines. Also, we've checked that our haystack is big enough to run
- // on the vector routine. Pointer validity is caller's responsibility.
- self.rfind_raw_impl(start, end)
- }
-
- /// Execute a search using simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of a simd128 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of a simd128 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> ThreeIter<'a, 'h> {
- ThreeIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of three possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Three::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Three`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct ThreeIter<'a, 'h> {
- searcher: &'a Three,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for ThreeIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for ThreeIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for ThreeIter<'a, 'h> {}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_memchr_quickcheck!(super);
-
- #[test]
- fn forward_one() {
- crate::tests::memchr::Runner::new(1).forward_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_one() {
- crate::tests::memchr::Runner::new(1).reverse_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn count_one() {
- crate::tests::memchr::Runner::new(1).count_iter(|haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).count())
- })
- }
-
- #[test]
- fn forward_two() {
- crate::tests::memchr::Runner::new(2).forward_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_two() {
- crate::tests::memchr::Runner::new(2).reverse_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn forward_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).rev().collect())
- },
- )
- }
-}
diff --git a/vendor/memchr/src/arch/wasm32/simd128/mod.rs b/vendor/memchr/src/arch/wasm32/simd128/mod.rs
deleted file mode 100644
index b55d1f0..0000000
--- a/vendor/memchr/src/arch/wasm32/simd128/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
-Algorithms for the `wasm32` target using 128-bit vectors via simd128.
-*/
-
-pub mod memchr;
-pub mod packedpair;
diff --git a/vendor/memchr/src/arch/wasm32/simd128/packedpair.rs b/vendor/memchr/src/arch/wasm32/simd128/packedpair.rs
deleted file mode 100644
index b629377..0000000
--- a/vendor/memchr/src/arch/wasm32/simd128/packedpair.rs
+++ /dev/null
@@ -1,229 +0,0 @@
-/*!
-A 128-bit vector implementation of the "packed pair" SIMD algorithm.
-
-The "packed pair" algorithm is based on the [generic SIMD] algorithm. The main
-difference is that it (by default) uses a background distribution of byte
-frequencies to heuristically select the pair of bytes to search for.
-
-[generic SIMD]: http://0x80.pl/articles/simd-strfind.html#first-and-last
-*/
-
-use core::arch::wasm32::v128;
-
-use crate::arch::{all::packedpair::Pair, generic::packedpair};
-
-/// A "packed pair" finder that uses 128-bit vector operations.
-///
-/// This finder picks two bytes that it believes have high predictive power
-/// for indicating an overall match of a needle. Depending on whether
-/// `Finder::find` or `Finder::find_prefilter` is used, it reports offsets
-/// where the needle matches or could match. In the prefilter case, candidates
-/// are reported whenever the [`Pair`] of bytes given matches.
-#[derive(Clone, Copy, Debug)]
-pub struct Finder(packedpair::Finder<v128>);
-
-impl Finder {
- /// Create a new pair searcher. The searcher returned can either report
- /// exact matches of `needle` or act as a prefilter and report candidate
- /// positions of `needle`.
- ///
- /// If simd128 is unavailable in the current environment or if a [`Pair`]
- /// could not be constructed from the needle given, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle: &[u8]) -> Option<Finder> {
- Finder::with_pair(needle, Pair::new(needle)?)
- }
-
- /// Create a new "packed pair" finder using the pair of bytes given.
- ///
- /// This constructor permits callers to control precisely which pair of
- /// bytes is used as a predicate.
- ///
- /// If simd128 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn with_pair(needle: &[u8], pair: Pair) -> Option<Finder> {
- if Finder::is_available() {
- // SAFETY: we check that simd128 is available above. We are also
- // guaranteed to have needle.len() > 1 because we have a valid
- // Pair.
- unsafe { Some(Finder::with_pair_impl(needle, pair)) }
- } else {
- None
- }
- }
-
- /// Create a new `Finder` specific to simd128 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as the safety for `packedpair::Finder::new`, and callers must also
- /// ensure that simd128 is available.
- #[target_feature(enable = "simd128")]
- #[inline]
- unsafe fn with_pair_impl(needle: &[u8], pair: Pair) -> Finder {
- let finder = packedpair::Finder::<v128>::new(needle, pair);
- Finder(finder)
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Finder::with_pair`] will
- /// return a `Some` value. Similarly, when it is false, it is guaranteed
- /// that `Finder::with_pair` will return a `None` value. Notice that this
- /// does not guarantee that [`Finder::new`] will return a `Finder`. Namely,
- /// even when `Finder::is_available` is true, it is not guaranteed that a
- /// valid [`Pair`] can be found from the needle given.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "simd128")]
- {
- true
- }
- #[cfg(not(target_feature = "simd128"))]
- {
- false
- }
- }
-
- /// Execute a search using wasm32 v128 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- self.find_impl(haystack, needle)
- }
-
- /// Execute a search using wasm32 v128 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find_prefilter(&self, haystack: &[u8]) -> Option<usize> {
- self.find_prefilter_impl(haystack)
- }
-
- /// Execute a search using wasm32 v128 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- fn find_impl(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- // SAFETY: The target feature safety obligation is automatically
- // fulfilled by virtue of being a method on `Finder`, which can only be
- // constructed when it is safe to call `simd128` routines.
- unsafe { self.0.find(haystack, needle) }
- }
-
- /// Execute a prefilter search using wasm32 v128 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `simd128` routines.)
- #[target_feature(enable = "simd128")]
- #[inline]
- fn find_prefilter_impl(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: The target feature safety obligation is automatically
- // fulfilled by virtue of being a method on `Finder`, which can only be
- // constructed when it is safe to call `simd128` routines.
- unsafe { self.0.find_prefilter(haystack) }
- }
-
- /// Returns the pair of offsets (into the needle) used to check as a
- /// predicate before confirming whether a needle exists at a particular
- /// position.
- #[inline]
- pub fn pair(&self) -> &Pair {
- self.0.pair()
- }
-
- /// Returns the minimum haystack length that this `Finder` can search.
- ///
- /// Using a haystack with length smaller than this in a search will result
- /// in a panic. The reason for this restriction is that this finder is
- /// meant to be a low-level component that is part of a larger substring
- /// strategy. In that sense, it avoids trying to handle all cases and
- /// instead only handles the cases that it can handle very well.
- #[inline]
- pub fn min_haystack_len(&self) -> usize {
- self.0.min_haystack_len()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- fn find(haystack: &[u8], needle: &[u8]) -> Option<Option<usize>> {
- let f = Finder::new(needle)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
-
- define_substring_forward_quickcheck!(find);
-
- #[test]
- fn forward_substring() {
- crate::tests::substring::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair_prefilter() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find_prefilter(haystack))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-}
diff --git a/vendor/memchr/src/arch/x86_64/avx2/memchr.rs b/vendor/memchr/src/arch/x86_64/avx2/memchr.rs
deleted file mode 100644
index 59f8c7f..0000000
--- a/vendor/memchr/src/arch/x86_64/avx2/memchr.rs
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*!
-This module defines 256-bit vector implementations of `memchr` and friends.
-
-The main types in this module are [`One`], [`Two`] and [`Three`]. They are for
-searching for one, two or three distinct bytes, respectively, in a haystack.
-Each type also has corresponding double ended iterators. These searchers are
-typically much faster than scalar routines accomplishing the same task.
-
-The `One` searcher also provides a [`One::count`] routine for efficiently
-counting the number of times a single byte occurs in a haystack. This is
-useful, for example, for counting the number of lines in a haystack. This
-routine exists because it is usually faster, especially with a high match
-count, then using [`One::find`] repeatedly. ([`OneIter`] specializes its
-`Iterator::count` implementation to use this routine.)
-
-Only one, two and three bytes are supported because three bytes is about
-the point where one sees diminishing returns. Beyond this point and it's
-probably (but not necessarily) better to just use a simple `[bool; 256]` array
-or similar. However, it depends mightily on the specific work-load and the
-expected match frequency.
-*/
-
-use core::arch::x86_64::{__m128i, __m256i};
-
-use crate::{arch::generic::memchr as generic, ext::Pointer, vector::Vector};
-
-/// Finds all occurrences of a single byte in a haystack.
-#[derive(Clone, Copy, Debug)]
-pub struct One {
- /// Used for haystacks less than 32 bytes.
- sse2: generic::One<__m128i>,
- /// Used for haystacks bigger than 32 bytes.
- avx2: generic::One<__m256i>,
-}
-
-impl One {
- /// Create a new searcher that finds occurrences of the needle byte given.
- ///
- /// This particular searcher is specialized to use AVX2 vector instructions
- /// that typically make it quite fast. (SSE2 is used for haystacks that
- /// are too short to accommodate an AVX2 vector.)
- ///
- /// If either SSE2 or AVX2 is unavailable in the current environment, then
- /// `None` is returned.
- #[inline]
- pub fn new(needle: u8) -> Option<One> {
- if One::is_available() {
- // SAFETY: we check that sse2 and avx2 are available above.
- unsafe { Some(One::new_unchecked(needle)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to AVX2 vectors and routines without
- /// checking that either SSE2 or AVX2 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute both `sse2` and
- /// `avx2` instructions in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to SSE2
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "sse2", enable = "avx2")]
- #[inline]
- pub unsafe fn new_unchecked(needle: u8) -> One {
- One {
- sse2: generic::One::new(needle),
- avx2: generic::One::new(needle),
- }
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`One::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `One::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- #[cfg(target_feature = "sse2")]
- {
- #[cfg(target_feature = "avx2")]
- {
- true
- }
- #[cfg(not(target_feature = "avx2"))]
- {
- #[cfg(feature = "std")]
- {
- std::is_x86_feature_detected!("avx2")
- }
- #[cfg(not(feature = "std"))]
- {
- false
- }
- }
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Counts all occurrences of this byte in the given haystack.
- #[inline]
- pub fn count(&self, haystack: &[u8]) -> usize {
- // SAFETY: All of our pointers are derived directly from a borrowed
- // slice, which is guaranteed to be valid.
- unsafe {
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- self.count_raw(start, end)
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let len = end.distance(start);
- if len < __m256i::BYTES {
- return if len < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- generic::fwd_byte_by_byte(start, end, |b| {
- b == self.sse2.needle1()
- })
- } else {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- self.find_raw_sse2(start, end)
- };
- }
- // SAFETY: Building a `One` means it's safe to call both 'sse2' and
- // 'avx2' routines. Also, we've checked that our haystack is big
- // enough to run on the vector routine. Pointer validity is caller's
- // responsibility.
- //
- // Note that we could call `self.avx2.find_raw` directly here. But that
- // means we'd have to annotate this routine with `target_feature`.
- // Which is fine, because this routine is `unsafe` anyway and the
- // `target_feature` obligation is met by virtue of building a `One`.
- // The real problem is that a routine with a `target_feature`
- // annotation generally can't be inlined into caller code unless
- // the caller code has the same target feature annotations. Namely,
- // the common case (at time of writing) is for calling code to not
- // have the `avx2` target feature enabled *at compile time*. Without
- // `target_feature` on this routine, it can be inlined which will
- // handle some of the short-haystack cases above without touching the
- // architecture specific code.
- self.find_raw_avx2(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let len = end.distance(start);
- if len < __m256i::BYTES {
- return if len < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- generic::rev_byte_by_byte(start, end, |b| {
- b == self.sse2.needle1()
- })
- } else {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- self.rfind_raw_sse2(start, end)
- };
- }
- // SAFETY: Building a `One` means it's safe to call both 'sse2' and
- // 'avx2' routines. Also, we've checked that our haystack is big
- // enough to run on the vector routine. Pointer validity is caller's
- // responsibility.
- //
- // See note in forward routine above for why we don't just call
- // `self.avx2.rfind_raw` directly here.
- self.rfind_raw_avx2(start, end)
- }
-
- /// Counts all occurrences of this byte in the given haystack represented
- /// by raw pointers.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `0` will always be returned.
- #[inline]
- pub unsafe fn count_raw(&self, start: *const u8, end: *const u8) -> usize {
- if start >= end {
- return 0;
- }
- let len = end.distance(start);
- if len < __m256i::BYTES {
- return if len < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- generic::count_byte_by_byte(start, end, |b| {
- b == self.sse2.needle1()
- })
- } else {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- self.count_raw_sse2(start, end)
- };
- }
- // SAFETY: Building a `One` means it's safe to call both 'sse2' and
- // 'avx2' routines. Also, we've checked that our haystack is big
- // enough to run on the vector routine. Pointer validity is caller's
- // responsibility.
- self.count_raw_avx2(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_raw_sse2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.sse2.find_raw(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn rfind_raw_sse2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.sse2.rfind_raw(start, end)
- }
-
- /// Execute a count using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::count_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn count_raw_sse2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> usize {
- self.sse2.count_raw(start, end)
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an AVX2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "avx2")]
- #[inline]
- unsafe fn find_raw_avx2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.avx2.find_raw(start, end)
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an AVX2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "avx2")]
- #[inline]
- unsafe fn rfind_raw_avx2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.avx2.rfind_raw(start, end)
- }
-
- /// Execute a count using AVX2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::count_raw`], except the distance between `start` and
- /// `end` must be at least the size of an AVX2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "avx2")]
- #[inline]
- unsafe fn count_raw_avx2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> usize {
- self.avx2.count_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> OneIter<'a, 'h> {
- OneIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of a single byte in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`One::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`One`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct OneIter<'a, 'h> {
- searcher: &'a One,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for OneIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn count(self) -> usize {
- self.it.count(|s, e| {
- // SAFETY: We rely on our generic iterator to return valid start
- // and end pointers.
- unsafe { self.searcher.count_raw(s, e) }
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for OneIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for OneIter<'a, 'h> {}
-
-/// Finds all occurrences of two bytes in a haystack.
-///
-/// That is, this reports matches of one of two possible bytes. For example,
-/// searching for `a` or `b` in `afoobar` would report matches at offsets `0`,
-/// `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Two {
- /// Used for haystacks less than 32 bytes.
- sse2: generic::Two<__m128i>,
- /// Used for haystacks bigger than 32 bytes.
- avx2: generic::Two<__m256i>,
-}
-
-impl Two {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use AVX2 vector instructions
- /// that typically make it quite fast. (SSE2 is used for haystacks that
- /// are too short to accommodate an AVX2 vector.)
- ///
- /// If either SSE2 or AVX2 is unavailable in the current environment, then
- /// `None` is returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8) -> Option<Two> {
- if Two::is_available() {
- // SAFETY: we check that sse2 and avx2 are available above.
- unsafe { Some(Two::new_unchecked(needle1, needle2)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to AVX2 vectors and routines without
- /// checking that either SSE2 or AVX2 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute both `sse2` and
- /// `avx2` instructions in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to SSE2
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "sse2", enable = "avx2")]
- #[inline]
- pub unsafe fn new_unchecked(needle1: u8, needle2: u8) -> Two {
- Two {
- sse2: generic::Two::new(needle1, needle2),
- avx2: generic::Two::new(needle1, needle2),
- }
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Two::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Two::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- #[cfg(target_feature = "sse2")]
- {
- #[cfg(target_feature = "avx2")]
- {
- true
- }
- #[cfg(not(target_feature = "avx2"))]
- {
- #[cfg(feature = "std")]
- {
- std::is_x86_feature_detected!("avx2")
- }
- #[cfg(not(feature = "std"))]
- {
- false
- }
- }
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let len = end.distance(start);
- if len < __m256i::BYTES {
- return if len < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- generic::fwd_byte_by_byte(start, end, |b| {
- b == self.sse2.needle1() || b == self.sse2.needle2()
- })
- } else {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- self.find_raw_sse2(start, end)
- };
- }
- // SAFETY: Building a `Two` means it's safe to call both 'sse2' and
- // 'avx2' routines. Also, we've checked that our haystack is big
- // enough to run on the vector routine. Pointer validity is caller's
- // responsibility.
- //
- // Note that we could call `self.avx2.find_raw` directly here. But that
- // means we'd have to annotate this routine with `target_feature`.
- // Which is fine, because this routine is `unsafe` anyway and the
- // `target_feature` obligation is met by virtue of building a `Two`.
- // The real problem is that a routine with a `target_feature`
- // annotation generally can't be inlined into caller code unless
- // the caller code has the same target feature annotations. Namely,
- // the common case (at time of writing) is for calling code to not
- // have the `avx2` target feature enabled *at compile time*. Without
- // `target_feature` on this routine, it can be inlined which will
- // handle some of the short-haystack cases above without touching the
- // architecture specific code.
- self.find_raw_avx2(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let len = end.distance(start);
- if len < __m256i::BYTES {
- return if len < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- generic::rev_byte_by_byte(start, end, |b| {
- b == self.sse2.needle1() || b == self.sse2.needle2()
- })
- } else {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- self.rfind_raw_sse2(start, end)
- };
- }
- // SAFETY: Building a `Two` means it's safe to call both 'sse2' and
- // 'avx2' routines. Also, we've checked that our haystack is big
- // enough to run on the vector routine. Pointer validity is caller's
- // responsibility.
- //
- // See note in forward routine above for why we don't just call
- // `self.avx2.rfind_raw` directly here.
- self.rfind_raw_avx2(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_raw_sse2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.sse2.find_raw(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn rfind_raw_sse2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.sse2.rfind_raw(start, end)
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an AVX2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "avx2")]
- #[inline]
- unsafe fn find_raw_avx2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.avx2.find_raw(start, end)
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an AVX2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "avx2")]
- #[inline]
- unsafe fn rfind_raw_avx2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.avx2.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle bytes in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> TwoIter<'a, 'h> {
- TwoIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of two possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Two::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Two`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct TwoIter<'a, 'h> {
- searcher: &'a Two,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for TwoIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for TwoIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for TwoIter<'a, 'h> {}
-
-/// Finds all occurrences of three bytes in a haystack.
-///
-/// That is, this reports matches of one of three possible bytes. For example,
-/// searching for `a`, `b` or `o` in `afoobar` would report matches at offsets
-/// `0`, `2`, `3`, `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Three {
- /// Used for haystacks less than 32 bytes.
- sse2: generic::Three<__m128i>,
- /// Used for haystacks bigger than 32 bytes.
- avx2: generic::Three<__m256i>,
-}
-
-impl Three {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use AVX2 vector instructions
- /// that typically make it quite fast. (SSE2 is used for haystacks that
- /// are too short to accommodate an AVX2 vector.)
- ///
- /// If either SSE2 or AVX2 is unavailable in the current environment, then
- /// `None` is returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8, needle3: u8) -> Option<Three> {
- if Three::is_available() {
- // SAFETY: we check that sse2 and avx2 are available above.
- unsafe { Some(Three::new_unchecked(needle1, needle2, needle3)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to AVX2 vectors and routines without
- /// checking that either SSE2 or AVX2 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute both `sse2` and
- /// `avx2` instructions in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to SSE2
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "sse2", enable = "avx2")]
- #[inline]
- pub unsafe fn new_unchecked(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- ) -> Three {
- Three {
- sse2: generic::Three::new(needle1, needle2, needle3),
- avx2: generic::Three::new(needle1, needle2, needle3),
- }
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Three::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Three::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- #[cfg(target_feature = "sse2")]
- {
- #[cfg(target_feature = "avx2")]
- {
- true
- }
- #[cfg(not(target_feature = "avx2"))]
- {
- #[cfg(feature = "std")]
- {
- std::is_x86_feature_detected!("avx2")
- }
- #[cfg(not(feature = "std"))]
- {
- false
- }
- }
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let len = end.distance(start);
- if len < __m256i::BYTES {
- return if len < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- generic::fwd_byte_by_byte(start, end, |b| {
- b == self.sse2.needle1()
- || b == self.sse2.needle2()
- || b == self.sse2.needle3()
- })
- } else {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- self.find_raw_sse2(start, end)
- };
- }
- // SAFETY: Building a `Three` means it's safe to call both 'sse2' and
- // 'avx2' routines. Also, we've checked that our haystack is big
- // enough to run on the vector routine. Pointer validity is caller's
- // responsibility.
- //
- // Note that we could call `self.avx2.find_raw` directly here. But that
- // means we'd have to annotate this routine with `target_feature`.
- // Which is fine, because this routine is `unsafe` anyway and the
- // `target_feature` obligation is met by virtue of building a `Three`.
- // The real problem is that a routine with a `target_feature`
- // annotation generally can't be inlined into caller code unless
- // the caller code has the same target feature annotations. Namely,
- // the common case (at time of writing) is for calling code to not
- // have the `avx2` target feature enabled *at compile time*. Without
- // `target_feature` on this routine, it can be inlined which will
- // handle some of the short-haystack cases above without touching the
- // architecture specific code.
- self.find_raw_avx2(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- let len = end.distance(start);
- if len < __m256i::BYTES {
- return if len < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- generic::rev_byte_by_byte(start, end, |b| {
- b == self.sse2.needle1()
- || b == self.sse2.needle2()
- || b == self.sse2.needle3()
- })
- } else {
- // SAFETY: We require the caller to pass valid start/end
- // pointers.
- self.rfind_raw_sse2(start, end)
- };
- }
- // SAFETY: Building a `Three` means it's safe to call both 'sse2' and
- // 'avx2' routines. Also, we've checked that our haystack is big
- // enough to run on the vector routine. Pointer validity is caller's
- // responsibility.
- //
- // See note in forward routine above for why we don't just call
- // `self.avx2.rfind_raw` directly here.
- self.rfind_raw_avx2(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_raw_sse2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.sse2.find_raw(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn rfind_raw_sse2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.sse2.rfind_raw(start, end)
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an AVX2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "avx2")]
- #[inline]
- unsafe fn find_raw_avx2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.avx2.find_raw(start, end)
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an AVX2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `sse2`/`avx2` routines.)
- #[target_feature(enable = "avx2")]
- #[inline]
- unsafe fn rfind_raw_avx2(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.avx2.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle bytes in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> ThreeIter<'a, 'h> {
- ThreeIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of three possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Three::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Three`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct ThreeIter<'a, 'h> {
- searcher: &'a Three,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for ThreeIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for ThreeIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for ThreeIter<'a, 'h> {}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_memchr_quickcheck!(super);
-
- #[test]
- fn forward_one() {
- crate::tests::memchr::Runner::new(1).forward_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_one() {
- crate::tests::memchr::Runner::new(1).reverse_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn count_one() {
- crate::tests::memchr::Runner::new(1).count_iter(|haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).count())
- })
- }
-
- #[test]
- fn forward_two() {
- crate::tests::memchr::Runner::new(2).forward_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_two() {
- crate::tests::memchr::Runner::new(2).reverse_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn forward_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).rev().collect())
- },
- )
- }
-}
diff --git a/vendor/memchr/src/arch/x86_64/avx2/mod.rs b/vendor/memchr/src/arch/x86_64/avx2/mod.rs
deleted file mode 100644
index ee4097d..0000000
--- a/vendor/memchr/src/arch/x86_64/avx2/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
-Algorithms for the `x86_64` target using 256-bit vectors via AVX2.
-*/
-
-pub mod memchr;
-pub mod packedpair;
diff --git a/vendor/memchr/src/arch/x86_64/avx2/packedpair.rs b/vendor/memchr/src/arch/x86_64/avx2/packedpair.rs
deleted file mode 100644
index efae7b6..0000000
--- a/vendor/memchr/src/arch/x86_64/avx2/packedpair.rs
+++ /dev/null
@@ -1,272 +0,0 @@
-/*!
-A 256-bit vector implementation of the "packed pair" SIMD algorithm.
-
-The "packed pair" algorithm is based on the [generic SIMD] algorithm. The main
-difference is that it (by default) uses a background distribution of byte
-frequencies to heuristically select the pair of bytes to search for.
-
-[generic SIMD]: http://0x80.pl/articles/simd-strfind.html#first-and-last
-*/
-
-use core::arch::x86_64::{__m128i, __m256i};
-
-use crate::arch::{all::packedpair::Pair, generic::packedpair};
-
-/// A "packed pair" finder that uses 256-bit vector operations.
-///
-/// This finder picks two bytes that it believes have high predictive power
-/// for indicating an overall match of a needle. Depending on whether
-/// `Finder::find` or `Finder::find_prefilter` is used, it reports offsets
-/// where the needle matches or could match. In the prefilter case, candidates
-/// are reported whenever the [`Pair`] of bytes given matches.
-#[derive(Clone, Copy, Debug)]
-pub struct Finder {
- sse2: packedpair::Finder<__m128i>,
- avx2: packedpair::Finder<__m256i>,
-}
-
-impl Finder {
- /// Create a new pair searcher. The searcher returned can either report
- /// exact matches of `needle` or act as a prefilter and report candidate
- /// positions of `needle`.
- ///
- /// If AVX2 is unavailable in the current environment or if a [`Pair`]
- /// could not be constructed from the needle given, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle: &[u8]) -> Option<Finder> {
- Finder::with_pair(needle, Pair::new(needle)?)
- }
-
- /// Create a new "packed pair" finder using the pair of bytes given.
- ///
- /// This constructor permits callers to control precisely which pair of
- /// bytes is used as a predicate.
- ///
- /// If AVX2 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn with_pair(needle: &[u8], pair: Pair) -> Option<Finder> {
- if Finder::is_available() {
- // SAFETY: we check that sse2/avx2 is available above. We are also
- // guaranteed to have needle.len() > 1 because we have a valid
- // Pair.
- unsafe { Some(Finder::with_pair_impl(needle, pair)) }
- } else {
- None
- }
- }
-
- /// Create a new `Finder` specific to SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as the safety for `packedpair::Finder::new`, and callers must also
- /// ensure that both SSE2 and AVX2 are available.
- #[target_feature(enable = "sse2", enable = "avx2")]
- #[inline]
- unsafe fn with_pair_impl(needle: &[u8], pair: Pair) -> Finder {
- let sse2 = packedpair::Finder::<__m128i>::new(needle, pair);
- let avx2 = packedpair::Finder::<__m256i>::new(needle, pair);
- Finder { sse2, avx2 }
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Finder::with_pair`] will
- /// return a `Some` value. Similarly, when it is false, it is guaranteed
- /// that `Finder::with_pair` will return a `None` value. Notice that this
- /// does not guarantee that [`Finder::new`] will return a `Finder`. Namely,
- /// even when `Finder::is_available` is true, it is not guaranteed that a
- /// valid [`Pair`] can be found from the needle given.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- #[cfg(target_feature = "sse2")]
- {
- #[cfg(target_feature = "avx2")]
- {
- true
- }
- #[cfg(not(target_feature = "avx2"))]
- {
- #[cfg(feature = "std")]
- {
- std::is_x86_feature_detected!("avx2")
- }
- #[cfg(not(feature = "std"))]
- {
- false
- }
- }
- }
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- // SAFETY: Building a `Finder` means it's safe to call 'sse2' routines.
- unsafe { self.find_impl(haystack, needle) }
- }
-
- /// Run this finder on the given haystack as a prefilter.
- ///
- /// If a candidate match is found, then an offset where the needle *could*
- /// begin in the haystack is returned.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find_prefilter(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: Building a `Finder` means it's safe to call 'sse2' routines.
- unsafe { self.find_prefilter_impl(haystack) }
- }
-
- /// Execute a search using AVX2 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `sse2` and `avx2` routines.)
- #[target_feature(enable = "sse2", enable = "avx2")]
- #[inline]
- unsafe fn find_impl(
- &self,
- haystack: &[u8],
- needle: &[u8],
- ) -> Option<usize> {
- if haystack.len() < self.avx2.min_haystack_len() {
- self.sse2.find(haystack, needle)
- } else {
- self.avx2.find(haystack, needle)
- }
- }
-
- /// Execute a prefilter search using AVX2 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `sse2` and `avx2` routines.)
- #[target_feature(enable = "sse2", enable = "avx2")]
- #[inline]
- unsafe fn find_prefilter_impl(&self, haystack: &[u8]) -> Option<usize> {
- if haystack.len() < self.avx2.min_haystack_len() {
- self.sse2.find_prefilter(haystack)
- } else {
- self.avx2.find_prefilter(haystack)
- }
- }
-
- /// Returns the pair of offsets (into the needle) used to check as a
- /// predicate before confirming whether a needle exists at a particular
- /// position.
- #[inline]
- pub fn pair(&self) -> &Pair {
- self.avx2.pair()
- }
-
- /// Returns the minimum haystack length that this `Finder` can search.
- ///
- /// Using a haystack with length smaller than this in a search will result
- /// in a panic. The reason for this restriction is that this finder is
- /// meant to be a low-level component that is part of a larger substring
- /// strategy. In that sense, it avoids trying to handle all cases and
- /// instead only handles the cases that it can handle very well.
- #[inline]
- pub fn min_haystack_len(&self) -> usize {
- // The caller doesn't need to care about AVX2's min_haystack_len
- // since this implementation will automatically switch to the SSE2
- // implementation if the haystack is too short for AVX2. Therefore, the
- // caller only needs to care about SSE2's min_haystack_len.
- //
- // This does assume that SSE2's min_haystack_len is less than or
- // equal to AVX2's min_haystack_len. In practice, this is true and
- // there is no way it could be false based on how this Finder is
- // implemented. Namely, both SSE2 and AVX2 use the same `Pair`. If
- // they used different pairs, then it's possible (although perhaps
- // pathological) for SSE2's min_haystack_len to be bigger than AVX2's.
- self.sse2.min_haystack_len()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- fn find(haystack: &[u8], needle: &[u8]) -> Option<Option<usize>> {
- let f = Finder::new(needle)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
-
- define_substring_forward_quickcheck!(find);
-
- #[test]
- fn forward_substring() {
- crate::tests::substring::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair_prefilter() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- if !cfg!(target_feature = "sse2") {
- return None;
- }
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find_prefilter(haystack))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-}
diff --git a/vendor/memchr/src/arch/x86_64/memchr.rs b/vendor/memchr/src/arch/x86_64/memchr.rs
deleted file mode 100644
index fcb1399..0000000
--- a/vendor/memchr/src/arch/x86_64/memchr.rs
+++ /dev/null
@@ -1,335 +0,0 @@
-/*!
-Wrapper routines for `memchr` and friends.
-
-These routines efficiently dispatch to the best implementation based on what
-the CPU supports.
-*/
-
-/// Provides a way to run a memchr-like function while amortizing the cost of
-/// runtime CPU feature detection.
-///
-/// This works by loading a function pointer from an atomic global. Initially,
-/// this global is set to a function that does CPU feature detection. For
-/// example, if AVX2 is enabled, then the AVX2 implementation is used.
-/// Otherwise, at least on x86_64, the SSE2 implementation is used. (And
-/// in some niche cases, if SSE2 isn't available, then the architecture
-/// independent fallback implementation is used.)
-///
-/// After the first call to this function, the atomic global is replaced with
-/// the specific AVX2, SSE2 or fallback routine chosen. Subsequent calls then
-/// will directly call the chosen routine instead of needing to go through the
-/// CPU feature detection branching again.
-///
-/// This particular macro is specifically written to provide the implementation
-/// of functions with the following signature:
-///
-/// ```ignore
-/// fn memchr(needle1: u8, start: *const u8, end: *const u8) -> Option<usize>;
-/// ```
-///
-/// Where you can also have `memchr2` and `memchr3`, but with `needle2` and
-/// `needle3`, respectively. The `start` and `end` parameters correspond to the
-/// start and end of the haystack, respectively.
-///
-/// We use raw pointers here instead of the more obvious `haystack: &[u8]` so
-/// that the function is compatible with our lower level iterator logic that
-/// operates on raw pointers. We use this macro to implement "raw" memchr
-/// routines with the signature above, and then define memchr routines using
-/// regular slices on top of them.
-///
-/// Note that we use `#[cfg(target_feature = "sse2")]` below even though
-/// it shouldn't be strictly necessary because without it, it seems to
-/// cause the compiler to blow up. I guess it can't handle a function
-/// pointer being created with a sse target feature? Dunno. See the
-/// `build-for-x86-64-but-non-sse-target` CI job if you want to experiment with
-/// this.
-///
-/// # Safety
-///
-/// Primarily callers must that `$fnty` is a correct function pointer type and
-/// not something else.
-///
-/// Callers must also ensure that `$memchrty::$memchrfind` corresponds to a
-/// routine that returns a valid function pointer when a match is found. That
-/// is, a pointer that is `>= start` and `< end`.
-///
-/// Callers must also ensure that the `$hay_start` and `$hay_end` identifiers
-/// correspond to valid pointers.
-macro_rules! unsafe_ifunc {
- (
- $memchrty:ident,
- $memchrfind:ident,
- $fnty:ty,
- $retty:ty,
- $hay_start:ident,
- $hay_end:ident,
- $($needle:ident),+
- ) => {{
- #![allow(unused_unsafe)]
-
- use core::sync::atomic::{AtomicPtr, Ordering};
-
- type Fn = *mut ();
- type RealFn = $fnty;
- static FN: AtomicPtr<()> = AtomicPtr::new(detect as Fn);
-
- #[cfg(target_feature = "sse2")]
- #[target_feature(enable = "sse2", enable = "avx2")]
- unsafe fn find_avx2(
- $($needle: u8),+,
- $hay_start: *const u8,
- $hay_end: *const u8,
- ) -> $retty {
- use crate::arch::x86_64::avx2::memchr::$memchrty;
- $memchrty::new_unchecked($($needle),+)
- .$memchrfind($hay_start, $hay_end)
- }
-
- #[cfg(target_feature = "sse2")]
- #[target_feature(enable = "sse2")]
- unsafe fn find_sse2(
- $($needle: u8),+,
- $hay_start: *const u8,
- $hay_end: *const u8,
- ) -> $retty {
- use crate::arch::x86_64::sse2::memchr::$memchrty;
- $memchrty::new_unchecked($($needle),+)
- .$memchrfind($hay_start, $hay_end)
- }
-
- unsafe fn find_fallback(
- $($needle: u8),+,
- $hay_start: *const u8,
- $hay_end: *const u8,
- ) -> $retty {
- use crate::arch::all::memchr::$memchrty;
- $memchrty::new($($needle),+).$memchrfind($hay_start, $hay_end)
- }
-
- unsafe fn detect(
- $($needle: u8),+,
- $hay_start: *const u8,
- $hay_end: *const u8,
- ) -> $retty {
- let fun = {
- #[cfg(not(target_feature = "sse2"))]
- {
- debug!(
- "no sse2 feature available, using fallback for {}",
- stringify!($memchrty),
- );
- find_fallback as RealFn
- }
- #[cfg(target_feature = "sse2")]
- {
- use crate::arch::x86_64::{sse2, avx2};
- if avx2::memchr::$memchrty::is_available() {
- debug!("chose AVX2 for {}", stringify!($memchrty));
- find_avx2 as RealFn
- } else if sse2::memchr::$memchrty::is_available() {
- debug!("chose SSE2 for {}", stringify!($memchrty));
- find_sse2 as RealFn
- } else {
- debug!("chose fallback for {}", stringify!($memchrty));
- find_fallback as RealFn
- }
- }
- };
- FN.store(fun as Fn, Ordering::Relaxed);
- // SAFETY: The only thing we need to uphold here is the
- // `#[target_feature]` requirements. Since we check is_available
- // above before using the corresponding implementation, we are
- // guaranteed to only call code that is supported on the current
- // CPU.
- fun($($needle),+, $hay_start, $hay_end)
- }
-
- // SAFETY: By virtue of the caller contract, RealFn is a function
- // pointer, which is always safe to transmute with a *mut (). Also,
- // since we use $memchrty::is_available, it is guaranteed to be safe
- // to call $memchrty::$memchrfind.
- unsafe {
- let fun = FN.load(Ordering::Relaxed);
- core::mem::transmute::<Fn, RealFn>(fun)(
- $($needle),+,
- $hay_start,
- $hay_end,
- )
- }
- }};
-}
-
-// The routines below dispatch to AVX2, SSE2 or a fallback routine based on
-// what's available in the current environment. The secret sauce here is that
-// we only check for which one to use approximately once, and then "cache" that
-// choice into a global function pointer. Subsequent invocations then just call
-// the appropriate function directly.
-
-/// memchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::find_raw`.
-#[inline(always)]
-pub(crate) fn memchr_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- // SAFETY: We provide a valid function pointer type.
- unsafe_ifunc!(
- One,
- find_raw,
- unsafe fn(u8, *const u8, *const u8) -> Option<*const u8>,
- Option<*const u8>,
- start,
- end,
- n1
- )
-}
-
-/// memrchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::rfind_raw`.
-#[inline(always)]
-pub(crate) fn memrchr_raw(
- n1: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- // SAFETY: We provide a valid function pointer type.
- unsafe_ifunc!(
- One,
- rfind_raw,
- unsafe fn(u8, *const u8, *const u8) -> Option<*const u8>,
- Option<*const u8>,
- start,
- end,
- n1
- )
-}
-
-/// memchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::find_raw`.
-#[inline(always)]
-pub(crate) fn memchr2_raw(
- n1: u8,
- n2: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- // SAFETY: We provide a valid function pointer type.
- unsafe_ifunc!(
- Two,
- find_raw,
- unsafe fn(u8, u8, *const u8, *const u8) -> Option<*const u8>,
- Option<*const u8>,
- start,
- end,
- n1,
- n2
- )
-}
-
-/// memrchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::rfind_raw`.
-#[inline(always)]
-pub(crate) fn memrchr2_raw(
- n1: u8,
- n2: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- // SAFETY: We provide a valid function pointer type.
- unsafe_ifunc!(
- Two,
- rfind_raw,
- unsafe fn(u8, u8, *const u8, *const u8) -> Option<*const u8>,
- Option<*const u8>,
- start,
- end,
- n1,
- n2
- )
-}
-
-/// memchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::find_raw`.
-#[inline(always)]
-pub(crate) fn memchr3_raw(
- n1: u8,
- n2: u8,
- n3: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- // SAFETY: We provide a valid function pointer type.
- unsafe_ifunc!(
- Three,
- find_raw,
- unsafe fn(u8, u8, u8, *const u8, *const u8) -> Option<*const u8>,
- Option<*const u8>,
- start,
- end,
- n1,
- n2,
- n3
- )
-}
-
-/// memrchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::rfind_raw`.
-#[inline(always)]
-pub(crate) fn memrchr3_raw(
- n1: u8,
- n2: u8,
- n3: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- // SAFETY: We provide a valid function pointer type.
- unsafe_ifunc!(
- Three,
- rfind_raw,
- unsafe fn(u8, u8, u8, *const u8, *const u8) -> Option<*const u8>,
- Option<*const u8>,
- start,
- end,
- n1,
- n2,
- n3
- )
-}
-
-/// Count all matching bytes, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::count_raw`.
-#[inline(always)]
-pub(crate) fn count_raw(n1: u8, start: *const u8, end: *const u8) -> usize {
- // SAFETY: We provide a valid function pointer type.
- unsafe_ifunc!(
- One,
- count_raw,
- unsafe fn(u8, *const u8, *const u8) -> usize,
- usize,
- start,
- end,
- n1
- )
-}
diff --git a/vendor/memchr/src/arch/x86_64/mod.rs b/vendor/memchr/src/arch/x86_64/mod.rs
deleted file mode 100644
index 5dad721..0000000
--- a/vendor/memchr/src/arch/x86_64/mod.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-/*!
-Vector algorithms for the `x86_64` target.
-*/
-
-pub mod avx2;
-pub mod sse2;
-
-pub(crate) mod memchr;
diff --git a/vendor/memchr/src/arch/x86_64/sse2/memchr.rs b/vendor/memchr/src/arch/x86_64/sse2/memchr.rs
deleted file mode 100644
index c6f75df..0000000
--- a/vendor/memchr/src/arch/x86_64/sse2/memchr.rs
+++ /dev/null
@@ -1,1077 +0,0 @@
-/*!
-This module defines 128-bit vector implementations of `memchr` and friends.
-
-The main types in this module are [`One`], [`Two`] and [`Three`]. They are for
-searching for one, two or three distinct bytes, respectively, in a haystack.
-Each type also has corresponding double ended iterators. These searchers are
-typically much faster than scalar routines accomplishing the same task.
-
-The `One` searcher also provides a [`One::count`] routine for efficiently
-counting the number of times a single byte occurs in a haystack. This is
-useful, for example, for counting the number of lines in a haystack. This
-routine exists because it is usually faster, especially with a high match
-count, then using [`One::find`] repeatedly. ([`OneIter`] specializes its
-`Iterator::count` implementation to use this routine.)
-
-Only one, two and three bytes are supported because three bytes is about
-the point where one sees diminishing returns. Beyond this point and it's
-probably (but not necessarily) better to just use a simple `[bool; 256]` array
-or similar. However, it depends mightily on the specific work-load and the
-expected match frequency.
-*/
-
-use core::arch::x86_64::__m128i;
-
-use crate::{arch::generic::memchr as generic, ext::Pointer, vector::Vector};
-
-/// Finds all occurrences of a single byte in a haystack.
-#[derive(Clone, Copy, Debug)]
-pub struct One(generic::One<__m128i>);
-
-impl One {
- /// Create a new searcher that finds occurrences of the needle byte given.
- ///
- /// This particular searcher is specialized to use SSE2 vector instructions
- /// that typically make it quite fast.
- ///
- /// If SSE2 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle: u8) -> Option<One> {
- if One::is_available() {
- // SAFETY: we check that sse2 is available above.
- unsafe { Some(One::new_unchecked(needle)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to SSE2 vectors and routines without
- /// checking that SSE2 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `sse2` instructions
- /// in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to SSE2
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "sse2")]
- #[inline]
- pub unsafe fn new_unchecked(needle: u8) -> One {
- One(generic::One::new(needle))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`One::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `One::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "sse2")]
- {
- true
- }
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Counts all occurrences of this byte in the given haystack.
- #[inline]
- pub fn count(&self, haystack: &[u8]) -> usize {
- // SAFETY: All of our pointers are derived directly from a borrowed
- // slice, which is guaranteed to be valid.
- unsafe {
- let start = haystack.as_ptr();
- let end = start.add(haystack.len());
- self.count_raw(start, end)
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'sse2' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- //
- // Note that we could call `self.0.find_raw` directly here. But that
- // means we'd have to annotate this routine with `target_feature`.
- // Which is fine, because this routine is `unsafe` anyway and the
- // `target_feature` obligation is met by virtue of building a `One`.
- // The real problem is that a routine with a `target_feature`
- // annotation generally can't be inlined into caller code unless the
- // caller code has the same target feature annotations. Which is maybe
- // okay for SSE2, but we do the same thing for AVX2 where caller code
- // probably usually doesn't have AVX2 enabled. That means that this
- // routine can be inlined which will handle some of the short-haystack
- // cases above without touching the architecture specific code.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'sse2' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- //
- // See note in forward routine above for why we don't just call
- // `self.0.rfind_raw` directly here.
- self.rfind_raw_impl(start, end)
- }
-
- /// Counts all occurrences of this byte in the given haystack represented
- /// by raw pointers.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `0` will always be returned.
- #[inline]
- pub unsafe fn count_raw(&self, start: *const u8, end: *const u8) -> usize {
- if start >= end {
- return 0;
- }
- if end.distance(start) < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::count_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- });
- }
- // SAFETY: Building a `One` means it's safe to call 'sse2' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- self.count_raw_impl(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Execute a count using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`One::count_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `One`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn count_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> usize {
- self.0.count_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> OneIter<'a, 'h> {
- OneIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of a single byte in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`One::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`One`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct OneIter<'a, 'h> {
- searcher: &'a One,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for OneIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn count(self) -> usize {
- self.it.count(|s, e| {
- // SAFETY: We rely on our generic iterator to return valid start
- // and end pointers.
- unsafe { self.searcher.count_raw(s, e) }
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for OneIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for OneIter<'a, 'h> {}
-
-/// Finds all occurrences of two bytes in a haystack.
-///
-/// That is, this reports matches of one of two possible bytes. For example,
-/// searching for `a` or `b` in `afoobar` would report matches at offsets `0`,
-/// `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Two(generic::Two<__m128i>);
-
-impl Two {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use SSE2 vector instructions
- /// that typically make it quite fast.
- ///
- /// If SSE2 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8) -> Option<Two> {
- if Two::is_available() {
- // SAFETY: we check that sse2 is available above.
- unsafe { Some(Two::new_unchecked(needle1, needle2)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to SSE2 vectors and routines without
- /// checking that SSE2 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `sse2` instructions
- /// in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to SSE2
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "sse2")]
- #[inline]
- pub unsafe fn new_unchecked(needle1: u8, needle2: u8) -> Two {
- Two(generic::Two::new(needle1, needle2))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Two::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Two::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "sse2")]
- {
- true
- }
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1() || b == self.0.needle2()
- });
- }
- // SAFETY: Building a `Two` means it's safe to call 'sse2' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- //
- // Note that we could call `self.0.find_raw` directly here. But that
- // means we'd have to annotate this routine with `target_feature`.
- // Which is fine, because this routine is `unsafe` anyway and the
- // `target_feature` obligation is met by virtue of building a `Two`.
- // The real problem is that a routine with a `target_feature`
- // annotation generally can't be inlined into caller code unless the
- // caller code has the same target feature annotations. Which is maybe
- // okay for SSE2, but we do the same thing for AVX2 where caller code
- // probably usually doesn't have AVX2 enabled. That means that this
- // routine can be inlined which will handle some of the short-haystack
- // cases above without touching the architecture specific code.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1() || b == self.0.needle2()
- });
- }
- // SAFETY: Building a `Two` means it's safe to call 'sse2' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- //
- // See note in forward routine above for why we don't just call
- // `self.0.rfind_raw` directly here.
- self.rfind_raw_impl(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Two::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Two`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle bytes in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> TwoIter<'a, 'h> {
- TwoIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of two possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Two::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Two`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct TwoIter<'a, 'h> {
- searcher: &'a Two,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for TwoIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for TwoIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for TwoIter<'a, 'h> {}
-
-/// Finds all occurrences of three bytes in a haystack.
-///
-/// That is, this reports matches of one of three possible bytes. For example,
-/// searching for `a`, `b` or `o` in `afoobar` would report matches at offsets
-/// `0`, `2`, `3`, `4` and `5`.
-#[derive(Clone, Copy, Debug)]
-pub struct Three(generic::Three<__m128i>);
-
-impl Three {
- /// Create a new searcher that finds occurrences of the needle bytes given.
- ///
- /// This particular searcher is specialized to use SSE2 vector instructions
- /// that typically make it quite fast.
- ///
- /// If SSE2 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle1: u8, needle2: u8, needle3: u8) -> Option<Three> {
- if Three::is_available() {
- // SAFETY: we check that sse2 is available above.
- unsafe { Some(Three::new_unchecked(needle1, needle2, needle3)) }
- } else {
- None
- }
- }
-
- /// Create a new finder specific to SSE2 vectors and routines without
- /// checking that SSE2 is available.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that it is safe to execute `sse2` instructions
- /// in the current environment.
- ///
- /// Note that it is a common misconception that if one compiles for an
- /// `x86_64` target, then they therefore automatically have access to SSE2
- /// instructions. While this is almost always the case, it isn't true in
- /// 100% of cases.
- #[target_feature(enable = "sse2")]
- #[inline]
- pub unsafe fn new_unchecked(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- ) -> Three {
- Three(generic::Three::new(needle1, needle2, needle3))
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Three::new`] will return
- /// a `Some` value. Similarly, when it is false, it is guaranteed that
- /// `Three::new` will return a `None` value.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(target_feature = "sse2")]
- {
- true
- }
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- }
-
- /// Return the first occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `find_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.find_raw(s, e)
- })
- }
- }
-
- /// Return the last occurrence of one of the needle bytes in the given
- /// haystack. If no such occurrence exists, then `None` is returned.
- ///
- /// The occurrence is reported as an offset into `haystack`. Its maximum
- /// value is `haystack.len() - 1`.
- #[inline]
- pub fn rfind(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: `rfind_raw` guarantees that if a pointer is returned, it
- // falls within the bounds of the start and end pointers.
- unsafe {
- generic::search_slice_with_raw(haystack, |s, e| {
- self.rfind_raw(s, e)
- })
- }
- }
-
- /// Like `find`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn find_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::fwd_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- || b == self.0.needle2()
- || b == self.0.needle3()
- });
- }
- // SAFETY: Building a `Three` means it's safe to call 'sse2' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- //
- // Note that we could call `self.0.find_raw` directly here. But that
- // means we'd have to annotate this routine with `target_feature`.
- // Which is fine, because this routine is `unsafe` anyway and the
- // `target_feature` obligation is met by virtue of building a `Three`.
- // The real problem is that a routine with a `target_feature`
- // annotation generally can't be inlined into caller code unless the
- // caller code has the same target feature annotations. Which is maybe
- // okay for SSE2, but we do the same thing for AVX2 where caller code
- // probably usually doesn't have AVX2 enabled. That means that this
- // routine can be inlined which will handle some of the short-haystack
- // cases above without touching the architecture specific code.
- self.find_raw_impl(start, end)
- }
-
- /// Like `rfind`, but accepts and returns raw pointers.
- ///
- /// When a match is found, the pointer returned is guaranteed to be
- /// `>= start` and `< end`.
- ///
- /// This routine is useful if you're already using raw pointers and would
- /// like to avoid converting back to a slice before executing a search.
- ///
- /// # Safety
- ///
- /// * Both `start` and `end` must be valid for reads.
- /// * Both `start` and `end` must point to an initialized value.
- /// * Both `start` and `end` must point to the same allocated object and
- /// must either be in bounds or at most one byte past the end of the
- /// allocated object.
- /// * Both `start` and `end` must be _derived from_ a pointer to the same
- /// object.
- /// * The distance between `start` and `end` must not overflow `isize`.
- /// * The distance being in bounds must not rely on "wrapping around" the
- /// address space.
- ///
- /// Note that callers may pass a pair of pointers such that `start >= end`.
- /// In that case, `None` will always be returned.
- #[inline]
- pub unsafe fn rfind_raw(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- if start >= end {
- return None;
- }
- if end.distance(start) < __m128i::BYTES {
- // SAFETY: We require the caller to pass valid start/end pointers.
- return generic::rev_byte_by_byte(start, end, |b| {
- b == self.0.needle1()
- || b == self.0.needle2()
- || b == self.0.needle3()
- });
- }
- // SAFETY: Building a `Three` means it's safe to call 'sse2' routines.
- // Also, we've checked that our haystack is big enough to run on the
- // vector routine. Pointer validity is caller's responsibility.
- //
- // See note in forward routine above for why we don't just call
- // `self.0.rfind_raw` directly here.
- self.rfind_raw_impl(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::find_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.find_raw(start, end)
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as [`Three::rfind_raw`], except the distance between `start` and
- /// `end` must be at least the size of an SSE2 vector (in bytes).
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Three`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn rfind_raw_impl(
- &self,
- start: *const u8,
- end: *const u8,
- ) -> Option<*const u8> {
- self.0.rfind_raw(start, end)
- }
-
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[inline]
- pub fn iter<'a, 'h>(&'a self, haystack: &'h [u8]) -> ThreeIter<'a, 'h> {
- ThreeIter { searcher: self, it: generic::Iter::new(haystack) }
- }
-}
-
-/// An iterator over all occurrences of three possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`Three::iter`] method.
-///
-/// The lifetime parameters are as follows:
-///
-/// * `'a` refers to the lifetime of the underlying [`Three`] searcher.
-/// * `'h` refers to the lifetime of the haystack being searched.
-#[derive(Clone, Debug)]
-pub struct ThreeIter<'a, 'h> {
- searcher: &'a Three,
- it: generic::Iter<'h>,
-}
-
-impl<'a, 'h> Iterator for ThreeIter<'a, 'h> {
- type Item = usize;
-
- #[inline]
- fn next(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'find_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next(|s, e| self.searcher.find_raw(s, e)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.it.size_hint()
- }
-}
-
-impl<'a, 'h> DoubleEndedIterator for ThreeIter<'a, 'h> {
- #[inline]
- fn next_back(&mut self) -> Option<usize> {
- // SAFETY: We rely on the generic iterator to provide valid start
- // and end pointers, but we guarantee that any pointer returned by
- // 'rfind_raw' falls within the bounds of the start and end pointer.
- unsafe { self.it.next_back(|s, e| self.searcher.rfind_raw(s, e)) }
- }
-}
-
-impl<'a, 'h> core::iter::FusedIterator for ThreeIter<'a, 'h> {}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_memchr_quickcheck!(super);
-
- #[test]
- fn forward_one() {
- crate::tests::memchr::Runner::new(1).forward_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_one() {
- crate::tests::memchr::Runner::new(1).reverse_iter(
- |haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn count_one() {
- crate::tests::memchr::Runner::new(1).count_iter(|haystack, needles| {
- Some(One::new(needles[0])?.iter(haystack).count())
- })
- }
-
- #[test]
- fn forward_two() {
- crate::tests::memchr::Runner::new(2).forward_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_two() {
- crate::tests::memchr::Runner::new(2).reverse_iter(
- |haystack, needles| {
- let n1 = needles.get(0).copied()?;
- let n2 = needles.get(1).copied()?;
- Some(Two::new(n1, n2)?.iter(haystack).rev().collect())
- },
- )
- }
-
- #[test]
- fn forward_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).collect())
- },
- )
- }
-
- #[test]
- fn reverse_three() {
- 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(Three::new(n1, n2, n3)?.iter(haystack).rev().collect())
- },
- )
- }
-}
diff --git a/vendor/memchr/src/arch/x86_64/sse2/mod.rs b/vendor/memchr/src/arch/x86_64/sse2/mod.rs
deleted file mode 100644
index bcb8307..0000000
--- a/vendor/memchr/src/arch/x86_64/sse2/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
-Algorithms for the `x86_64` target using 128-bit vectors via SSE2.
-*/
-
-pub mod memchr;
-pub mod packedpair;
diff --git a/vendor/memchr/src/arch/x86_64/sse2/packedpair.rs b/vendor/memchr/src/arch/x86_64/sse2/packedpair.rs
deleted file mode 100644
index c8b5b99..0000000
--- a/vendor/memchr/src/arch/x86_64/sse2/packedpair.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-/*!
-A 128-bit vector implementation of the "packed pair" SIMD algorithm.
-
-The "packed pair" algorithm is based on the [generic SIMD] algorithm. The main
-difference is that it (by default) uses a background distribution of byte
-frequencies to heuristically select the pair of bytes to search for.
-
-[generic SIMD]: http://0x80.pl/articles/simd-strfind.html#first-and-last
-*/
-
-use core::arch::x86_64::__m128i;
-
-use crate::arch::{all::packedpair::Pair, generic::packedpair};
-
-/// A "packed pair" finder that uses 128-bit vector operations.
-///
-/// This finder picks two bytes that it believes have high predictive power
-/// for indicating an overall match of a needle. Depending on whether
-/// `Finder::find` or `Finder::find_prefilter` is used, it reports offsets
-/// where the needle matches or could match. In the prefilter case, candidates
-/// are reported whenever the [`Pair`] of bytes given matches.
-#[derive(Clone, Copy, Debug)]
-pub struct Finder(packedpair::Finder<__m128i>);
-
-impl Finder {
- /// Create a new pair searcher. The searcher returned can either report
- /// exact matches of `needle` or act as a prefilter and report candidate
- /// positions of `needle`.
- ///
- /// If SSE2 is unavailable in the current environment or if a [`Pair`]
- /// could not be constructed from the needle given, then `None` is
- /// returned.
- #[inline]
- pub fn new(needle: &[u8]) -> Option<Finder> {
- Finder::with_pair(needle, Pair::new(needle)?)
- }
-
- /// Create a new "packed pair" finder using the pair of bytes given.
- ///
- /// This constructor permits callers to control precisely which pair of
- /// bytes is used as a predicate.
- ///
- /// If SSE2 is unavailable in the current environment, then `None` is
- /// returned.
- #[inline]
- pub fn with_pair(needle: &[u8], pair: Pair) -> Option<Finder> {
- if Finder::is_available() {
- // SAFETY: we check that sse2 is available above. We are also
- // guaranteed to have needle.len() > 1 because we have a valid
- // Pair.
- unsafe { Some(Finder::with_pair_impl(needle, pair)) }
- } else {
- None
- }
- }
-
- /// Create a new `Finder` specific to SSE2 vectors and routines.
- ///
- /// # Safety
- ///
- /// Same as the safety for `packedpair::Finder::new`, and callers must also
- /// ensure that SSE2 is available.
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn with_pair_impl(needle: &[u8], pair: Pair) -> Finder {
- let finder = packedpair::Finder::<__m128i>::new(needle, pair);
- Finder(finder)
- }
-
- /// Returns true when this implementation is available in the current
- /// environment.
- ///
- /// When this is true, it is guaranteed that [`Finder::with_pair`] will
- /// return a `Some` value. Similarly, when it is false, it is guaranteed
- /// that `Finder::with_pair` will return a `None` value. Notice that this
- /// does not guarantee that [`Finder::new`] will return a `Finder`. Namely,
- /// even when `Finder::is_available` is true, it is not guaranteed that a
- /// valid [`Pair`] can be found from the needle given.
- ///
- /// Note also that for the lifetime of a single program, if this returns
- /// true then it will always return true.
- #[inline]
- pub fn is_available() -> bool {
- #[cfg(not(target_feature = "sse2"))]
- {
- false
- }
- #[cfg(target_feature = "sse2")]
- {
- true
- }
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
- // SAFETY: Building a `Finder` means it's safe to call 'sse2' routines.
- unsafe { self.find_impl(haystack, needle) }
- }
-
- /// Run this finder on the given haystack as a prefilter.
- ///
- /// If a candidate match is found, then an offset where the needle *could*
- /// begin in the haystack is returned.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- #[inline]
- pub fn find_prefilter(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: Building a `Finder` means it's safe to call 'sse2' routines.
- unsafe { self.find_prefilter_impl(haystack) }
- }
-
- /// Execute a search using SSE2 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_impl(
- &self,
- haystack: &[u8],
- needle: &[u8],
- ) -> Option<usize> {
- self.0.find(haystack, needle)
- }
-
- /// Execute a prefilter search using SSE2 vectors and routines.
- ///
- /// # Panics
- ///
- /// When `haystack.len()` is less than [`Finder::min_haystack_len`].
- ///
- /// # Safety
- ///
- /// (The target feature safety obligation is automatically fulfilled by
- /// virtue of being a method on `Finder`, which can only be constructed
- /// when it is safe to call `sse2` routines.)
- #[target_feature(enable = "sse2")]
- #[inline]
- unsafe fn find_prefilter_impl(&self, haystack: &[u8]) -> Option<usize> {
- self.0.find_prefilter(haystack)
- }
-
- /// Returns the pair of offsets (into the needle) used to check as a
- /// predicate before confirming whether a needle exists at a particular
- /// position.
- #[inline]
- pub fn pair(&self) -> &Pair {
- self.0.pair()
- }
-
- /// Returns the minimum haystack length that this `Finder` can search.
- ///
- /// Using a haystack with length smaller than this in a search will result
- /// in a panic. The reason for this restriction is that this finder is
- /// meant to be a low-level component that is part of a larger substring
- /// strategy. In that sense, it avoids trying to handle all cases and
- /// instead only handles the cases that it can handle very well.
- #[inline]
- pub fn min_haystack_len(&self) -> usize {
- self.0.min_haystack_len()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- fn find(haystack: &[u8], needle: &[u8]) -> Option<Option<usize>> {
- let f = Finder::new(needle)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
-
- define_substring_forward_quickcheck!(find);
-
- #[test]
- fn forward_substring() {
- crate::tests::substring::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find(haystack, needle))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-
- #[test]
- fn forward_packedpair_prefilter() {
- fn find(
- haystack: &[u8],
- needle: &[u8],
- index1: u8,
- index2: u8,
- ) -> Option<Option<usize>> {
- let pair = Pair::with_indices(needle, index1, index2)?;
- let f = Finder::with_pair(needle, pair)?;
- if haystack.len() < f.min_haystack_len() {
- return None;
- }
- Some(f.find_prefilter(haystack))
- }
- crate::tests::packedpair::Runner::new().fwd(find).run()
- }
-}
diff --git a/vendor/memchr/src/cow.rs b/vendor/memchr/src/cow.rs
deleted file mode 100644
index f291645..0000000
--- a/vendor/memchr/src/cow.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-use core::ops;
-
-/// A specialized copy-on-write byte string.
-///
-/// The purpose of this type is to permit usage of a "borrowed or owned
-/// byte string" in a way that keeps std/no-std compatibility. That is, in
-/// no-std/alloc mode, this type devolves into a simple &[u8] with no owned
-/// variant available. We can't just use a plain Cow because Cow is not in
-/// core.
-#[derive(Clone, Debug)]
-pub struct CowBytes<'a>(Imp<'a>);
-
-// N.B. We don't use alloc::borrow::Cow here since we can get away with a
-// Box<[u8]> for our use case, which is 1/3 smaller than the Vec<u8> that
-// a Cow<[u8]> would use.
-#[cfg(feature = "alloc")]
-#[derive(Clone, Debug)]
-enum Imp<'a> {
- Borrowed(&'a [u8]),
- Owned(alloc::boxed::Box<[u8]>),
-}
-
-#[cfg(not(feature = "alloc"))]
-#[derive(Clone, Debug)]
-struct Imp<'a>(&'a [u8]);
-
-impl<'a> ops::Deref for CowBytes<'a> {
- type Target = [u8];
-
- #[inline(always)]
- fn deref(&self) -> &[u8] {
- self.as_slice()
- }
-}
-
-impl<'a> CowBytes<'a> {
- /// Create a new borrowed CowBytes.
- #[inline(always)]
- pub(crate) fn new<B: ?Sized + AsRef<[u8]>>(bytes: &'a B) -> CowBytes<'a> {
- CowBytes(Imp::new(bytes.as_ref()))
- }
-
- /// Create a new owned CowBytes.
- #[cfg(feature = "alloc")]
- #[inline(always)]
- fn new_owned(bytes: alloc::boxed::Box<[u8]>) -> CowBytes<'static> {
- CowBytes(Imp::Owned(bytes))
- }
-
- /// Return a borrowed byte string, regardless of whether this is an owned
- /// or borrowed byte string internally.
- #[inline(always)]
- pub(crate) fn as_slice(&self) -> &[u8] {
- self.0.as_slice()
- }
-
- /// Return an owned version of this copy-on-write byte string.
- ///
- /// If this is already an owned byte string internally, then this is a
- /// no-op. Otherwise, the internal byte string is copied.
- #[cfg(feature = "alloc")]
- #[inline(always)]
- pub(crate) fn into_owned(self) -> CowBytes<'static> {
- match self.0 {
- Imp::Borrowed(b) => {
- CowBytes::new_owned(alloc::boxed::Box::from(b))
- }
- Imp::Owned(b) => CowBytes::new_owned(b),
- }
- }
-}
-
-impl<'a> Imp<'a> {
- #[inline(always)]
- pub fn new(bytes: &'a [u8]) -> Imp<'a> {
- #[cfg(feature = "alloc")]
- {
- Imp::Borrowed(bytes)
- }
- #[cfg(not(feature = "alloc"))]
- {
- Imp(bytes)
- }
- }
-
- #[cfg(feature = "alloc")]
- #[inline(always)]
- pub fn as_slice(&self) -> &[u8] {
- #[cfg(feature = "alloc")]
- {
- match self {
- Imp::Owned(ref x) => x,
- Imp::Borrowed(x) => x,
- }
- }
- #[cfg(not(feature = "alloc"))]
- {
- self.0
- }
- }
-
- #[cfg(not(feature = "alloc"))]
- #[inline(always)]
- pub fn as_slice(&self) -> &[u8] {
- self.0
- }
-}
diff --git a/vendor/memchr/src/ext.rs b/vendor/memchr/src/ext.rs
deleted file mode 100644
index 1bb21dd..0000000
--- a/vendor/memchr/src/ext.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-/// A trait for adding some helper routines to pointers.
-pub(crate) trait Pointer {
- /// Returns the distance, in units of `T`, between `self` and `origin`.
- ///
- /// # Safety
- ///
- /// Same as `ptr::offset_from` in addition to `self >= origin`.
- unsafe fn distance(self, origin: Self) -> usize;
-
- /// Casts this pointer to `usize`.
- ///
- /// Callers should not convert the `usize` back to a pointer if at all
- /// possible. (And if you believe it's necessary, open an issue to discuss
- /// why. Otherwise, it has the potential to violate pointer provenance.)
- /// The purpose of this function is just to be able to do arithmetic, i.e.,
- /// computing offsets or alignments.
- fn as_usize(self) -> usize;
-}
-
-impl<T> Pointer for *const T {
- unsafe fn distance(self, origin: *const T) -> usize {
- // TODO: Replace with `ptr::sub_ptr` once stabilized.
- usize::try_from(self.offset_from(origin)).unwrap_unchecked()
- }
-
- fn as_usize(self) -> usize {
- self as usize
- }
-}
-
-impl<T> Pointer for *mut T {
- unsafe fn distance(self, origin: *mut T) -> usize {
- (self as *const T).distance(origin as *const T)
- }
-
- fn as_usize(self) -> usize {
- (self as *const T).as_usize()
- }
-}
-
-/// A trait for adding some helper routines to raw bytes.
-pub(crate) trait Byte {
- /// Converts this byte to a `char` if it's ASCII. Otherwise panics.
- fn to_char(self) -> char;
-}
-
-impl Byte for u8 {
- fn to_char(self) -> char {
- assert!(self.is_ascii());
- char::from(self)
- }
-}
diff --git a/vendor/memchr/src/lib.rs b/vendor/memchr/src/lib.rs
deleted file mode 100644
index de366fb..0000000
--- a/vendor/memchr/src/lib.rs
+++ /dev/null
@@ -1,221 +0,0 @@
-/*!
-This library provides heavily optimized routines for string search primitives.
-
-# Overview
-
-This section gives a brief high level overview of what this crate offers.
-
-* The top-level module provides routines for searching for 1, 2 or 3 bytes
- in the forward or reverse direction. When searching for more than one byte,
- positions are considered a match if the byte at that position matches any
- of the bytes.
-* The [`memmem`] sub-module provides forward and reverse substring search
- routines.
-
-In all such cases, routines operate on `&[u8]` without regard to encoding. This
-is exactly what you want when searching either UTF-8 or arbitrary bytes.
-
-# Example: using `memchr`
-
-This example shows how to use `memchr` to find the first occurrence of `z` in
-a haystack:
-
-```
-use memchr::memchr;
-
-let haystack = b"foo bar baz quuz";
-assert_eq!(Some(10), memchr(b'z', haystack));
-```
-
-# Example: matching one of three possible bytes
-
-This examples shows how to use `memrchr3` to find occurrences of `a`, `b` or
-`c`, starting at the end of the haystack.
-
-```
-use memchr::memchr3_iter;
-
-let haystack = b"xyzaxyzbxyzc";
-
-let mut it = memchr3_iter(b'a', b'b', b'c', haystack).rev();
-assert_eq!(Some(11), it.next());
-assert_eq!(Some(7), it.next());
-assert_eq!(Some(3), it.next());
-assert_eq!(None, it.next());
-```
-
-# Example: iterating over substring matches
-
-This example shows how to use the [`memmem`] sub-module to find occurrences of
-a substring in a haystack.
-
-```
-use memchr::memmem;
-
-let haystack = b"foo bar foo baz foo";
-
-let mut it = memmem::find_iter(haystack, "foo");
-assert_eq!(Some(0), it.next());
-assert_eq!(Some(8), it.next());
-assert_eq!(Some(16), it.next());
-assert_eq!(None, it.next());
-```
-
-# Example: repeating a search for the same needle
-
-It may be possible for the overhead of constructing a substring searcher to be
-measurable in some workloads. In cases where the same needle is used to search
-many haystacks, it is possible to do construction once and thus to avoid it for
-subsequent searches. This can be done with a [`memmem::Finder`]:
-
-```
-use memchr::memmem;
-
-let finder = memmem::Finder::new("foo");
-
-assert_eq!(Some(4), finder.find(b"baz foo quux"));
-assert_eq!(None, finder.find(b"quux baz bar"));
-```
-
-# Why use this crate?
-
-At first glance, the APIs provided by this crate might seem weird. Why provide
-a dedicated routine like `memchr` for something that could be implemented
-clearly and trivially in one line:
-
-```
-fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().position(|&b| b == needle)
-}
-```
-
-Or similarly, why does this crate provide substring search routines when Rust's
-core library already provides them?
-
-```
-fn search(haystack: &str, needle: &str) -> Option<usize> {
- haystack.find(needle)
-}
-```
-
-The primary reason for both of them to exist is performance. When it comes to
-performance, at a high level at least, there are two primary ways to look at
-it:
-
-* **Throughput**: For this, think about it as, "given some very large haystack
- and a byte that never occurs in that haystack, how long does it take to
- search through it and determine that it, in fact, does not occur?"
-* **Latency**: For this, think about it as, "given a tiny haystack---just a
- few bytes---how long does it take to determine if a byte is in it?"
-
-The `memchr` routine in this crate has _slightly_ worse latency than the
-solution presented above, however, its throughput can easily be over an
-order of magnitude faster. This is a good general purpose trade off to make.
-You rarely lose, but often gain big.
-
-**NOTE:** The name `memchr` comes from the corresponding routine in `libc`. A
-key advantage of using this library is that its performance is not tied to its
-quality of implementation in the `libc` you happen to be using, which can vary
-greatly from platform to platform.
-
-But what about substring search? This one is a bit more complicated. The
-primary reason for its existence is still indeed performance, but it's also
-useful because Rust's core library doesn't actually expose any substring
-search routine on arbitrary bytes. The only substring search routine that
-exists works exclusively on valid UTF-8.
-
-So if you have valid UTF-8, is there a reason to use this over the standard
-library substring search routine? Yes. This routine is faster on almost every
-metric, including latency. The natural question then, is why isn't this
-implementation in the standard library, even if only for searching on UTF-8?
-The reason is that the implementation details for using SIMD in the standard
-library haven't quite been worked out yet.
-
-**NOTE:** Currently, only `x86_64`, `wasm32` and `aarch64` targets have vector
-accelerated implementations of `memchr` (and friends) and `memmem`.
-
-# Crate features
-
-* **std** - When enabled (the default), this will permit features specific to
-the standard library. Currently, the only thing used from the standard library
-is runtime SIMD CPU feature detection. This means that this feature must be
-enabled to get AVX2 accelerated routines on `x86_64` targets without enabling
-the `avx2` feature at compile time, for example. When `std` is not enabled,
-this crate will still attempt to use SSE2 accelerated routines on `x86_64`. It
-will also use AVX2 accelerated routines when the `avx2` feature is enabled at
-compile time. In general, enable this feature if you can.
-* **alloc** - When enabled (the default), APIs in this crate requiring some
-kind of allocation will become available. For example, the
-[`memmem::Finder::into_owned`](crate::memmem::Finder::into_owned) API and the
-[`arch::all::shiftor`](crate::arch::all::shiftor) substring search
-implementation. Otherwise, this crate is designed from the ground up to be
-usable in core-only contexts, so the `alloc` feature doesn't add much
-currently. Notably, disabling `std` but enabling `alloc` will **not** result
-in the use of AVX2 on `x86_64` targets unless the `avx2` feature is enabled
-at compile time. (With `std` enabled, AVX2 can be used even without the `avx2`
-feature enabled at compile time by way of runtime CPU feature detection.)
-* **logging** - When enabled (disabled by default), the `log` crate is used
-to emit log messages about what kinds of `memchr` and `memmem` algorithms
-are used. Namely, both `memchr` and `memmem` have a number of different
-implementation choices depending on the target and CPU, and the log messages
-can help show what specific implementations are being used. Generally, this is
-useful for debugging performance issues.
-* **libc** - **DEPRECATED**. Previously, this enabled the use of the target's
-`memchr` function from whatever `libc` was linked into the program. This
-feature is now a no-op because this crate's implementation of `memchr` should
-now be sufficiently fast on a number of platforms that `libc` should no longer
-be needed. (This feature is somewhat of a holdover from this crate's origins.
-Originally, this crate was literally just a safe wrapper function around the
-`memchr` function from `libc`.)
-*/
-
-#![deny(missing_docs)]
-#![no_std]
-// It's just not worth trying to squash all dead code warnings. Pretty
-// unfortunate IMO. Not really sure how to fix this other than to either
-// live with it or sprinkle a whole mess of `cfg` annotations everywhere.
-#![cfg_attr(
- not(any(
- all(target_arch = "x86_64", target_feature = "sse2"),
- target_arch = "wasm32",
- target_arch = "aarch64",
- )),
- allow(dead_code)
-)]
-// Same deal for miri.
-#![cfg_attr(miri, allow(dead_code, unused_macros))]
-
-// Supporting 8-bit (or others) would be fine. If you need it, please submit a
-// bug report at https://github.com/BurntSushi/memchr
-#[cfg(not(any(
- target_pointer_width = "16",
- target_pointer_width = "32",
- target_pointer_width = "64"
-)))]
-compile_error!("memchr currently not supported on non-{16,32,64}");
-
-#[cfg(any(test, feature = "std"))]
-extern crate std;
-
-#[cfg(any(test, feature = "alloc"))]
-extern crate alloc;
-
-pub use crate::memchr::{
- memchr, memchr2, memchr2_iter, memchr3, memchr3_iter, memchr_iter,
- memrchr, memrchr2, memrchr2_iter, memrchr3, memrchr3_iter, memrchr_iter,
- Memchr, Memchr2, Memchr3,
-};
-
-#[macro_use]
-mod macros;
-
-#[cfg(test)]
-#[macro_use]
-mod tests;
-
-pub mod arch;
-mod cow;
-mod ext;
-mod memchr;
-pub mod memmem;
-mod vector;
diff --git a/vendor/memchr/src/macros.rs b/vendor/memchr/src/macros.rs
deleted file mode 100644
index 31b4ca3..0000000
--- a/vendor/memchr/src/macros.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Some feature combinations result in some of these macros never being used.
-// Which is fine. Just squash the warnings.
-#![allow(unused_macros)]
-
-macro_rules! log {
- ($($tt:tt)*) => {
- #[cfg(feature = "logging")]
- {
- $($tt)*
- }
- }
-}
-
-macro_rules! debug {
- ($($tt:tt)*) => { log!(log::debug!($($tt)*)) }
-}
-
-macro_rules! trace {
- ($($tt:tt)*) => { log!(log::trace!($($tt)*)) }
-}
diff --git a/vendor/memchr/src/memchr.rs b/vendor/memchr/src/memchr.rs
deleted file mode 100644
index 68adb9a..0000000
--- a/vendor/memchr/src/memchr.rs
+++ /dev/null
@@ -1,903 +0,0 @@
-use core::iter::Rev;
-
-use crate::arch::generic::memchr as generic;
-
-/// Search for the first occurrence of a byte in a slice.
-///
-/// This returns the index corresponding to the first occurrence of `needle` in
-/// `haystack`, or `None` if one is not found. If an index is returned, it is
-/// guaranteed to be less than `haystack.len()`.
-///
-/// While this is semantically the same as something like
-/// `haystack.iter().position(|&b| b == needle)`, this routine will attempt to
-/// use highly optimized vector operations that can be an order of magnitude
-/// faster (or more).
-///
-/// # Example
-///
-/// This shows how to find the first position of a byte in a byte string.
-///
-/// ```
-/// use memchr::memchr;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memchr(b'k', haystack), Some(8));
-/// ```
-#[inline]
-pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
- // SAFETY: memchr_raw, when a match is found, always returns a valid
- // pointer between start and end.
- unsafe {
- generic::search_slice_with_raw(haystack, |start, end| {
- memchr_raw(needle, start, end)
- })
- }
-}
-
-/// Search for the last occurrence of a byte in a slice.
-///
-/// This returns the index corresponding to the last occurrence of `needle` in
-/// `haystack`, or `None` if one is not found. If an index is returned, it is
-/// guaranteed to be less than `haystack.len()`.
-///
-/// While this is semantically the same as something like
-/// `haystack.iter().rposition(|&b| b == needle)`, this routine will attempt to
-/// use highly optimized vector operations that can be an order of magnitude
-/// faster (or more).
-///
-/// # Example
-///
-/// This shows how to find the last position of a byte in a byte string.
-///
-/// ```
-/// use memchr::memrchr;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memrchr(b'o', haystack), Some(17));
-/// ```
-#[inline]
-pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
- // SAFETY: memrchr_raw, when a match is found, always returns a valid
- // pointer between start and end.
- unsafe {
- generic::search_slice_with_raw(haystack, |start, end| {
- memrchr_raw(needle, start, end)
- })
- }
-}
-
-/// Search for the first occurrence of two possible bytes in a haystack.
-///
-/// This returns the index corresponding to the first occurrence of one of the
-/// needle bytes in `haystack`, or `None` if one is not found. If an index is
-/// returned, it is guaranteed to be less than `haystack.len()`.
-///
-/// While this is semantically the same as something like
-/// `haystack.iter().position(|&b| b == needle1 || b == needle2)`, this routine
-/// will attempt to use highly optimized vector operations that can be an order
-/// of magnitude faster (or more).
-///
-/// # Example
-///
-/// This shows how to find the first position of one of two possible bytes in a
-/// haystack.
-///
-/// ```
-/// use memchr::memchr2;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memchr2(b'k', b'q', haystack), Some(4));
-/// ```
-#[inline]
-pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
- // SAFETY: memchr2_raw, when a match is found, always returns a valid
- // pointer between start and end.
- unsafe {
- generic::search_slice_with_raw(haystack, |start, end| {
- memchr2_raw(needle1, needle2, start, end)
- })
- }
-}
-
-/// Search for the last occurrence of two possible bytes in a haystack.
-///
-/// This returns the index corresponding to the last occurrence of one of the
-/// needle bytes in `haystack`, or `None` if one is not found. If an index is
-/// returned, it is guaranteed to be less than `haystack.len()`.
-///
-/// While this is semantically the same as something like
-/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2)`, this
-/// routine will attempt to use highly optimized vector operations that can be
-/// an order of magnitude faster (or more).
-///
-/// # Example
-///
-/// This shows how to find the last position of one of two possible bytes in a
-/// haystack.
-///
-/// ```
-/// use memchr::memrchr2;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memrchr2(b'k', b'o', haystack), Some(17));
-/// ```
-#[inline]
-pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
- // SAFETY: memrchr2_raw, when a match is found, always returns a valid
- // pointer between start and end.
- unsafe {
- generic::search_slice_with_raw(haystack, |start, end| {
- memrchr2_raw(needle1, needle2, start, end)
- })
- }
-}
-
-/// Search for the first occurrence of three possible bytes in a haystack.
-///
-/// This returns the index corresponding to the first occurrence of one of the
-/// needle bytes in `haystack`, or `None` if one is not found. If an index is
-/// returned, it is guaranteed to be less than `haystack.len()`.
-///
-/// While this is semantically the same as something like
-/// `haystack.iter().position(|&b| b == needle1 || b == needle2 || b == needle3)`,
-/// this routine will attempt to use highly optimized vector operations that
-/// can be an order of magnitude faster (or more).
-///
-/// # Example
-///
-/// This shows how to find the first position of one of three possible bytes in
-/// a haystack.
-///
-/// ```
-/// use memchr::memchr3;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memchr3(b'k', b'q', b'u', haystack), Some(4));
-/// ```
-#[inline]
-pub fn memchr3(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: &[u8],
-) -> Option<usize> {
- // SAFETY: memchr3_raw, when a match is found, always returns a valid
- // pointer between start and end.
- unsafe {
- generic::search_slice_with_raw(haystack, |start, end| {
- memchr3_raw(needle1, needle2, needle3, start, end)
- })
- }
-}
-
-/// Search for the last occurrence of three possible bytes in a haystack.
-///
-/// This returns the index corresponding to the last occurrence of one of the
-/// needle bytes in `haystack`, or `None` if one is not found. If an index is
-/// returned, it is guaranteed to be less than `haystack.len()`.
-///
-/// While this is semantically the same as something like
-/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2 || b == needle3)`,
-/// this routine will attempt to use highly optimized vector operations that
-/// can be an order of magnitude faster (or more).
-///
-/// # Example
-///
-/// This shows how to find the last position of one of three possible bytes in
-/// a haystack.
-///
-/// ```
-/// use memchr::memrchr3;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memrchr3(b'k', b'o', b'n', haystack), Some(17));
-/// ```
-#[inline]
-pub fn memrchr3(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: &[u8],
-) -> Option<usize> {
- // SAFETY: memrchr3_raw, when a match is found, always returns a valid
- // pointer between start and end.
- unsafe {
- generic::search_slice_with_raw(haystack, |start, end| {
- memrchr3_raw(needle1, needle2, needle3, start, end)
- })
- }
-}
-
-/// Returns an iterator over all occurrences of the needle in a haystack.
-///
-/// The iterator returned implements `DoubleEndedIterator`. This means it
-/// can also be used to find occurrences in reverse order.
-#[inline]
-pub fn memchr_iter<'h>(needle: u8, haystack: &'h [u8]) -> Memchr<'h> {
- Memchr::new(needle, haystack)
-}
-
-/// Returns an iterator over all occurrences of the needle in a haystack, in
-/// reverse.
-#[inline]
-pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>> {
- Memchr::new(needle, haystack).rev()
-}
-
-/// Returns an iterator over all occurrences of the needles in a haystack.
-///
-/// The iterator returned implements `DoubleEndedIterator`. This means it
-/// can also be used to find occurrences in reverse order.
-#[inline]
-pub fn memchr2_iter<'h>(
- needle1: u8,
- needle2: u8,
- haystack: &'h [u8],
-) -> Memchr2<'h> {
- Memchr2::new(needle1, needle2, haystack)
-}
-
-/// Returns an iterator over all occurrences of the needles in a haystack, in
-/// reverse.
-#[inline]
-pub fn memrchr2_iter(
- needle1: u8,
- needle2: u8,
- haystack: &[u8],
-) -> Rev<Memchr2<'_>> {
- Memchr2::new(needle1, needle2, haystack).rev()
-}
-
-/// Returns an iterator over all occurrences of the needles in a haystack.
-///
-/// The iterator returned implements `DoubleEndedIterator`. This means it
-/// can also be used to find occurrences in reverse order.
-#[inline]
-pub fn memchr3_iter<'h>(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: &'h [u8],
-) -> Memchr3<'h> {
- Memchr3::new(needle1, needle2, needle3, haystack)
-}
-
-/// Returns an iterator over all occurrences of the needles in a haystack, in
-/// reverse.
-#[inline]
-pub fn memrchr3_iter(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: &[u8],
-) -> Rev<Memchr3<'_>> {
- Memchr3::new(needle1, needle2, needle3, haystack).rev()
-}
-
-/// An iterator over all occurrences of a single byte in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`memchr_iter`] or `[memrchr_iter`]
-/// functions. It can also be created with the [`Memchr::new`] method.
-///
-/// The lifetime parameter `'h` refers to the lifetime of the haystack being
-/// searched.
-#[derive(Clone, Debug)]
-pub struct Memchr<'h> {
- needle1: u8,
- it: crate::arch::generic::memchr::Iter<'h>,
-}
-
-impl<'h> Memchr<'h> {
- /// Returns an iterator over all occurrences of the needle byte in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[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> {
- // SAFETY: All of our implementations of memchr ensure that any
- // pointers returns will fall within the start and end bounds, and this
- // upholds the safety contract of `self.it.next`.
- unsafe {
- // NOTE: I attempted to define an enum of previously created
- // searchers and then switch on those here instead of just
- // calling `memchr_raw` (or `One::new(..).find_raw(..)`). But
- // that turned out to have a fair bit of extra overhead when
- // searching very small haystacks.
- self.it.next(|s, e| memchr_raw(self.needle1, s, e))
- }
- }
-
- #[inline]
- fn count(self) -> usize {
- self.it.count(|s, e| {
- // SAFETY: We rely on our generic iterator to return valid start
- // and end pointers.
- 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> {
- // SAFETY: All of our implementations of memchr ensure that any
- // pointers returns will fall within the start and end bounds, and this
- // upholds the safety contract of `self.it.next_back`.
- unsafe { self.it.next_back(|s, e| memrchr_raw(self.needle1, s, e)) }
- }
-}
-
-impl<'h> core::iter::FusedIterator for Memchr<'h> {}
-
-/// An iterator over all occurrences of two possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`memchr2_iter`] or `[memrchr2_iter`]
-/// functions. It can also be created with the [`Memchr2::new`] method.
-///
-/// The lifetime parameter `'h` refers to the lifetime of the haystack being
-/// searched.
-#[derive(Clone, Debug)]
-pub struct Memchr2<'h> {
- needle1: u8,
- needle2: u8,
- it: crate::arch::generic::memchr::Iter<'h>,
-}
-
-impl<'h> Memchr2<'h> {
- /// Returns an iterator over all occurrences of the needle bytes in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[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> {
- // SAFETY: All of our implementations of memchr ensure that any
- // pointers returns will fall within the start and end bounds, and this
- // upholds the safety contract of `self.it.next`.
- 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> {
- // SAFETY: All of our implementations of memchr ensure that any
- // pointers returns will fall within the start and end bounds, and this
- // upholds the safety contract of `self.it.next_back`.
- unsafe {
- self.it.next_back(|s, e| {
- memrchr2_raw(self.needle1, self.needle2, s, e)
- })
- }
- }
-}
-
-impl<'h> core::iter::FusedIterator for Memchr2<'h> {}
-
-/// An iterator over all occurrences of three possible bytes in a haystack.
-///
-/// This iterator implements `DoubleEndedIterator`, which means it can also be
-/// used to find occurrences in reverse order.
-///
-/// This iterator is created by the [`memchr2_iter`] or `[memrchr2_iter`]
-/// functions. It can also be created with the [`Memchr3::new`] method.
-///
-/// The lifetime parameter `'h` refers to the lifetime of the haystack being
-/// searched.
-#[derive(Clone, Debug)]
-pub struct Memchr3<'h> {
- needle1: u8,
- needle2: u8,
- needle3: u8,
- it: crate::arch::generic::memchr::Iter<'h>,
-}
-
-impl<'h> Memchr3<'h> {
- /// Returns an iterator over all occurrences of the needle bytes in the
- /// given haystack.
- ///
- /// The iterator returned implements `DoubleEndedIterator`. This means it
- /// can also be used to find occurrences in reverse order.
- #[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> {
- // SAFETY: All of our implementations of memchr ensure that any
- // pointers returns will fall within the start and end bounds, and this
- // upholds the safety contract of `self.it.next`.
- 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> {
- // SAFETY: All of our implementations of memchr ensure that any
- // pointers returns will fall within the start and end bounds, and this
- // upholds the safety contract of `self.it.next_back`.
- 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> {}
-
-/// memchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::find_raw`.
-#[inline]
-unsafe fn memchr_raw(
- needle: u8,
- start: *const u8,
- end: *const u8,
-) -> Option<*const u8> {
- #[cfg(target_arch = "x86_64")]
- {
- // x86_64 does CPU feature detection at runtime in order to use AVX2
- // instructions even when the `avx2` feature isn't enabled at compile
- // time. This function also handles using a fallback if neither AVX2
- // nor SSE2 (unusual) are available.
- 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)
- }
-}
-
-/// memrchr, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::rfind_raw`.
-#[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)
- }
-}
-
-/// memchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::find_raw`.
-#[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)
- }
-}
-
-/// memrchr2, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Two::rfind_raw`.
-#[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)
- }
-}
-
-/// memchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::find_raw`.
-#[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)
- }
-}
-
-/// memrchr3, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `Three::rfind_raw`.
-#[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)
- }
-}
-
-/// Count all matching bytes, but using raw pointers to represent the haystack.
-///
-/// # Safety
-///
-/// Pointers must be valid. See `One::count_raw`.
-#[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))
- },
- )
- }
-
- // Prior to memchr 2.6, the memchr iterators both implemented Send and
- // Sync. But in memchr 2.6, the iterator changed to use raw pointers
- // internally and I didn't add explicit Send/Sync impls. This ended up
- // regressing the API. This test ensures we don't do that again.
- //
- // See: https://github.com/BurntSushi/memchr/issues/133
- #[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>()
- }
-}
diff --git a/vendor/memchr/src/memmem/mod.rs b/vendor/memchr/src/memmem/mod.rs
deleted file mode 100644
index 4f04943..0000000
--- a/vendor/memchr/src/memmem/mod.rs
+++ /dev/null
@@ -1,737 +0,0 @@
-/*!
-This module provides forward and reverse substring search routines.
-
-Unlike the standard library's substring search routines, these work on
-arbitrary bytes. For all non-empty needles, these routines will report exactly
-the same values as the corresponding routines in the standard library. For
-the empty needle, the standard library reports matches only at valid UTF-8
-boundaries, where as these routines will report matches at every position.
-
-Other than being able to work on arbitrary bytes, the primary reason to prefer
-these routines over the standard library routines is that these will generally
-be faster. In some cases, significantly so.
-
-# Example: iterating over substring matches
-
-This example shows how to use [`find_iter`] to find occurrences of a substring
-in a haystack.
-
-```
-use memchr::memmem;
-
-let haystack = b"foo bar foo baz foo";
-
-let mut it = memmem::find_iter(haystack, "foo");
-assert_eq!(Some(0), it.next());
-assert_eq!(Some(8), it.next());
-assert_eq!(Some(16), it.next());
-assert_eq!(None, it.next());
-```
-
-# Example: iterating over substring matches in reverse
-
-This example shows how to use [`rfind_iter`] to find occurrences of a substring
-in a haystack starting from the end of the haystack.
-
-**NOTE:** This module does not implement double ended iterators, so reverse
-searches aren't done by calling `rev` on a forward iterator.
-
-```
-use memchr::memmem;
-
-let haystack = b"foo bar foo baz foo";
-
-let mut it = memmem::rfind_iter(haystack, "foo");
-assert_eq!(Some(16), it.next());
-assert_eq!(Some(8), it.next());
-assert_eq!(Some(0), it.next());
-assert_eq!(None, it.next());
-```
-
-# Example: repeating a search for the same needle
-
-It may be possible for the overhead of constructing a substring searcher to be
-measurable in some workloads. In cases where the same needle is used to search
-many haystacks, it is possible to do construction once and thus to avoid it for
-subsequent searches. This can be done with a [`Finder`] (or a [`FinderRev`] for
-reverse searches).
-
-```
-use memchr::memmem;
-
-let finder = memmem::Finder::new("foo");
-
-assert_eq!(Some(4), finder.find(b"baz foo quux"));
-assert_eq!(None, finder.find(b"quux baz bar"));
-```
-*/
-
-pub use crate::memmem::searcher::PrefilterConfig as Prefilter;
-
-// This is exported here for use in the crate::arch::all::twoway
-// implementation. This is essentially an abstraction breaker. Namely, the
-// public API of twoway doesn't support providing a prefilter, but its crate
-// internal API does. The main reason for this is that I didn't want to do the
-// API design required to support it without a concrete use case.
-pub(crate) use crate::memmem::searcher::Pre;
-
-use crate::{
- arch::all::{
- packedpair::{DefaultFrequencyRank, HeuristicFrequencyRank},
- rabinkarp,
- },
- cow::CowBytes,
- memmem::searcher::{PrefilterState, Searcher, SearcherRev},
-};
-
-mod searcher;
-
-/// Returns an iterator over all non-overlapping occurrences of a substring in
-/// a haystack.
-///
-/// # Complexity
-///
-/// This routine is guaranteed to have worst case linear time complexity
-/// with respect to both the needle and the haystack. That is, this runs
-/// in `O(needle.len() + haystack.len())` time.
-///
-/// This routine is also guaranteed to have worst case constant space
-/// complexity.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use memchr::memmem;
-///
-/// let haystack = b"foo bar foo baz foo";
-/// let mut it = memmem::find_iter(haystack, b"foo");
-/// assert_eq!(Some(0), it.next());
-/// assert_eq!(Some(8), it.next());
-/// assert_eq!(Some(16), it.next());
-/// assert_eq!(None, it.next());
-/// ```
-#[inline]
-pub fn find_iter<'h, 'n, N: 'n + ?Sized + AsRef<[u8]>>(
- haystack: &'h [u8],
- needle: &'n N,
-) -> FindIter<'h, 'n> {
- FindIter::new(haystack, Finder::new(needle))
-}
-
-/// Returns a reverse iterator over all non-overlapping occurrences of a
-/// substring in a haystack.
-///
-/// # Complexity
-///
-/// This routine is guaranteed to have worst case linear time complexity
-/// with respect to both the needle and the haystack. That is, this runs
-/// in `O(needle.len() + haystack.len())` time.
-///
-/// This routine is also guaranteed to have worst case constant space
-/// complexity.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use memchr::memmem;
-///
-/// let haystack = b"foo bar foo baz foo";
-/// let mut it = memmem::rfind_iter(haystack, b"foo");
-/// assert_eq!(Some(16), it.next());
-/// assert_eq!(Some(8), it.next());
-/// assert_eq!(Some(0), it.next());
-/// assert_eq!(None, it.next());
-/// ```
-#[inline]
-pub fn rfind_iter<'h, 'n, N: 'n + ?Sized + AsRef<[u8]>>(
- haystack: &'h [u8],
- needle: &'n N,
-) -> FindRevIter<'h, 'n> {
- FindRevIter::new(haystack, FinderRev::new(needle))
-}
-
-/// Returns the index of the first occurrence of the given needle.
-///
-/// Note that if you're are searching for the same needle in many different
-/// small haystacks, it may be faster to initialize a [`Finder`] once,
-/// and reuse it for each search.
-///
-/// # Complexity
-///
-/// This routine is guaranteed to have worst case linear time complexity
-/// with respect to both the needle and the haystack. That is, this runs
-/// in `O(needle.len() + haystack.len())` time.
-///
-/// This routine is also guaranteed to have worst case constant space
-/// complexity.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use memchr::memmem;
-///
-/// let haystack = b"foo bar baz";
-/// assert_eq!(Some(0), memmem::find(haystack, b"foo"));
-/// assert_eq!(Some(4), memmem::find(haystack, b"bar"));
-/// assert_eq!(None, memmem::find(haystack, b"quux"));
-/// ```
-#[inline]
-pub fn find(haystack: &[u8], needle: &[u8]) -> Option<usize> {
- if haystack.len() < 64 {
- rabinkarp::Finder::new(needle).find(haystack, needle)
- } else {
- Finder::new(needle).find(haystack)
- }
-}
-
-/// Returns the index of the last occurrence of the given needle.
-///
-/// Note that if you're are searching for the same needle in many different
-/// small haystacks, it may be faster to initialize a [`FinderRev`] once,
-/// and reuse it for each search.
-///
-/// # Complexity
-///
-/// This routine is guaranteed to have worst case linear time complexity
-/// with respect to both the needle and the haystack. That is, this runs
-/// in `O(needle.len() + haystack.len())` time.
-///
-/// This routine is also guaranteed to have worst case constant space
-/// complexity.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use memchr::memmem;
-///
-/// let haystack = b"foo bar baz";
-/// assert_eq!(Some(0), memmem::rfind(haystack, b"foo"));
-/// assert_eq!(Some(4), memmem::rfind(haystack, b"bar"));
-/// assert_eq!(Some(8), memmem::rfind(haystack, b"ba"));
-/// assert_eq!(None, memmem::rfind(haystack, b"quux"));
-/// ```
-#[inline]
-pub fn rfind(haystack: &[u8], needle: &[u8]) -> Option<usize> {
- if haystack.len() < 64 {
- rabinkarp::FinderRev::new(needle).rfind(haystack, needle)
- } else {
- FinderRev::new(needle).rfind(haystack)
- }
-}
-
-/// An iterator over non-overlapping substring matches.
-///
-/// Matches are reported by the byte offset at which they begin.
-///
-/// `'h` is the lifetime of the haystack while `'n` is the lifetime of the
-/// needle.
-#[derive(Debug, Clone)]
-pub struct FindIter<'h, 'n> {
- haystack: &'h [u8],
- prestate: PrefilterState,
- finder: Finder<'n>,
- pos: usize,
-}
-
-impl<'h, 'n> FindIter<'h, 'n> {
- #[inline(always)]
- pub(crate) fn new(
- haystack: &'h [u8],
- finder: Finder<'n>,
- ) -> FindIter<'h, 'n> {
- let prestate = PrefilterState::new();
- FindIter { haystack, prestate, finder, pos: 0 }
- }
-
- /// Convert this iterator into its owned variant, such that it no longer
- /// borrows the finder and needle.
- ///
- /// If this is already an owned iterator, then this is a no-op. Otherwise,
- /// this copies the needle.
- ///
- /// This is only available when the `alloc` feature is enabled.
- #[cfg(feature = "alloc")]
- #[inline]
- pub fn into_owned(self) -> FindIter<'h, 'static> {
- FindIter {
- haystack: self.haystack,
- prestate: self.prestate,
- finder: self.finder.into_owned(),
- pos: self.pos,
- }
- }
-}
-
-impl<'h, 'n> Iterator for FindIter<'h, 'n> {
- type Item = usize;
-
- fn next(&mut self) -> Option<usize> {
- let needle = self.finder.needle();
- let haystack = self.haystack.get(self.pos..)?;
- let idx =
- self.finder.searcher.find(&mut self.prestate, haystack, needle)?;
-
- let pos = self.pos + idx;
- self.pos = pos + needle.len().max(1);
-
- Some(pos)
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- // The largest possible number of non-overlapping matches is the
- // quotient of the haystack and the needle (or the length of the
- // haystack, if the needle is empty)
- match self.haystack.len().checked_sub(self.pos) {
- None => (0, Some(0)),
- Some(haystack_len) => match self.finder.needle().len() {
- // Empty needles always succeed and match at every point
- // (including the very end)
- 0 => (
- haystack_len.saturating_add(1),
- haystack_len.checked_add(1),
- ),
- needle_len => (0, Some(haystack_len / needle_len)),
- },
- }
- }
-}
-
-/// An iterator over non-overlapping substring matches in reverse.
-///
-/// Matches are reported by the byte offset at which they begin.
-///
-/// `'h` is the lifetime of the haystack while `'n` is the lifetime of the
-/// needle.
-#[derive(Clone, Debug)]
-pub struct FindRevIter<'h, 'n> {
- haystack: &'h [u8],
- finder: FinderRev<'n>,
- /// When searching with an empty needle, this gets set to `None` after
- /// we've yielded the last element at `0`.
- pos: Option<usize>,
-}
-
-impl<'h, 'n> FindRevIter<'h, 'n> {
- #[inline(always)]
- pub(crate) fn new(
- haystack: &'h [u8],
- finder: FinderRev<'n>,
- ) -> FindRevIter<'h, 'n> {
- let pos = Some(haystack.len());
- FindRevIter { haystack, finder, pos }
- }
-
- /// Convert this iterator into its owned variant, such that it no longer
- /// borrows the finder and needle.
- ///
- /// If this is already an owned iterator, then this is a no-op. Otherwise,
- /// this copies the needle.
- ///
- /// This is only available when the `std` feature is enabled.
- #[cfg(feature = "alloc")]
- #[inline]
- pub fn into_owned(self) -> FindRevIter<'h, 'static> {
- FindRevIter {
- haystack: self.haystack,
- finder: self.finder.into_owned(),
- pos: self.pos,
- }
- }
-}
-
-impl<'h, 'n> Iterator for FindRevIter<'h, 'n> {
- type Item = usize;
-
- fn next(&mut self) -> Option<usize> {
- let pos = match self.pos {
- None => return None,
- Some(pos) => pos,
- };
- let result = self.finder.rfind(&self.haystack[..pos]);
- match result {
- None => None,
- Some(i) => {
- if pos == i {
- self.pos = pos.checked_sub(1);
- } else {
- self.pos = Some(i);
- }
- Some(i)
- }
- }
- }
-}
-
-/// A single substring searcher fixed to a particular needle.
-///
-/// The purpose of this type is to permit callers to construct a substring
-/// searcher that can be used to search haystacks without the overhead of
-/// constructing the searcher in the first place. This is a somewhat niche
-/// concern when it's necessary to re-use the same needle to search multiple
-/// different haystacks with as little overhead as possible. In general, using
-/// [`find`] is good enough, but `Finder` is useful when you can meaningfully
-/// observe searcher construction time in a profile.
-///
-/// When the `std` feature is enabled, then this type has an `into_owned`
-/// version which permits building a `Finder` that is not connected to
-/// the lifetime of its needle.
-#[derive(Clone, Debug)]
-pub struct Finder<'n> {
- needle: CowBytes<'n>,
- searcher: Searcher,
-}
-
-impl<'n> Finder<'n> {
- /// Create a new finder for the given needle.
- #[inline]
- pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'n B) -> Finder<'n> {
- FinderBuilder::new().build_forward(needle)
- }
-
- /// Returns the index of the first occurrence of this needle in the given
- /// haystack.
- ///
- /// # Complexity
- ///
- /// This routine is guaranteed to have worst case linear time complexity
- /// with respect to both the needle and the haystack. That is, this runs
- /// in `O(needle.len() + haystack.len())` time.
- ///
- /// This routine is also guaranteed to have worst case constant space
- /// complexity.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use memchr::memmem::Finder;
- ///
- /// let haystack = b"foo bar baz";
- /// assert_eq!(Some(0), Finder::new("foo").find(haystack));
- /// assert_eq!(Some(4), Finder::new("bar").find(haystack));
- /// assert_eq!(None, Finder::new("quux").find(haystack));
- /// ```
- #[inline]
- pub fn find(&self, haystack: &[u8]) -> Option<usize> {
- let mut prestate = PrefilterState::new();
- let needle = self.needle.as_slice();
- self.searcher.find(&mut prestate, haystack, needle)
- }
-
- /// Returns an iterator over all occurrences of a substring in a haystack.
- ///
- /// # Complexity
- ///
- /// This routine is guaranteed to have worst case linear time complexity
- /// with respect to both the needle and the haystack. That is, this runs
- /// in `O(needle.len() + haystack.len())` time.
- ///
- /// This routine is also guaranteed to have worst case constant space
- /// complexity.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use memchr::memmem::Finder;
- ///
- /// let haystack = b"foo bar foo baz foo";
- /// let finder = Finder::new(b"foo");
- /// let mut it = finder.find_iter(haystack);
- /// assert_eq!(Some(0), it.next());
- /// assert_eq!(Some(8), it.next());
- /// assert_eq!(Some(16), it.next());
- /// assert_eq!(None, it.next());
- /// ```
- #[inline]
- pub fn find_iter<'a, 'h>(
- &'a self,
- haystack: &'h [u8],
- ) -> FindIter<'h, 'a> {
- FindIter::new(haystack, self.as_ref())
- }
-
- /// Convert this finder into its owned variant, such that it no longer
- /// borrows the needle.
- ///
- /// If this is already an owned finder, then this is a no-op. Otherwise,
- /// this copies the needle.
- ///
- /// This is only available when the `alloc` feature is enabled.
- #[cfg(feature = "alloc")]
- #[inline]
- pub fn into_owned(self) -> Finder<'static> {
- Finder {
- needle: self.needle.into_owned(),
- searcher: self.searcher.clone(),
- }
- }
-
- /// Convert this finder into its borrowed variant.
- ///
- /// This is primarily useful if your finder is owned and you'd like to
- /// store its borrowed variant in some intermediate data structure.
- ///
- /// Note that the lifetime parameter of the returned finder is tied to the
- /// lifetime of `self`, and may be shorter than the `'n` lifetime of the
- /// needle itself. Namely, a finder's needle can be either borrowed or
- /// owned, so the lifetime of the needle returned must necessarily be the
- /// shorter of the two.
- #[inline]
- pub fn as_ref(&self) -> Finder<'_> {
- Finder {
- needle: CowBytes::new(self.needle()),
- searcher: self.searcher.clone(),
- }
- }
-
- /// Returns the needle that this finder searches for.
- ///
- /// Note that the lifetime of the needle returned is tied to the lifetime
- /// of the finder, and may be shorter than the `'n` lifetime. Namely, a
- /// finder's needle can be either borrowed or owned, so the lifetime of the
- /// needle returned must necessarily be the shorter of the two.
- #[inline]
- pub fn needle(&self) -> &[u8] {
- self.needle.as_slice()
- }
-}
-
-/// A single substring reverse searcher fixed to a particular needle.
-///
-/// The purpose of this type is to permit callers to construct a substring
-/// searcher that can be used to search haystacks without the overhead of
-/// constructing the searcher in the first place. This is a somewhat niche
-/// concern when it's necessary to re-use the same needle to search multiple
-/// different haystacks with as little overhead as possible. In general,
-/// using [`rfind`] is good enough, but `FinderRev` is useful when you can
-/// meaningfully observe searcher construction time in a profile.
-///
-/// When the `std` feature is enabled, then this type has an `into_owned`
-/// version which permits building a `FinderRev` that is not connected to
-/// the lifetime of its needle.
-#[derive(Clone, Debug)]
-pub struct FinderRev<'n> {
- needle: CowBytes<'n>,
- searcher: SearcherRev,
-}
-
-impl<'n> FinderRev<'n> {
- /// Create a new reverse finder for the given needle.
- #[inline]
- pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'n B) -> FinderRev<'n> {
- FinderBuilder::new().build_reverse(needle)
- }
-
- /// Returns the index of the last occurrence of this needle in the given
- /// haystack.
- ///
- /// The haystack may be any type that can be cheaply converted into a
- /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
- ///
- /// # Complexity
- ///
- /// This routine is guaranteed to have worst case linear time complexity
- /// with respect to both the needle and the haystack. That is, this runs
- /// in `O(needle.len() + haystack.len())` time.
- ///
- /// This routine is also guaranteed to have worst case constant space
- /// complexity.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use memchr::memmem::FinderRev;
- ///
- /// let haystack = b"foo bar baz";
- /// assert_eq!(Some(0), FinderRev::new("foo").rfind(haystack));
- /// assert_eq!(Some(4), FinderRev::new("bar").rfind(haystack));
- /// assert_eq!(None, FinderRev::new("quux").rfind(haystack));
- /// ```
- pub fn rfind<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> {
- self.searcher.rfind(haystack.as_ref(), self.needle.as_slice())
- }
-
- /// Returns a reverse iterator over all occurrences of a substring in a
- /// haystack.
- ///
- /// # Complexity
- ///
- /// This routine is guaranteed to have worst case linear time complexity
- /// with respect to both the needle and the haystack. That is, this runs
- /// in `O(needle.len() + haystack.len())` time.
- ///
- /// This routine is also guaranteed to have worst case constant space
- /// complexity.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use memchr::memmem::FinderRev;
- ///
- /// let haystack = b"foo bar foo baz foo";
- /// let finder = FinderRev::new(b"foo");
- /// let mut it = finder.rfind_iter(haystack);
- /// assert_eq!(Some(16), it.next());
- /// assert_eq!(Some(8), it.next());
- /// assert_eq!(Some(0), it.next());
- /// assert_eq!(None, it.next());
- /// ```
- #[inline]
- pub fn rfind_iter<'a, 'h>(
- &'a self,
- haystack: &'h [u8],
- ) -> FindRevIter<'h, 'a> {
- FindRevIter::new(haystack, self.as_ref())
- }
-
- /// Convert this finder into its owned variant, such that it no longer
- /// borrows the needle.
- ///
- /// If this is already an owned finder, then this is a no-op. Otherwise,
- /// this copies the needle.
- ///
- /// This is only available when the `std` feature is enabled.
- #[cfg(feature = "alloc")]
- #[inline]
- pub fn into_owned(self) -> FinderRev<'static> {
- FinderRev {
- needle: self.needle.into_owned(),
- searcher: self.searcher.clone(),
- }
- }
-
- /// Convert this finder into its borrowed variant.
- ///
- /// This is primarily useful if your finder is owned and you'd like to
- /// store its borrowed variant in some intermediate data structure.
- ///
- /// Note that the lifetime parameter of the returned finder is tied to the
- /// lifetime of `self`, and may be shorter than the `'n` lifetime of the
- /// needle itself. Namely, a finder's needle can be either borrowed or
- /// owned, so the lifetime of the needle returned must necessarily be the
- /// shorter of the two.
- #[inline]
- pub fn as_ref(&self) -> FinderRev<'_> {
- FinderRev {
- needle: CowBytes::new(self.needle()),
- searcher: self.searcher.clone(),
- }
- }
-
- /// Returns the needle that this finder searches for.
- ///
- /// Note that the lifetime of the needle returned is tied to the lifetime
- /// of the finder, and may be shorter than the `'n` lifetime. Namely, a
- /// finder's needle can be either borrowed or owned, so the lifetime of the
- /// needle returned must necessarily be the shorter of the two.
- #[inline]
- pub fn needle(&self) -> &[u8] {
- self.needle.as_slice()
- }
-}
-
-/// A builder for constructing non-default forward or reverse memmem finders.
-///
-/// A builder is primarily useful for configuring a substring searcher.
-/// Currently, the only configuration exposed is the ability to disable
-/// heuristic prefilters used to speed up certain searches.
-#[derive(Clone, Debug, Default)]
-pub struct FinderBuilder {
- prefilter: Prefilter,
-}
-
-impl FinderBuilder {
- /// Create a new finder builder with default settings.
- pub fn new() -> FinderBuilder {
- FinderBuilder::default()
- }
-
- /// Build a forward finder using the given needle from the current
- /// settings.
- pub fn build_forward<'n, B: ?Sized + AsRef<[u8]>>(
- &self,
- needle: &'n B,
- ) -> Finder<'n> {
- self.build_forward_with_ranker(DefaultFrequencyRank, needle)
- }
-
- /// Build a forward finder using the given needle and a custom heuristic for
- /// determining the frequency of a given byte in the dataset.
- /// See [`HeuristicFrequencyRank`] for more details.
- pub fn build_forward_with_ranker<
- 'n,
- R: HeuristicFrequencyRank,
- B: ?Sized + AsRef<[u8]>,
- >(
- &self,
- ranker: R,
- needle: &'n B,
- ) -> Finder<'n> {
- let needle = needle.as_ref();
- Finder {
- needle: CowBytes::new(needle),
- searcher: Searcher::new(self.prefilter, ranker, needle),
- }
- }
-
- /// Build a reverse finder using the given needle from the current
- /// settings.
- pub fn build_reverse<'n, B: ?Sized + AsRef<[u8]>>(
- &self,
- needle: &'n B,
- ) -> FinderRev<'n> {
- let needle = needle.as_ref();
- FinderRev {
- needle: CowBytes::new(needle),
- searcher: SearcherRev::new(needle),
- }
- }
-
- /// Configure the prefilter setting for the finder.
- ///
- /// See the documentation for [`Prefilter`] for more discussion on why
- /// you might want to configure this.
- pub fn prefilter(&mut self, prefilter: Prefilter) -> &mut FinderBuilder {
- self.prefilter = prefilter;
- self
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- define_substring_forward_quickcheck!(|h, n| Some(Finder::new(n).find(h)));
- define_substring_reverse_quickcheck!(|h, n| Some(
- FinderRev::new(n).rfind(h)
- ));
-
- #[test]
- fn forward() {
- crate::tests::substring::Runner::new()
- .fwd(|h, n| Some(Finder::new(n).find(h)))
- .run();
- }
-
- #[test]
- fn reverse() {
- crate::tests::substring::Runner::new()
- .rev(|h, n| Some(FinderRev::new(n).rfind(h)))
- .run();
- }
-}
diff --git a/vendor/memchr/src/memmem/searcher.rs b/vendor/memchr/src/memmem/searcher.rs
deleted file mode 100644
index 98b9bd6..0000000
--- a/vendor/memchr/src/memmem/searcher.rs
+++ /dev/null
@@ -1,1030 +0,0 @@
-use crate::arch::all::{
- packedpair::{HeuristicFrequencyRank, Pair},
- rabinkarp, twoway,
-};
-
-#[cfg(target_arch = "aarch64")]
-use crate::arch::aarch64::neon::packedpair as neon;
-#[cfg(target_arch = "wasm32")]
-use crate::arch::wasm32::simd128::packedpair as simd128;
-#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
-use crate::arch::x86_64::{
- avx2::packedpair as avx2, sse2::packedpair as sse2,
-};
-
-/// A "meta" substring searcher.
-///
-/// To a first approximation, this chooses what it believes to be the "best"
-/// substring search implemnetation based on the needle at construction time.
-/// Then, every call to `find` will execute that particular implementation. To
-/// a second approximation, multiple substring search algorithms may be used,
-/// depending on the haystack. For example, for supremely short haystacks,
-/// Rabin-Karp is typically used.
-///
-/// See the documentation on `Prefilter` for an explanation of the dispatching
-/// mechanism. The quick summary is that an enum has too much overhead and
-/// we can't use dynamic dispatch via traits because we need to work in a
-/// core-only environment. (Dynamic dispatch works in core-only, but you
-/// need `&dyn Trait` and we really need a `Box<dyn Trait>` here. The latter
-/// requires `alloc`.) So instead, we use a union and an appropriately paired
-/// free function to read from the correct field on the union and execute the
-/// chosen substring search implementation.
-#[derive(Clone)]
-pub(crate) struct Searcher {
- call: SearcherKindFn,
- kind: SearcherKind,
- rabinkarp: rabinkarp::Finder,
-}
-
-impl Searcher {
- /// Creates a new "meta" substring searcher that attempts to choose the
- /// best algorithm based on the needle, heuristics and what the current
- /// target supports.
- #[inline]
- pub(crate) fn new<R: HeuristicFrequencyRank>(
- prefilter: PrefilterConfig,
- ranker: R,
- needle: &[u8],
- ) -> Searcher {
- let rabinkarp = rabinkarp::Finder::new(needle);
- if needle.len() <= 1 {
- return if needle.is_empty() {
- trace!("building empty substring searcher");
- Searcher {
- call: searcher_kind_empty,
- kind: SearcherKind { empty: () },
- rabinkarp,
- }
- } else {
- trace!("building one-byte substring searcher");
- debug_assert_eq!(1, needle.len());
- Searcher {
- call: searcher_kind_one_byte,
- kind: SearcherKind { one_byte: needle[0] },
- rabinkarp,
- }
- };
- }
- let pair = match Pair::with_ranker(needle, &ranker) {
- Some(pair) => pair,
- None => return Searcher::twoway(needle, rabinkarp, None),
- };
- debug_assert_ne!(
- pair.index1(),
- pair.index2(),
- "pair offsets should not be equivalent"
- );
- #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
- {
- if let Some(pp) = avx2::Finder::with_pair(needle, pair) {
- if do_packed_search(needle) {
- trace!("building x86_64 AVX2 substring searcher");
- let kind = SearcherKind { avx2: pp };
- Searcher { call: searcher_kind_avx2, kind, rabinkarp }
- } else if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- let prestrat = Prefilter::avx2(pp, needle);
- Searcher::twoway(needle, rabinkarp, Some(prestrat))
- }
- } else if let Some(pp) = sse2::Finder::with_pair(needle, pair) {
- if do_packed_search(needle) {
- trace!("building x86_64 SSE2 substring searcher");
- let kind = SearcherKind { sse2: pp };
- Searcher { call: searcher_kind_sse2, kind, rabinkarp }
- } else if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- let prestrat = Prefilter::sse2(pp, needle);
- Searcher::twoway(needle, rabinkarp, Some(prestrat))
- }
- } else if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- // We're pretty unlikely to get to this point, but it is
- // possible to be running on x86_64 without SSE2. Namely, it's
- // really up to the OS whether it wants to support vector
- // registers or not.
- let prestrat = Prefilter::fallback(ranker, pair, needle);
- Searcher::twoway(needle, rabinkarp, prestrat)
- }
- }
- #[cfg(target_arch = "wasm32")]
- {
- if let Some(pp) = simd128::Finder::with_pair(needle, pair) {
- if do_packed_search(needle) {
- trace!("building wasm32 simd128 substring searcher");
- let kind = SearcherKind { simd128: pp };
- Searcher { call: searcher_kind_simd128, kind, rabinkarp }
- } else if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- let prestrat = Prefilter::simd128(pp, needle);
- Searcher::twoway(needle, rabinkarp, Some(prestrat))
- }
- } else if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- let prestrat = Prefilter::fallback(ranker, pair, needle);
- Searcher::twoway(needle, rabinkarp, prestrat)
- }
- }
- #[cfg(target_arch = "aarch64")]
- {
- if let Some(pp) = neon::Finder::with_pair(needle, pair) {
- if do_packed_search(needle) {
- trace!("building aarch64 neon substring searcher");
- let kind = SearcherKind { neon: pp };
- Searcher { call: searcher_kind_neon, kind, rabinkarp }
- } else if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- let prestrat = Prefilter::neon(pp, needle);
- Searcher::twoway(needle, rabinkarp, Some(prestrat))
- }
- } else if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- let prestrat = Prefilter::fallback(ranker, pair, needle);
- Searcher::twoway(needle, rabinkarp, prestrat)
- }
- }
- #[cfg(not(any(
- all(target_arch = "x86_64", target_feature = "sse2"),
- target_arch = "wasm32",
- target_arch = "aarch64"
- )))]
- {
- if prefilter.is_none() {
- Searcher::twoway(needle, rabinkarp, None)
- } else {
- let prestrat = Prefilter::fallback(ranker, pair, needle);
- Searcher::twoway(needle, rabinkarp, prestrat)
- }
- }
- }
-
- /// Creates a new searcher that always uses the Two-Way algorithm. This is
- /// typically used when vector algorithms are unavailable or inappropriate.
- /// (For example, when the needle is "too long.")
- ///
- /// If a prefilter is given, then the searcher returned will be accelerated
- /// by the prefilter.
- #[inline]
- fn twoway(
- needle: &[u8],
- rabinkarp: rabinkarp::Finder,
- prestrat: Option<Prefilter>,
- ) -> Searcher {
- let finder = twoway::Finder::new(needle);
- match prestrat {
- None => {
- trace!("building scalar two-way substring searcher");
- let kind = SearcherKind { two_way: finder };
- Searcher { call: searcher_kind_two_way, kind, rabinkarp }
- }
- Some(prestrat) => {
- trace!(
- "building scalar two-way \
- substring searcher with a prefilter"
- );
- let two_way_with_prefilter =
- TwoWayWithPrefilter { finder, prestrat };
- let kind = SearcherKind { two_way_with_prefilter };
- Searcher {
- call: searcher_kind_two_way_with_prefilter,
- kind,
- rabinkarp,
- }
- }
- }
- }
-
- /// Searches the given haystack for the given needle. The needle given
- /// should be the same as the needle that this finder was initialized
- /// with.
- ///
- /// Inlining this can lead to big wins for latency, and #[inline] doesn't
- /// seem to be enough in some cases.
- #[inline(always)]
- pub(crate) fn find(
- &self,
- prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
- ) -> Option<usize> {
- if haystack.len() < needle.len() {
- None
- } else {
- // SAFETY: By construction, we've ensured that the function
- // in `self.call` is properly paired with the union used in
- // `self.kind`.
- unsafe { (self.call)(self, prestate, haystack, needle) }
- }
- }
-}
-
-impl core::fmt::Debug for Searcher {
- fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- f.debug_struct("Searcher")
- .field("call", &"<searcher function>")
- .field("kind", &"<searcher kind union>")
- .field("rabinkarp", &self.rabinkarp)
- .finish()
- }
-}
-
-/// A union indicating one of several possible substring search implementations
-/// that are in active use.
-///
-/// This union should only be read by one of the functions prefixed with
-/// `searcher_kind_`. Namely, the correct function is meant to be paired with
-/// the union by the caller, such that the function always reads from the
-/// designated union field.
-#[derive(Clone, Copy)]
-union SearcherKind {
- empty: (),
- one_byte: u8,
- two_way: twoway::Finder,
- two_way_with_prefilter: TwoWayWithPrefilter,
- #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
- sse2: crate::arch::x86_64::sse2::packedpair::Finder,
- #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
- avx2: crate::arch::x86_64::avx2::packedpair::Finder,
- #[cfg(target_arch = "wasm32")]
- simd128: crate::arch::wasm32::simd128::packedpair::Finder,
- #[cfg(target_arch = "aarch64")]
- neon: crate::arch::aarch64::neon::packedpair::Finder,
-}
-
-/// A two-way substring searcher with a prefilter.
-#[derive(Copy, Clone, Debug)]
-struct TwoWayWithPrefilter {
- finder: twoway::Finder,
- prestrat: Prefilter,
-}
-
-/// The type of a substring search function.
-///
-/// # Safety
-///
-/// When using a function of this type, callers must ensure that the correct
-/// function is paired with the value populated in `SearcherKind` union.
-type SearcherKindFn = unsafe fn(
- searcher: &Searcher,
- prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
-) -> Option<usize>;
-
-/// Reads from the `empty` field of `SearcherKind` to handle the case of
-/// searching for the empty needle. Works on all platforms.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.empty` union field is set.
-unsafe fn searcher_kind_empty(
- _searcher: &Searcher,
- _prestate: &mut PrefilterState,
- _haystack: &[u8],
- _needle: &[u8],
-) -> Option<usize> {
- Some(0)
-}
-
-/// Reads from the `one_byte` field of `SearcherKind` to handle the case of
-/// searching for a single byte needle. Works on all platforms.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.one_byte` union field is set.
-unsafe fn searcher_kind_one_byte(
- searcher: &Searcher,
- _prestate: &mut PrefilterState,
- haystack: &[u8],
- _needle: &[u8],
-) -> Option<usize> {
- let needle = searcher.kind.one_byte;
- crate::memchr(needle, haystack)
-}
-
-/// Reads from the `two_way` field of `SearcherKind` to handle the case of
-/// searching for an arbitrary needle without prefilter acceleration. Works on
-/// all platforms.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.two_way` union field is set.
-unsafe fn searcher_kind_two_way(
- searcher: &Searcher,
- _prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
-) -> Option<usize> {
- if rabinkarp::is_fast(haystack, needle) {
- searcher.rabinkarp.find(haystack, needle)
- } else {
- searcher.kind.two_way.find(haystack, needle)
- }
-}
-
-/// Reads from the `two_way_with_prefilter` field of `SearcherKind` to handle
-/// the case of searching for an arbitrary needle with prefilter acceleration.
-/// Works on all platforms.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.two_way_with_prefilter` union
-/// field is set.
-unsafe fn searcher_kind_two_way_with_prefilter(
- searcher: &Searcher,
- prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
-) -> Option<usize> {
- if rabinkarp::is_fast(haystack, needle) {
- searcher.rabinkarp.find(haystack, needle)
- } else {
- let TwoWayWithPrefilter { ref finder, ref prestrat } =
- searcher.kind.two_way_with_prefilter;
- let pre = Pre { prestate, prestrat };
- finder.find_with_prefilter(Some(pre), haystack, needle)
- }
-}
-
-/// Reads from the `sse2` field of `SearcherKind` to execute the x86_64 SSE2
-/// vectorized substring search implementation.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.sse2` union field is set.
-#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
-unsafe fn searcher_kind_sse2(
- searcher: &Searcher,
- _prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
-) -> Option<usize> {
- let finder = &searcher.kind.sse2;
- if haystack.len() < finder.min_haystack_len() {
- searcher.rabinkarp.find(haystack, needle)
- } else {
- finder.find(haystack, needle)
- }
-}
-
-/// Reads from the `avx2` field of `SearcherKind` to execute the x86_64 AVX2
-/// vectorized substring search implementation.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.avx2` union field is set.
-#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
-unsafe fn searcher_kind_avx2(
- searcher: &Searcher,
- _prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
-) -> Option<usize> {
- let finder = &searcher.kind.avx2;
- if haystack.len() < finder.min_haystack_len() {
- searcher.rabinkarp.find(haystack, needle)
- } else {
- finder.find(haystack, needle)
- }
-}
-
-/// Reads from the `simd128` field of `SearcherKind` to execute the wasm32
-/// simd128 vectorized substring search implementation.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.simd128` union field is set.
-#[cfg(target_arch = "wasm32")]
-unsafe fn searcher_kind_simd128(
- searcher: &Searcher,
- _prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
-) -> Option<usize> {
- let finder = &searcher.kind.simd128;
- if haystack.len() < finder.min_haystack_len() {
- searcher.rabinkarp.find(haystack, needle)
- } else {
- finder.find(haystack, needle)
- }
-}
-
-/// Reads from the `neon` field of `SearcherKind` to execute the aarch64 neon
-/// vectorized substring search implementation.
-///
-/// # Safety
-///
-/// Callers must ensure that the `searcher.kind.neon` union field is set.
-#[cfg(target_arch = "aarch64")]
-unsafe fn searcher_kind_neon(
- searcher: &Searcher,
- _prestate: &mut PrefilterState,
- haystack: &[u8],
- needle: &[u8],
-) -> Option<usize> {
- let finder = &searcher.kind.neon;
- if haystack.len() < finder.min_haystack_len() {
- searcher.rabinkarp.find(haystack, needle)
- } else {
- finder.find(haystack, needle)
- }
-}
-
-/// A reverse substring searcher.
-#[derive(Clone, Debug)]
-pub(crate) struct SearcherRev {
- kind: SearcherRevKind,
- rabinkarp: rabinkarp::FinderRev,
-}
-
-/// The kind of the reverse searcher.
-///
-/// For the reverse case, we don't do any SIMD acceleration or prefilters.
-/// There is no specific technical reason why we don't, but rather don't do it
-/// because it's not clear it's worth the extra code to do so. If you have a
-/// use case for it, please file an issue.
-///
-/// We also don't do the union trick as we do with the forward case and
-/// prefilters. Basically for the same reason we don't have prefilters or
-/// vector algorithms for reverse searching: it's not clear it's worth doing.
-/// Please file an issue if you have a compelling use case for fast reverse
-/// substring search.
-#[derive(Clone, Debug)]
-enum SearcherRevKind {
- Empty,
- OneByte { needle: u8 },
- TwoWay { finder: twoway::FinderRev },
-}
-
-impl SearcherRev {
- /// Creates a new searcher for finding occurrences of the given needle in
- /// reverse. That is, it reports the last (instead of the first) occurrence
- /// of a needle in a haystack.
- #[inline]
- pub(crate) fn new(needle: &[u8]) -> SearcherRev {
- let kind = if needle.len() <= 1 {
- if needle.is_empty() {
- trace!("building empty reverse substring searcher");
- SearcherRevKind::Empty
- } else {
- trace!("building one-byte reverse substring searcher");
- debug_assert_eq!(1, needle.len());
- SearcherRevKind::OneByte { needle: needle[0] }
- }
- } else {
- trace!("building scalar two-way reverse substring searcher");
- let finder = twoway::FinderRev::new(needle);
- SearcherRevKind::TwoWay { finder }
- };
- let rabinkarp = rabinkarp::FinderRev::new(needle);
- SearcherRev { kind, rabinkarp }
- }
-
- /// Searches the given haystack for the last occurrence of the given
- /// needle. The needle given should be the same as the needle that this
- /// finder was initialized with.
- #[inline]
- pub(crate) fn rfind(
- &self,
- haystack: &[u8],
- needle: &[u8],
- ) -> Option<usize> {
- if haystack.len() < needle.len() {
- return None;
- }
- match self.kind {
- SearcherRevKind::Empty => Some(haystack.len()),
- SearcherRevKind::OneByte { needle } => {
- crate::memrchr(needle, haystack)
- }
- SearcherRevKind::TwoWay { ref finder } => {
- if rabinkarp::is_fast(haystack, needle) {
- self.rabinkarp.rfind(haystack, needle)
- } else {
- finder.rfind(haystack, needle)
- }
- }
- }
- }
-}
-
-/// Prefilter controls whether heuristics are used to accelerate searching.
-///
-/// A prefilter refers to the idea of detecting candidate matches very quickly,
-/// and then confirming whether those candidates are full matches. This
-/// idea can be quite effective since it's often the case that looking for
-/// candidates can be a lot faster than running a complete substring search
-/// over the entire input. Namely, looking for candidates can be done with
-/// extremely fast vectorized code.
-///
-/// The downside of a prefilter is that it assumes false positives (which are
-/// candidates generated by a prefilter that aren't matches) are somewhat rare
-/// relative to the frequency of full matches. That is, if a lot of false
-/// positives are generated, then it's possible for search time to be worse
-/// than if the prefilter wasn't enabled in the first place.
-///
-/// Another downside of a prefilter is that it can result in highly variable
-/// performance, where some cases are extraordinarily fast and others aren't.
-/// Typically, variable performance isn't a problem, but it may be for your use
-/// case.
-///
-/// The use of prefilters in this implementation does use a heuristic to detect
-/// when a prefilter might not be carrying its weight, and will dynamically
-/// disable its use. Nevertheless, this configuration option gives callers
-/// the ability to disable prefilters if you have knowledge that they won't be
-/// useful.
-#[derive(Clone, Copy, Debug)]
-#[non_exhaustive]
-pub enum PrefilterConfig {
- /// Never used a prefilter in substring search.
- None,
- /// Automatically detect whether a heuristic prefilter should be used. If
- /// it is used, then heuristics will be used to dynamically disable the
- /// prefilter if it is believed to not be carrying its weight.
- Auto,
-}
-
-impl Default for PrefilterConfig {
- fn default() -> PrefilterConfig {
- PrefilterConfig::Auto
- }
-}
-
-impl PrefilterConfig {
- /// Returns true when this prefilter is set to the `None` variant.
- fn is_none(&self) -> bool {
- matches!(*self, PrefilterConfig::None)
- }
-}
-
-/// The implementation of a prefilter.
-///
-/// This type encapsulates dispatch to one of several possible choices for a
-/// prefilter. Generally speaking, all prefilters have the same approximate
-/// algorithm: they choose a couple of bytes from the needle that are believed
-/// to be rare, use a fast vector algorithm to look for those bytes and return
-/// positions as candidates for some substring search algorithm (currently only
-/// Two-Way) to confirm as a match or not.
-///
-/// The differences between the algorithms are actually at the vector
-/// implementation level. Namely, we need different routines based on both
-/// which target architecture we're on and what CPU features are supported.
-///
-/// The straight-forwardly obvious approach here is to use an enum, and make
-/// `Prefilter::find` do case analysis to determine which algorithm was
-/// selected and invoke it. However, I've observed that this leads to poor
-/// codegen in some cases, especially in latency sensitive benchmarks. That is,
-/// this approach comes with overhead that I wasn't able to eliminate.
-///
-/// The second obvious approach is to use dynamic dispatch with traits. Doing
-/// that in this context where `Prefilter` owns the selection generally
-/// requires heap allocation, and this code is designed to run in core-only
-/// environments.
-///
-/// So we settle on using a union (that's `PrefilterKind`) and a function
-/// pointer (that's `PrefilterKindFn`). We select the right function pointer
-/// based on which field in the union we set, and that function in turn
-/// knows which field of the union to access. The downside of this approach
-/// is that it forces us to think about safety, but the upside is that
-/// there are some nice latency improvements to benchmarks. (Especially the
-/// `memmem/sliceslice/short` benchmark.)
-///
-/// In cases where we've selected a vector algorithm and the haystack given
-/// is too short, we fallback to the scalar version of `memchr` on the
-/// `rarest_byte`. (The scalar version of `memchr` is still better than a naive
-/// byte-at-a-time loop because it will read in `usize`-sized chunks at a
-/// time.)
-#[derive(Clone, Copy)]
-struct Prefilter {
- call: PrefilterKindFn,
- kind: PrefilterKind,
- rarest_byte: u8,
- rarest_offset: u8,
-}
-
-impl Prefilter {
- /// Return a "fallback" prefilter, but only if it is believed to be
- /// effective.
- #[inline]
- fn fallback<R: HeuristicFrequencyRank>(
- ranker: R,
- pair: Pair,
- needle: &[u8],
- ) -> Option<Prefilter> {
- /// The maximum frequency rank permitted for the fallback prefilter.
- /// If the rarest byte in the needle has a frequency rank above this
- /// value, then no prefilter is used if the fallback prefilter would
- /// otherwise be selected.
- const MAX_FALLBACK_RANK: u8 = 250;
-
- trace!("building fallback prefilter");
- let rarest_offset = pair.index1();
- let rarest_byte = needle[usize::from(rarest_offset)];
- let rarest_rank = ranker.rank(rarest_byte);
- if rarest_rank > MAX_FALLBACK_RANK {
- None
- } else {
- let finder = crate::arch::all::packedpair::Finder::with_pair(
- needle,
- pair.clone(),
- )?;
- let call = prefilter_kind_fallback;
- let kind = PrefilterKind { fallback: finder };
- Some(Prefilter { call, kind, rarest_byte, rarest_offset })
- }
- }
-
- /// Return a prefilter using a x86_64 SSE2 vector algorithm.
- #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
- #[inline]
- fn sse2(finder: sse2::Finder, needle: &[u8]) -> Prefilter {
- trace!("building x86_64 SSE2 prefilter");
- let rarest_offset = finder.pair().index1();
- let rarest_byte = needle[usize::from(rarest_offset)];
- Prefilter {
- call: prefilter_kind_sse2,
- kind: PrefilterKind { sse2: finder },
- rarest_byte,
- rarest_offset,
- }
- }
-
- /// Return a prefilter using a x86_64 AVX2 vector algorithm.
- #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
- #[inline]
- fn avx2(finder: avx2::Finder, needle: &[u8]) -> Prefilter {
- trace!("building x86_64 AVX2 prefilter");
- let rarest_offset = finder.pair().index1();
- let rarest_byte = needle[usize::from(rarest_offset)];
- Prefilter {
- call: prefilter_kind_avx2,
- kind: PrefilterKind { avx2: finder },
- rarest_byte,
- rarest_offset,
- }
- }
-
- /// Return a prefilter using a wasm32 simd128 vector algorithm.
- #[cfg(target_arch = "wasm32")]
- #[inline]
- fn simd128(finder: simd128::Finder, needle: &[u8]) -> Prefilter {
- trace!("building wasm32 simd128 prefilter");
- let rarest_offset = finder.pair().index1();
- let rarest_byte = needle[usize::from(rarest_offset)];
- Prefilter {
- call: prefilter_kind_simd128,
- kind: PrefilterKind { simd128: finder },
- rarest_byte,
- rarest_offset,
- }
- }
-
- /// Return a prefilter using a aarch64 neon vector algorithm.
- #[cfg(target_arch = "aarch64")]
- #[inline]
- fn neon(finder: neon::Finder, needle: &[u8]) -> Prefilter {
- trace!("building aarch64 neon prefilter");
- let rarest_offset = finder.pair().index1();
- let rarest_byte = needle[usize::from(rarest_offset)];
- Prefilter {
- call: prefilter_kind_neon,
- kind: PrefilterKind { neon: finder },
- rarest_byte,
- rarest_offset,
- }
- }
-
- /// Return a *candidate* position for a match.
- ///
- /// When this returns an offset, it implies that a match could begin at
- /// that offset, but it may not. That is, it is possible for a false
- /// positive to be returned.
- ///
- /// When `None` is returned, then it is guaranteed that there are no
- /// matches for the needle in the given haystack. That is, it is impossible
- /// for a false negative to be returned.
- ///
- /// The purpose of this routine is to look for candidate matching positions
- /// as quickly as possible before running a (likely) slower confirmation
- /// step.
- #[inline]
- fn find(&self, haystack: &[u8]) -> Option<usize> {
- // SAFETY: By construction, we've ensured that the function in
- // `self.call` is properly paired with the union used in `self.kind`.
- unsafe { (self.call)(self, haystack) }
- }
-
- /// A "simple" prefilter that just looks for the occurrence of the rarest
- /// byte from the needle. This is generally only used for very small
- /// haystacks.
- #[inline]
- fn find_simple(&self, haystack: &[u8]) -> Option<usize> {
- // We don't use crate::memchr here because the haystack should be small
- // enough that memchr won't be able to use vector routines anyway. So
- // we just skip straight to the fallback implementation which is likely
- // faster. (A byte-at-a-time loop is only used when the haystack is
- // smaller than `size_of::<usize>()`.)
- crate::arch::all::memchr::One::new(self.rarest_byte)
- .find(haystack)
- .map(|i| i.saturating_sub(usize::from(self.rarest_offset)))
- }
-}
-
-impl core::fmt::Debug for Prefilter {
- fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- f.debug_struct("Prefilter")
- .field("call", &"<prefilter function>")
- .field("kind", &"<prefilter kind union>")
- .field("rarest_byte", &self.rarest_byte)
- .field("rarest_offset", &self.rarest_offset)
- .finish()
- }
-}
-
-/// A union indicating one of several possible prefilters that are in active
-/// use.
-///
-/// This union should only be read by one of the functions prefixed with
-/// `prefilter_kind_`. Namely, the correct function is meant to be paired with
-/// the union by the caller, such that the function always reads from the
-/// designated union field.
-#[derive(Clone, Copy)]
-union PrefilterKind {
- fallback: crate::arch::all::packedpair::Finder,
- #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
- sse2: crate::arch::x86_64::sse2::packedpair::Finder,
- #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
- avx2: crate::arch::x86_64::avx2::packedpair::Finder,
- #[cfg(target_arch = "wasm32")]
- simd128: crate::arch::wasm32::simd128::packedpair::Finder,
- #[cfg(target_arch = "aarch64")]
- neon: crate::arch::aarch64::neon::packedpair::Finder,
-}
-
-/// The type of a prefilter function.
-///
-/// # Safety
-///
-/// When using a function of this type, callers must ensure that the correct
-/// function is paired with the value populated in `PrefilterKind` union.
-type PrefilterKindFn =
- unsafe fn(strat: &Prefilter, haystack: &[u8]) -> Option<usize>;
-
-/// Reads from the `fallback` field of `PrefilterKind` to execute the fallback
-/// prefilter. Works on all platforms.
-///
-/// # Safety
-///
-/// Callers must ensure that the `strat.kind.fallback` union field is set.
-unsafe fn prefilter_kind_fallback(
- strat: &Prefilter,
- haystack: &[u8],
-) -> Option<usize> {
- strat.kind.fallback.find_prefilter(haystack)
-}
-
-/// Reads from the `sse2` field of `PrefilterKind` to execute the x86_64 SSE2
-/// prefilter.
-///
-/// # Safety
-///
-/// Callers must ensure that the `strat.kind.sse2` union field is set.
-#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
-unsafe fn prefilter_kind_sse2(
- strat: &Prefilter,
- haystack: &[u8],
-) -> Option<usize> {
- let finder = &strat.kind.sse2;
- if haystack.len() < finder.min_haystack_len() {
- strat.find_simple(haystack)
- } else {
- finder.find_prefilter(haystack)
- }
-}
-
-/// Reads from the `avx2` field of `PrefilterKind` to execute the x86_64 AVX2
-/// prefilter.
-///
-/// # Safety
-///
-/// Callers must ensure that the `strat.kind.avx2` union field is set.
-#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
-unsafe fn prefilter_kind_avx2(
- strat: &Prefilter,
- haystack: &[u8],
-) -> Option<usize> {
- let finder = &strat.kind.avx2;
- if haystack.len() < finder.min_haystack_len() {
- strat.find_simple(haystack)
- } else {
- finder.find_prefilter(haystack)
- }
-}
-
-/// Reads from the `simd128` field of `PrefilterKind` to execute the wasm32
-/// simd128 prefilter.
-///
-/// # Safety
-///
-/// Callers must ensure that the `strat.kind.simd128` union field is set.
-#[cfg(target_arch = "wasm32")]
-unsafe fn prefilter_kind_simd128(
- strat: &Prefilter,
- haystack: &[u8],
-) -> Option<usize> {
- let finder = &strat.kind.simd128;
- if haystack.len() < finder.min_haystack_len() {
- strat.find_simple(haystack)
- } else {
- finder.find_prefilter(haystack)
- }
-}
-
-/// Reads from the `neon` field of `PrefilterKind` to execute the aarch64 neon
-/// prefilter.
-///
-/// # Safety
-///
-/// Callers must ensure that the `strat.kind.neon` union field is set.
-#[cfg(target_arch = "aarch64")]
-unsafe fn prefilter_kind_neon(
- strat: &Prefilter,
- haystack: &[u8],
-) -> Option<usize> {
- let finder = &strat.kind.neon;
- if haystack.len() < finder.min_haystack_len() {
- strat.find_simple(haystack)
- } else {
- finder.find_prefilter(haystack)
- }
-}
-
-/// PrefilterState tracks state associated with the effectiveness of a
-/// prefilter. It is used to track how many bytes, on average, are skipped by
-/// the prefilter. If this average dips below a certain threshold over time,
-/// then the state renders the prefilter inert and stops using it.
-///
-/// A prefilter state should be created for each search. (Where creating an
-/// iterator is treated as a single search.) A prefilter state should only be
-/// created from a `Freqy`. e.g., An inert `Freqy` will produce an inert
-/// `PrefilterState`.
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct PrefilterState {
- /// The number of skips that has been executed. This is always 1 greater
- /// than the actual number of skips. The special sentinel value of 0
- /// indicates that the prefilter is inert. This is useful to avoid
- /// additional checks to determine whether the prefilter is still
- /// "effective." Once a prefilter becomes inert, it should no longer be
- /// used (according to our heuristics).
- skips: u32,
- /// The total number of bytes that have been skipped.
- skipped: u32,
-}
-
-impl PrefilterState {
- /// The minimum number of skip attempts to try before considering whether
- /// a prefilter is effective or not.
- const MIN_SKIPS: u32 = 50;
-
- /// The minimum amount of bytes that skipping must average.
- ///
- /// This value was chosen based on varying it and checking
- /// the microbenchmarks. In particular, this can impact the
- /// pathological/repeated-{huge,small} benchmarks quite a bit if it's set
- /// too low.
- const MIN_SKIP_BYTES: u32 = 8;
-
- /// Create a fresh prefilter state.
- #[inline]
- pub(crate) fn new() -> PrefilterState {
- PrefilterState { skips: 1, skipped: 0 }
- }
-
- /// Update this state with the number of bytes skipped on the last
- /// invocation of the prefilter.
- #[inline]
- fn update(&mut self, skipped: usize) {
- self.skips = self.skips.saturating_add(1);
- // We need to do this dance since it's technically possible for
- // `skipped` to overflow a `u32`. (And we use a `u32` to reduce the
- // size of a prefilter state.)
- self.skipped = match u32::try_from(skipped) {
- Err(_) => core::u32::MAX,
- Ok(skipped) => self.skipped.saturating_add(skipped),
- };
- }
-
- /// Return true if and only if this state indicates that a prefilter is
- /// still effective.
- #[inline]
- fn is_effective(&mut self) -> bool {
- if self.is_inert() {
- return false;
- }
- if self.skips() < PrefilterState::MIN_SKIPS {
- return true;
- }
- if self.skipped >= PrefilterState::MIN_SKIP_BYTES * self.skips() {
- return true;
- }
-
- // We're inert.
- self.skips = 0;
- false
- }
-
- /// Returns true if the prefilter this state represents should no longer
- /// be used.
- #[inline]
- fn is_inert(&self) -> bool {
- self.skips == 0
- }
-
- /// Returns the total number of times the prefilter has been used.
- #[inline]
- fn skips(&self) -> u32 {
- // Remember, `0` is a sentinel value indicating inertness, so we
- // always need to subtract `1` to get our actual number of skips.
- self.skips.saturating_sub(1)
- }
-}
-
-/// A combination of prefilter effectiveness state and the prefilter itself.
-#[derive(Debug)]
-pub(crate) struct Pre<'a> {
- /// State that tracks the effectiveness of a prefilter.
- prestate: &'a mut PrefilterState,
- /// The actual prefilter.
- prestrat: &'a Prefilter,
-}
-
-impl<'a> Pre<'a> {
- /// Call this prefilter on the given haystack with the given needle.
- #[inline]
- pub(crate) fn find(&mut self, haystack: &[u8]) -> Option<usize> {
- let result = self.prestrat.find(haystack);
- self.prestate.update(result.unwrap_or(haystack.len()));
- result
- }
-
- /// Return true if and only if this prefilter should be used.
- #[inline]
- pub(crate) fn is_effective(&mut self) -> bool {
- self.prestate.is_effective()
- }
-}
-
-/// Returns true if the needle has the right characteristics for a vector
-/// algorithm to handle the entirety of substring search.
-///
-/// Vector algorithms can be used for prefilters for other substring search
-/// algorithms (like Two-Way), but they can also be used for substring search
-/// on their own. When used for substring search, vector algorithms will
-/// quickly identify candidate match positions (just like in the prefilter
-/// case), but instead of returning the candidate position they will try to
-/// confirm the match themselves. Confirmation happens via `memcmp`. This
-/// works well for short needles, but can break down when many false candidate
-/// positions are generated for large needles. Thus, we only permit vector
-/// algorithms to own substring search when the needle is of a certain length.
-#[inline]
-fn do_packed_search(needle: &[u8]) -> bool {
- /// The minimum length of a needle required for this algorithm. The minimum
- /// is 2 since a length of 1 should just use memchr and a length of 0 isn't
- /// a case handled by this searcher.
- const MIN_LEN: usize = 2;
-
- /// The maximum length of a needle required for this algorithm.
- ///
- /// In reality, there is no hard max here. The code below can handle any
- /// length needle. (Perhaps that suggests there are missing optimizations.)
- /// Instead, this is a heuristic and a bound guaranteeing our linear time
- /// complexity.
- ///
- /// It is a heuristic because when a candidate match is found, memcmp is
- /// run. For very large needles with lots of false positives, memcmp can
- /// make the code run quite slow.
- ///
- /// It is a bound because the worst case behavior with memcmp is
- /// multiplicative in the size of the needle and haystack, and we want
- /// to keep that additive. This bound ensures we still meet that bound
- /// theoretically, since it's just a constant. We aren't acting in bad
- /// faith here, memcmp on tiny needles is so fast that even in pathological
- /// cases (see pathological vector benchmarks), this is still just as fast
- /// or faster in practice.
- ///
- /// This specific number was chosen by tweaking a bit and running
- /// benchmarks. The rare-medium-needle, for example, gets about 5% faster
- /// by using this algorithm instead of a prefilter-accelerated Two-Way.
- /// There's also a theoretical desire to keep this number reasonably
- /// low, to mitigate the impact of pathological cases. I did try 64, and
- /// some benchmarks got a little better, and others (particularly the
- /// pathological ones), got a lot worse. So... 32 it is?
- const MAX_LEN: usize = 32;
- MIN_LEN <= needle.len() && needle.len() <= MAX_LEN
-}
diff --git a/vendor/memchr/src/tests/memchr/mod.rs b/vendor/memchr/src/tests/memchr/mod.rs
deleted file mode 100644
index 0564ad4..0000000
--- a/vendor/memchr/src/tests/memchr/mod.rs
+++ /dev/null
@@ -1,307 +0,0 @@
-use alloc::{
- string::{String, ToString},
- vec,
- vec::Vec,
-};
-
-use crate::ext::Byte;
-
-pub(crate) mod naive;
-#[macro_use]
-pub(crate) mod prop;
-
-const SEEDS: &'static [Seed] = &[
- Seed { haystack: "a", needles: &[b'a'], positions: &[0] },
- Seed { haystack: "aa", needles: &[b'a'], positions: &[0, 1] },
- Seed { haystack: "aaa", needles: &[b'a'], positions: &[0, 1, 2] },
- Seed { haystack: "", needles: &[b'a'], positions: &[] },
- Seed { haystack: "z", needles: &[b'a'], positions: &[] },
- Seed { haystack: "zz", needles: &[b'a'], positions: &[] },
- Seed { haystack: "zza", needles: &[b'a'], positions: &[2] },
- Seed { haystack: "zaza", needles: &[b'a'], positions: &[1, 3] },
- Seed { haystack: "zzza", needles: &[b'a'], positions: &[3] },
- Seed { haystack: "\x00a", needles: &[b'a'], positions: &[1] },
- Seed { haystack: "\x00", needles: &[b'\x00'], positions: &[0] },
- Seed { haystack: "\x00\x00", needles: &[b'\x00'], positions: &[0, 1] },
- Seed { haystack: "\x00a\x00", needles: &[b'\x00'], positions: &[0, 2] },
- Seed { haystack: "zzzzzzzzzzzzzzzza", needles: &[b'a'], positions: &[16] },
- Seed {
- haystack: "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzza",
- needles: &[b'a'],
- positions: &[32],
- },
- // two needles (applied to memchr2 + memchr3)
- Seed { haystack: "az", needles: &[b'a', b'z'], positions: &[0, 1] },
- Seed { haystack: "az", needles: &[b'a', b'z'], positions: &[0, 1] },
- Seed { haystack: "az", needles: &[b'x', b'y'], positions: &[] },
- Seed { haystack: "az", needles: &[b'a', b'y'], positions: &[0] },
- Seed { haystack: "az", needles: &[b'x', b'z'], positions: &[1] },
- Seed { haystack: "yyyyaz", needles: &[b'a', b'z'], positions: &[4, 5] },
- Seed { haystack: "yyyyaz", needles: &[b'z', b'a'], positions: &[4, 5] },
- // three needles (applied to memchr3)
- Seed {
- haystack: "xyz",
- needles: &[b'x', b'y', b'z'],
- positions: &[0, 1, 2],
- },
- Seed {
- haystack: "zxy",
- needles: &[b'x', b'y', b'z'],
- positions: &[0, 1, 2],
- },
- Seed { haystack: "zxy", needles: &[b'x', b'a', b'z'], positions: &[0, 1] },
- Seed { haystack: "zxy", needles: &[b't', b'a', b'z'], positions: &[0] },
- Seed { haystack: "yxz", needles: &[b't', b'a', b'z'], positions: &[2] },
-];
-
-/// Runs a host of substring search tests.
-///
-/// This has support for "partial" substring search implementations only work
-/// for a subset of needles/haystacks. For example, the "packed pair" substring
-/// search implementation only works for haystacks of some minimum length based
-/// of the pair of bytes selected and the size of the vector used.
-pub(crate) struct Runner {
- needle_len: usize,
-}
-
-impl Runner {
- /// Create a new test runner for forward and reverse byte search
- /// implementations.
- ///
- /// The `needle_len` given must be at most `3` and at least `1`. It
- /// corresponds to the number of needle bytes to search for.
- pub(crate) fn new(needle_len: usize) -> Runner {
- assert!(needle_len >= 1, "needle_len must be at least 1");
- assert!(needle_len <= 3, "needle_len must be at most 3");
- Runner { needle_len }
- }
-
- /// Run all tests. This panics on the first failure.
- ///
- /// If the implementation being tested returns `None` for a particular
- /// haystack/needle combination, then that test is skipped.
- pub(crate) fn forward_iter<F>(self, mut test: F)
- where
- F: FnMut(&[u8], &[u8]) -> Option<Vec<usize>> + 'static,
- {
- for seed in SEEDS.iter() {
- if seed.needles.len() > self.needle_len {
- continue;
- }
- for t in seed.generate() {
- let results = match test(t.haystack.as_bytes(), &t.needles) {
- None => continue,
- Some(results) => results,
- };
- assert_eq!(
- t.expected,
- results,
- "needles: {:?}, haystack: {:?}",
- t.needles
- .iter()
- .map(|&b| b.to_char())
- .collect::<Vec<char>>(),
- t.haystack,
- );
- }
- }
- }
-
- /// Run all tests in the reverse direction. This panics on the first
- /// failure.
- ///
- /// If the implementation being tested returns `None` for a particular
- /// haystack/needle combination, then that test is skipped.
- pub(crate) fn reverse_iter<F>(self, mut test: F)
- where
- F: FnMut(&[u8], &[u8]) -> Option<Vec<usize>> + 'static,
- {
- for seed in SEEDS.iter() {
- if seed.needles.len() > self.needle_len {
- continue;
- }
- for t in seed.generate() {
- let mut results = match test(t.haystack.as_bytes(), &t.needles)
- {
- None => continue,
- Some(results) => results,
- };
- results.reverse();
- assert_eq!(
- t.expected,
- results,
- "needles: {:?}, haystack: {:?}",
- t.needles
- .iter()
- .map(|&b| b.to_char())
- .collect::<Vec<char>>(),
- t.haystack,
- );
- }
- }
- }
-
- /// Run all tests as counting tests. This panics on the first failure.
- ///
- /// That is, this only checks that the number of matches is correct and
- /// not whether the offsets of each match are.
- pub(crate) fn count_iter<F>(self, mut test: F)
- where
- F: FnMut(&[u8], &[u8]) -> Option<usize> + 'static,
- {
- for seed in SEEDS.iter() {
- if seed.needles.len() > self.needle_len {
- continue;
- }
- for t in seed.generate() {
- let got = match test(t.haystack.as_bytes(), &t.needles) {
- None => continue,
- Some(got) => got,
- };
- assert_eq!(
- t.expected.len(),
- got,
- "needles: {:?}, haystack: {:?}",
- t.needles
- .iter()
- .map(|&b| b.to_char())
- .collect::<Vec<char>>(),
- t.haystack,
- );
- }
- }
- }
-
- /// Like `Runner::forward`, but for a function that returns only the next
- /// match and not all matches.
- ///
- /// If the function returns `None`, then it is skipped.
- pub(crate) fn forward_oneshot<F>(self, mut test: F)
- where
- F: FnMut(&[u8], &[u8]) -> Option<Option<usize>> + 'static,
- {
- self.forward_iter(move |haystack, needles| {
- let mut start = 0;
- let mut results = vec![];
- while let Some(i) = test(&haystack[start..], needles)? {
- results.push(start + i);
- start += i + 1;
- }
- Some(results)
- })
- }
-
- /// Like `Runner::reverse`, but for a function that returns only the last
- /// match and not all matches.
- ///
- /// If the function returns `None`, then it is skipped.
- pub(crate) fn reverse_oneshot<F>(self, mut test: F)
- where
- F: FnMut(&[u8], &[u8]) -> Option<Option<usize>> + 'static,
- {
- self.reverse_iter(move |haystack, needles| {
- let mut end = haystack.len();
- let mut results = vec![];
- while let Some(i) = test(&haystack[..end], needles)? {
- results.push(i);
- end = i;
- }
- Some(results)
- })
- }
-}
-
-/// A single test for memr?chr{,2,3}.
-#[derive(Clone, Debug)]
-struct Test {
- /// The string to search in.
- haystack: String,
- /// The needles to look for.
- needles: Vec<u8>,
- /// The offsets that are expected to be found for all needles in the
- /// forward direction.
- expected: Vec<usize>,
-}
-
-impl Test {
- fn new(seed: &Seed) -> Test {
- Test {
- haystack: seed.haystack.to_string(),
- needles: seed.needles.to_vec(),
- expected: seed.positions.to_vec(),
- }
- }
-}
-
-/// Data that can be expanded into many memchr tests by padding out the corpus.
-#[derive(Clone, Debug)]
-struct Seed {
- /// The thing to search. We use `&str` instead of `&[u8]` because they
- /// are nicer to write in tests, and we don't miss much since memchr
- /// doesn't care about UTF-8.
- ///
- /// Corpora cannot contain either '%' or '#'. We use these bytes when
- /// expanding test cases into many test cases, and we assume they are not
- /// used. If they are used, `memchr_tests` will panic.
- haystack: &'static str,
- /// The needles to search for. This is intended to be an alternation of
- /// needles. The number of needles may cause this test to be skipped for
- /// some memchr variants. For example, a test with 2 needles cannot be used
- /// to test `memchr`, but can be used to test `memchr2` and `memchr3`.
- /// However, a test with only 1 needle can be used to test all of `memchr`,
- /// `memchr2` and `memchr3`. We achieve this by filling in the needles with
- /// bytes that we never used in the corpus (such as '#').
- needles: &'static [u8],
- /// The positions expected to match for all of the needles.
- positions: &'static [usize],
-}
-
-impl Seed {
- /// Controls how much we expand the haystack on either side for each test.
- /// We lower this on Miri because otherwise running the tests would take
- /// forever.
- const EXPAND_LEN: usize = {
- #[cfg(not(miri))]
- {
- 515
- }
- #[cfg(miri)]
- {
- 6
- }
- };
-
- /// Expand this test into many variations of the same test.
- ///
- /// In particular, this will generate more tests with larger corpus sizes.
- /// The expected positions are updated to maintain the integrity of the
- /// test.
- ///
- /// This is important in testing a memchr implementation, because there are
- /// often different cases depending on the length of the corpus.
- ///
- /// Note that we extend the corpus by adding `%` bytes, which we
- /// don't otherwise use as a needle.
- fn generate(&self) -> impl Iterator<Item = Test> {
- let mut more = vec![];
-
- // Add bytes to the start of the corpus.
- for i in 0..Seed::EXPAND_LEN {
- let mut t = Test::new(self);
- let mut new: String = core::iter::repeat('%').take(i).collect();
- new.push_str(&t.haystack);
- t.haystack = new;
- t.expected = t.expected.into_iter().map(|p| p + i).collect();
- more.push(t);
- }
- // Add bytes to the end of the corpus.
- for i in 1..Seed::EXPAND_LEN {
- let mut t = Test::new(self);
- let padding: String = core::iter::repeat('%').take(i).collect();
- t.haystack.push_str(&padding);
- more.push(t);
- }
-
- more.into_iter()
- }
-}
diff --git a/vendor/memchr/src/tests/memchr/naive.rs b/vendor/memchr/src/tests/memchr/naive.rs
deleted file mode 100644
index 6ebcdae..0000000
--- a/vendor/memchr/src/tests/memchr/naive.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-pub(crate) fn memchr(n1: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().position(|&b| b == n1)
-}
-
-pub(crate) fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().position(|&b| b == n1 || b == n2)
-}
-
-pub(crate) fn memchr3(
- n1: u8,
- n2: u8,
- n3: u8,
- haystack: &[u8],
-) -> Option<usize> {
- haystack.iter().position(|&b| b == n1 || b == n2 || b == n3)
-}
-
-pub(crate) fn memrchr(n1: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().rposition(|&b| b == n1)
-}
-
-pub(crate) fn memrchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().rposition(|&b| b == n1 || b == n2)
-}
-
-pub(crate) fn memrchr3(
- n1: u8,
- n2: u8,
- n3: u8,
- haystack: &[u8],
-) -> Option<usize> {
- haystack.iter().rposition(|&b| b == n1 || b == n2 || b == n3)
-}
diff --git a/vendor/memchr/src/tests/memchr/prop.rs b/vendor/memchr/src/tests/memchr/prop.rs
deleted file mode 100644
index b988260..0000000
--- a/vendor/memchr/src/tests/memchr/prop.rs
+++ /dev/null
@@ -1,321 +0,0 @@
-#[cfg(miri)]
-#[macro_export]
-macro_rules! define_memchr_quickcheck {
- ($($tt:tt)*) => {};
-}
-
-#[cfg(not(miri))]
-#[macro_export]
-macro_rules! define_memchr_quickcheck {
- ($mod:ident) => {
- define_memchr_quickcheck!($mod, new);
- };
- ($mod:ident, $cons:ident) => {
- use alloc::vec::Vec;
-
- use quickcheck::TestResult;
-
- use crate::tests::memchr::{
- naive,
- prop::{double_ended_take, naive1_iter, naive2_iter, naive3_iter},
- };
-
- quickcheck::quickcheck! {
- fn qc_memchr_matches_naive(n1: u8, corpus: Vec<u8>) -> TestResult {
- let expected = naive::memchr(n1, &corpus);
- let got = match $mod::One::$cons(n1) {
- None => return TestResult::discard(),
- Some(f) => f.find(&corpus),
- };
- TestResult::from_bool(expected == got)
- }
-
- fn qc_memrchr_matches_naive(n1: u8, corpus: Vec<u8>) -> TestResult {
- let expected = naive::memrchr(n1, &corpus);
- let got = match $mod::One::$cons(n1) {
- None => return TestResult::discard(),
- Some(f) => f.rfind(&corpus),
- };
- TestResult::from_bool(expected == got)
- }
-
- fn qc_memchr2_matches_naive(n1: u8, n2: u8, corpus: Vec<u8>) -> TestResult {
- let expected = naive::memchr2(n1, n2, &corpus);
- let got = match $mod::Two::$cons(n1, n2) {
- None => return TestResult::discard(),
- Some(f) => f.find(&corpus),
- };
- TestResult::from_bool(expected == got)
- }
-
- fn qc_memrchr2_matches_naive(n1: u8, n2: u8, corpus: Vec<u8>) -> TestResult {
- let expected = naive::memrchr2(n1, n2, &corpus);
- let got = match $mod::Two::$cons(n1, n2) {
- None => return TestResult::discard(),
- Some(f) => f.rfind(&corpus),
- };
- TestResult::from_bool(expected == got)
- }
-
- fn qc_memchr3_matches_naive(
- n1: u8, n2: u8, n3: u8,
- corpus: Vec<u8>
- ) -> TestResult {
- let expected = naive::memchr3(n1, n2, n3, &corpus);
- let got = match $mod::Three::$cons(n1, n2, n3) {
- None => return TestResult::discard(),
- Some(f) => f.find(&corpus),
- };
- TestResult::from_bool(expected == got)
- }
-
- fn qc_memrchr3_matches_naive(
- n1: u8, n2: u8, n3: u8,
- corpus: Vec<u8>
- ) -> TestResult {
- let expected = naive::memrchr3(n1, n2, n3, &corpus);
- let got = match $mod::Three::$cons(n1, n2, n3) {
- None => return TestResult::discard(),
- Some(f) => f.rfind(&corpus),
- };
- TestResult::from_bool(expected == got)
- }
-
- fn qc_memchr_double_ended_iter(
- needle: u8, data: Vec<u8>, take_side: Vec<bool>
- ) -> TestResult {
- // make nonempty
- let mut take_side = take_side;
- if take_side.is_empty() { take_side.push(true) };
-
- let finder = match $mod::One::$cons(needle) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let iter = finder.iter(&data);
- let got = double_ended_take(
- iter,
- take_side.iter().cycle().cloned(),
- );
- let expected = naive1_iter(needle, &data);
-
- TestResult::from_bool(got.iter().cloned().eq(expected))
- }
-
- fn qc_memchr2_double_ended_iter(
- needle1: u8, needle2: u8, data: Vec<u8>, take_side: Vec<bool>
- ) -> TestResult {
- // make nonempty
- let mut take_side = take_side;
- if take_side.is_empty() { take_side.push(true) };
-
- let finder = match $mod::Two::$cons(needle1, needle2) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let iter = finder.iter(&data);
- let got = double_ended_take(
- iter,
- take_side.iter().cycle().cloned(),
- );
- let expected = naive2_iter(needle1, needle2, &data);
-
- TestResult::from_bool(got.iter().cloned().eq(expected))
- }
-
- fn qc_memchr3_double_ended_iter(
- needle1: u8, needle2: u8, needle3: u8,
- data: Vec<u8>, take_side: Vec<bool>
- ) -> TestResult {
- // make nonempty
- let mut take_side = take_side;
- if take_side.is_empty() { take_side.push(true) };
-
- let finder = match $mod::Three::$cons(needle1, needle2, needle3) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let iter = finder.iter(&data);
- let got = double_ended_take(
- iter,
- take_side.iter().cycle().cloned(),
- );
- let expected = naive3_iter(needle1, needle2, needle3, &data);
-
- TestResult::from_bool(got.iter().cloned().eq(expected))
- }
-
- fn qc_memchr1_iter(data: Vec<u8>) -> TestResult {
- let needle = 0;
- let finder = match $mod::One::$cons(needle) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let got = finder.iter(&data);
- let expected = naive1_iter(needle, &data);
- TestResult::from_bool(got.eq(expected))
- }
-
- fn qc_memchr1_rev_iter(data: Vec<u8>) -> TestResult {
- let needle = 0;
-
- let finder = match $mod::One::$cons(needle) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let got = finder.iter(&data).rev();
- let expected = naive1_iter(needle, &data).rev();
- TestResult::from_bool(got.eq(expected))
- }
-
- fn qc_memchr2_iter(data: Vec<u8>) -> TestResult {
- let needle1 = 0;
- let needle2 = 1;
-
- let finder = match $mod::Two::$cons(needle1, needle2) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let got = finder.iter(&data);
- let expected = naive2_iter(needle1, needle2, &data);
- TestResult::from_bool(got.eq(expected))
- }
-
- fn qc_memchr2_rev_iter(data: Vec<u8>) -> TestResult {
- let needle1 = 0;
- let needle2 = 1;
-
- let finder = match $mod::Two::$cons(needle1, needle2) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let got = finder.iter(&data).rev();
- let expected = naive2_iter(needle1, needle2, &data).rev();
- TestResult::from_bool(got.eq(expected))
- }
-
- fn qc_memchr3_iter(data: Vec<u8>) -> TestResult {
- let needle1 = 0;
- let needle2 = 1;
- let needle3 = 2;
-
- let finder = match $mod::Three::$cons(needle1, needle2, needle3) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let got = finder.iter(&data);
- let expected = naive3_iter(needle1, needle2, needle3, &data);
- TestResult::from_bool(got.eq(expected))
- }
-
- fn qc_memchr3_rev_iter(data: Vec<u8>) -> TestResult {
- let needle1 = 0;
- let needle2 = 1;
- let needle3 = 2;
-
- let finder = match $mod::Three::$cons(needle1, needle2, needle3) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let got = finder.iter(&data).rev();
- let expected = naive3_iter(needle1, needle2, needle3, &data).rev();
- TestResult::from_bool(got.eq(expected))
- }
-
- fn qc_memchr1_iter_size_hint(data: Vec<u8>) -> TestResult {
- // test that the size hint is within reasonable bounds
- let needle = 0;
- let finder = match $mod::One::$cons(needle) {
- None => return TestResult::discard(),
- Some(finder) => finder,
- };
- let mut iter = finder.iter(&data);
- let mut real_count = data
- .iter()
- .filter(|&&elt| elt == needle)
- .count();
-
- while let Some(index) = iter.next() {
- real_count -= 1;
- let (lower, upper) = iter.size_hint();
- assert!(lower <= real_count);
- assert!(upper.unwrap() >= real_count);
- assert!(upper.unwrap() <= data.len() - index);
- }
- TestResult::passed()
- }
- }
- };
-}
-
-// take items from a DEI, taking front for each true and back for each false.
-// Return a vector with the concatenation of the fronts and the reverse of the
-// backs.
-#[cfg(not(miri))]
-pub(crate) fn double_ended_take<I, J>(
- mut iter: I,
- take_side: J,
-) -> alloc::vec::Vec<I::Item>
-where
- I: DoubleEndedIterator,
- J: Iterator<Item = bool>,
-{
- let mut found_front = alloc::vec![];
- let mut found_back = alloc::vec![];
-
- for take_front in take_side {
- if take_front {
- if let Some(pos) = iter.next() {
- found_front.push(pos);
- } else {
- break;
- }
- } else {
- if let Some(pos) = iter.next_back() {
- found_back.push(pos);
- } else {
- break;
- }
- };
- }
-
- let mut all_found = found_front;
- all_found.extend(found_back.into_iter().rev());
- all_found
-}
-
-// return an iterator of the 0-based indices of haystack that match the needle
-#[cfg(not(miri))]
-pub(crate) fn naive1_iter<'a>(
- n1: u8,
- haystack: &'a [u8],
-) -> impl DoubleEndedIterator<Item = usize> + 'a {
- haystack.iter().enumerate().filter(move |&(_, &b)| b == n1).map(|t| t.0)
-}
-
-#[cfg(not(miri))]
-pub(crate) fn naive2_iter<'a>(
- n1: u8,
- n2: u8,
- haystack: &'a [u8],
-) -> impl DoubleEndedIterator<Item = usize> + 'a {
- haystack
- .iter()
- .enumerate()
- .filter(move |&(_, &b)| b == n1 || b == n2)
- .map(|t| t.0)
-}
-
-#[cfg(not(miri))]
-pub(crate) fn naive3_iter<'a>(
- n1: u8,
- n2: u8,
- n3: u8,
- haystack: &'a [u8],
-) -> impl DoubleEndedIterator<Item = usize> + 'a {
- haystack
- .iter()
- .enumerate()
- .filter(move |&(_, &b)| b == n1 || b == n2 || b == n3)
- .map(|t| t.0)
-}
diff --git a/vendor/memchr/src/tests/mod.rs b/vendor/memchr/src/tests/mod.rs
deleted file mode 100644
index 259b678..0000000
--- a/vendor/memchr/src/tests/mod.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#[macro_use]
-pub(crate) mod memchr;
-pub(crate) mod packedpair;
-#[macro_use]
-pub(crate) mod substring;
-
-// For debugging, particularly in CI, print out the byte order of the current
-// target.
-#[test]
-fn byte_order() {
- #[cfg(target_endian = "little")]
- std::eprintln!("LITTLE ENDIAN");
- #[cfg(target_endian = "big")]
- std::eprintln!("BIG ENDIAN");
-}
diff --git a/vendor/memchr/src/tests/packedpair.rs b/vendor/memchr/src/tests/packedpair.rs
deleted file mode 100644
index 204635b..0000000
--- a/vendor/memchr/src/tests/packedpair.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-use alloc::{boxed::Box, vec, vec::Vec};
-
-/// A set of "packed pair" test seeds. Each seed serves as the base for the
-/// generation of many other tests. In essence, the seed captures the pair of
-/// bytes we used for a predicate and first byte among our needle. The tests
-/// generated from each seed essentially vary the length of the needle and
-/// haystack, while using the rare/first byte configuration from the seed.
-///
-/// The purpose of this is to test many different needle/haystack lengths.
-/// In particular, some of the vector optimizations might only have bugs
-/// in haystacks of a certain size.
-const SEEDS: &[Seed] = &[
- // Why not use different 'first' bytes? It seemed like a good idea to be
- // able to configure it, but when I wrote the test generator below, it
- // didn't seem necessary to use for reasons that I forget.
- Seed { first: b'x', index1: b'y', index2: b'z' },
- Seed { first: b'x', index1: b'x', index2: b'z' },
- Seed { first: b'x', index1: b'y', index2: b'x' },
- Seed { first: b'x', index1: b'x', index2: b'x' },
- Seed { first: b'x', index1: b'y', index2: b'y' },
-];
-
-/// Runs a host of "packed pair" search tests.
-///
-/// These tests specifically look for the occurrence of a possible substring
-/// match based on a pair of bytes matching at the right offsets.
-pub(crate) struct Runner {
- fwd: Option<
- Box<
- dyn FnMut(&[u8], &[u8], u8, u8) -> Option<Option<usize>> + 'static,
- >,
- >,
-}
-
-impl Runner {
- /// Create a new test runner for "packed pair" substring search.
- pub(crate) fn new() -> Runner {
- Runner { fwd: None }
- }
-
- /// Run all tests. This panics on the first failure.
- ///
- /// If the implementation being tested returns `None` for a particular
- /// haystack/needle combination, then that test is skipped.
- ///
- /// This runs tests on both the forward and reverse implementations given.
- /// If either (or both) are missing, then tests for that implementation are
- /// skipped.
- pub(crate) fn run(self) {
- if let Some(mut fwd) = self.fwd {
- for seed in SEEDS.iter() {
- for t in seed.generate() {
- match fwd(&t.haystack, &t.needle, t.index1, t.index2) {
- None => continue,
- Some(result) => {
- assert_eq!(
- t.fwd, result,
- "FORWARD, needle: {:?}, haystack: {:?}, \
- index1: {:?}, index2: {:?}",
- t.needle, t.haystack, t.index1, t.index2,
- )
- }
- }
- }
- }
- }
- }
-
- /// Set the implementation for forward "packed pair" substring search.
- ///
- /// If the closure returns `None`, then it is assumed that the given
- /// test cannot be applied to the particular implementation and it is
- /// skipped. For example, if a particular implementation only supports
- /// needles or haystacks for some minimum length.
- ///
- /// If this is not set, then forward "packed pair" search is not tested.
- pub(crate) fn fwd(
- mut self,
- search: impl FnMut(&[u8], &[u8], u8, u8) -> Option<Option<usize>> + 'static,
- ) -> Runner {
- self.fwd = Some(Box::new(search));
- self
- }
-}
-
-/// A test that represents the input and expected output to a "packed pair"
-/// search function. The test should be able to run with any "packed pair"
-/// implementation and get the expected output.
-struct Test {
- haystack: Vec<u8>,
- needle: Vec<u8>,
- index1: u8,
- index2: u8,
- fwd: Option<usize>,
-}
-
-impl Test {
- /// Create a new "packed pair" test from a seed and some given offsets to
- /// the pair of bytes to use as a predicate in the seed's needle.
- ///
- /// If a valid test could not be constructed, then None is returned.
- /// (Currently, we take the approach of massaging tests to be valid
- /// instead of rejecting them outright.)
- fn new(
- seed: Seed,
- index1: usize,
- index2: usize,
- haystack_len: usize,
- needle_len: usize,
- fwd: Option<usize>,
- ) -> Option<Test> {
- let mut index1: u8 = index1.try_into().unwrap();
- let mut index2: u8 = index2.try_into().unwrap();
- // The '#' byte is never used in a haystack (unless we're expecting
- // a match), while the '@' byte is never used in a needle.
- let mut haystack = vec![b'@'; haystack_len];
- let mut needle = vec![b'#'; needle_len];
- needle[0] = seed.first;
- needle[index1 as usize] = seed.index1;
- needle[index2 as usize] = seed.index2;
- // If we're expecting a match, then make sure the needle occurs
- // in the haystack at the expected position.
- if let Some(i) = fwd {
- haystack[i..i + needle.len()].copy_from_slice(&needle);
- }
- // If the operations above lead to rare offsets pointing to the
- // non-first occurrence of a byte, then adjust it. This might lead
- // to redundant tests, but it's simpler than trying to change the
- // generation process I think.
- if let Some(i) = crate::memchr(seed.index1, &needle) {
- index1 = u8::try_from(i).unwrap();
- }
- if let Some(i) = crate::memchr(seed.index2, &needle) {
- index2 = u8::try_from(i).unwrap();
- }
- Some(Test { haystack, needle, index1, index2, fwd })
- }
-}
-
-/// Data that describes a single prefilter test seed.
-#[derive(Clone, Copy)]
-struct Seed {
- first: u8,
- index1: u8,
- index2: u8,
-}
-
-impl Seed {
- const NEEDLE_LENGTH_LIMIT: usize = {
- #[cfg(not(miri))]
- {
- 33
- }
- #[cfg(miri)]
- {
- 5
- }
- };
-
- const HAYSTACK_LENGTH_LIMIT: usize = {
- #[cfg(not(miri))]
- {
- 65
- }
- #[cfg(miri)]
- {
- 8
- }
- };
-
- /// Generate a series of prefilter tests from this seed.
- fn generate(self) -> impl Iterator<Item = Test> {
- let len_start = 2;
- // The iterator below generates *a lot* of tests. The number of
- // tests was chosen somewhat empirically to be "bearable" when
- // running the test suite.
- //
- // We use an iterator here because the collective haystacks of all
- // these test cases add up to enough memory to OOM a conservative
- // sandbox or a small laptop.
- (len_start..=Seed::NEEDLE_LENGTH_LIMIT).flat_map(move |needle_len| {
- let index_start = len_start - 1;
- (index_start..needle_len).flat_map(move |index1| {
- (index1..needle_len).flat_map(move |index2| {
- (needle_len..=Seed::HAYSTACK_LENGTH_LIMIT).flat_map(
- move |haystack_len| {
- Test::new(
- self,
- index1,
- index2,
- haystack_len,
- needle_len,
- None,
- )
- .into_iter()
- .chain(
- (0..=(haystack_len - needle_len)).flat_map(
- move |output| {
- Test::new(
- self,
- index1,
- index2,
- haystack_len,
- needle_len,
- Some(output),
- )
- },
- ),
- )
- },
- )
- })
- })
- })
- }
-}
diff --git a/vendor/memchr/src/tests/substring/mod.rs b/vendor/memchr/src/tests/substring/mod.rs
deleted file mode 100644
index dd10cbd..0000000
--- a/vendor/memchr/src/tests/substring/mod.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-/*!
-This module defines tests and test helpers for substring implementations.
-*/
-
-use alloc::{
- boxed::Box,
- format,
- string::{String, ToString},
-};
-
-pub(crate) mod naive;
-#[macro_use]
-pub(crate) mod prop;
-
-const SEEDS: &'static [Seed] = &[
- Seed::new("", "", Some(0), Some(0)),
- Seed::new("", "a", Some(0), Some(1)),
- Seed::new("", "ab", Some(0), Some(2)),
- Seed::new("", "abc", Some(0), Some(3)),
- Seed::new("a", "", None, None),
- Seed::new("a", "a", Some(0), Some(0)),
- Seed::new("a", "aa", Some(0), Some(1)),
- Seed::new("a", "ba", Some(1), Some(1)),
- Seed::new("a", "bba", Some(2), Some(2)),
- Seed::new("a", "bbba", Some(3), Some(3)),
- Seed::new("a", "bbbab", Some(3), Some(3)),
- Seed::new("a", "bbbabb", Some(3), Some(3)),
- Seed::new("a", "bbbabbb", Some(3), Some(3)),
- Seed::new("a", "bbbbbb", None, None),
- Seed::new("ab", "", None, None),
- Seed::new("ab", "a", None, None),
- Seed::new("ab", "b", None, None),
- Seed::new("ab", "ab", Some(0), Some(0)),
- Seed::new("ab", "aab", Some(1), Some(1)),
- Seed::new("ab", "aaab", Some(2), Some(2)),
- Seed::new("ab", "abaab", Some(0), Some(3)),
- Seed::new("ab", "baaab", Some(3), Some(3)),
- Seed::new("ab", "acb", None, None),
- Seed::new("ab", "abba", Some(0), Some(0)),
- Seed::new("abc", "ab", None, None),
- Seed::new("abc", "abc", Some(0), Some(0)),
- Seed::new("abc", "abcz", Some(0), Some(0)),
- Seed::new("abc", "abczz", Some(0), Some(0)),
- Seed::new("abc", "zabc", Some(1), Some(1)),
- Seed::new("abc", "zzabc", Some(2), Some(2)),
- Seed::new("abc", "azbc", None, None),
- Seed::new("abc", "abzc", None, None),
- Seed::new("abczdef", "abczdefzzzzzzzzzzzzzzzzzzzz", Some(0), Some(0)),
- Seed::new("abczdef", "zzzzzzzzzzzzzzzzzzzzabczdef", Some(20), Some(20)),
- Seed::new(
- "xyz",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxyz",
- Some(32),
- Some(32),
- ),
- Seed::new("\u{0}\u{15}", "\u{0}\u{15}\u{15}\u{0}", Some(0), Some(0)),
- Seed::new("\u{0}\u{1e}", "\u{1e}\u{0}", None, None),
-];
-
-/// Runs a host of substring search tests.
-///
-/// This has support for "partial" substring search implementations only work
-/// for a subset of needles/haystacks. For example, the "packed pair" substring
-/// search implementation only works for haystacks of some minimum length based
-/// of the pair of bytes selected and the size of the vector used.
-pub(crate) struct Runner {
- fwd: Option<
- Box<dyn FnMut(&[u8], &[u8]) -> Option<Option<usize>> + 'static>,
- >,
- rev: Option<
- Box<dyn FnMut(&[u8], &[u8]) -> Option<Option<usize>> + 'static>,
- >,
-}
-
-impl Runner {
- /// Create a new test runner for forward and reverse substring search
- /// implementations.
- pub(crate) fn new() -> Runner {
- Runner { fwd: None, rev: None }
- }
-
- /// Run all tests. This panics on the first failure.
- ///
- /// If the implementation being tested returns `None` for a particular
- /// haystack/needle combination, then that test is skipped.
- ///
- /// This runs tests on both the forward and reverse implementations given.
- /// If either (or both) are missing, then tests for that implementation are
- /// skipped.
- pub(crate) fn run(self) {
- if let Some(mut fwd) = self.fwd {
- for seed in SEEDS.iter() {
- for t in seed.generate() {
- match fwd(t.haystack.as_bytes(), t.needle.as_bytes()) {
- None => continue,
- Some(result) => {
- assert_eq!(
- t.fwd, result,
- "FORWARD, needle: {:?}, haystack: {:?}",
- t.needle, t.haystack,
- );
- }
- }
- }
- }
- }
- if let Some(mut rev) = self.rev {
- for seed in SEEDS.iter() {
- for t in seed.generate() {
- match rev(t.haystack.as_bytes(), t.needle.as_bytes()) {
- None => continue,
- Some(result) => {
- assert_eq!(
- t.rev, result,
- "REVERSE, needle: {:?}, haystack: {:?}",
- t.needle, t.haystack,
- );
- }
- }
- }
- }
- }
- }
-
- /// Set the implementation for forward substring search.
- ///
- /// If the closure returns `None`, then it is assumed that the given
- /// test cannot be applied to the particular implementation and it is
- /// skipped. For example, if a particular implementation only supports
- /// needles or haystacks for some minimum length.
- ///
- /// If this is not set, then forward substring search is not tested.
- pub(crate) fn fwd(
- mut self,
- search: impl FnMut(&[u8], &[u8]) -> Option<Option<usize>> + 'static,
- ) -> Runner {
- self.fwd = Some(Box::new(search));
- self
- }
-
- /// Set the implementation for reverse substring search.
- ///
- /// If the closure returns `None`, then it is assumed that the given
- /// test cannot be applied to the particular implementation and it is
- /// skipped. For example, if a particular implementation only supports
- /// needles or haystacks for some minimum length.
- ///
- /// If this is not set, then reverse substring search is not tested.
- pub(crate) fn rev(
- mut self,
- search: impl FnMut(&[u8], &[u8]) -> Option<Option<usize>> + 'static,
- ) -> Runner {
- self.rev = Some(Box::new(search));
- self
- }
-}
-
-/// A single substring test for forward and reverse searches.
-#[derive(Clone, Debug)]
-struct Test {
- needle: String,
- haystack: String,
- fwd: Option<usize>,
- rev: Option<usize>,
-}
-
-/// A single substring test for forward and reverse searches.
-///
-/// Each seed is valid on its own, but it also serves as a starting point
-/// to generate more tests. Namely, we pad out the haystacks with other
-/// characters so that we get more complete coverage. This is especially useful
-/// for testing vector algorithms that tend to have weird special cases for
-/// alignment and loop unrolling.
-///
-/// Padding works by assuming certain characters never otherwise appear in a
-/// needle or a haystack. Neither should contain a `#` character.
-#[derive(Clone, Copy, Debug)]
-struct Seed {
- needle: &'static str,
- haystack: &'static str,
- fwd: Option<usize>,
- rev: Option<usize>,
-}
-
-impl Seed {
- const MAX_PAD: usize = 34;
-
- const fn new(
- needle: &'static str,
- haystack: &'static str,
- fwd: Option<usize>,
- rev: Option<usize>,
- ) -> Seed {
- Seed { needle, haystack, fwd, rev }
- }
-
- fn generate(self) -> impl Iterator<Item = Test> {
- assert!(!self.needle.contains('#'), "needle must not contain '#'");
- assert!(!self.haystack.contains('#'), "haystack must not contain '#'");
- (0..=Seed::MAX_PAD)
- // Generate tests for padding at the beginning of haystack.
- .map(move |pad| {
- let needle = self.needle.to_string();
- let prefix = "#".repeat(pad);
- let haystack = format!("{}{}", prefix, self.haystack);
- let fwd = if needle.is_empty() {
- Some(0)
- } else {
- self.fwd.map(|i| pad + i)
- };
- let rev = if needle.is_empty() {
- Some(haystack.len())
- } else {
- self.rev.map(|i| pad + i)
- };
- Test { needle, haystack, fwd, rev }
- })
- // Generate tests for padding at the end of haystack.
- .chain((1..=Seed::MAX_PAD).map(move |pad| {
- let needle = self.needle.to_string();
- let suffix = "#".repeat(pad);
- let haystack = format!("{}{}", self.haystack, suffix);
- let fwd = if needle.is_empty() { Some(0) } else { self.fwd };
- let rev = if needle.is_empty() {
- Some(haystack.len())
- } else {
- self.rev
- };
- Test { needle, haystack, fwd, rev }
- }))
- }
-}
diff --git a/vendor/memchr/src/tests/substring/naive.rs b/vendor/memchr/src/tests/substring/naive.rs
deleted file mode 100644
index 1bc6009..0000000
--- a/vendor/memchr/src/tests/substring/naive.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-/*!
-This module defines "naive" implementations of substring search.
-
-These are sometimes useful to compare with "real" substring implementations.
-The idea is that they are so simple that they are unlikely to be incorrect.
-*/
-
-/// Naively search forwards for the given needle in the given haystack.
-pub(crate) fn find(haystack: &[u8], needle: &[u8]) -> Option<usize> {
- let end = haystack.len().checked_sub(needle.len()).map_or(0, |i| i + 1);
- for i in 0..end {
- if needle == &haystack[i..i + needle.len()] {
- return Some(i);
- }
- }
- None
-}
-
-/// Naively search in reverse for the given needle in the given haystack.
-pub(crate) fn rfind(haystack: &[u8], needle: &[u8]) -> Option<usize> {
- let end = haystack.len().checked_sub(needle.len()).map_or(0, |i| i + 1);
- for i in (0..end).rev() {
- if needle == &haystack[i..i + needle.len()] {
- return Some(i);
- }
- }
- None
-}
-
-#[cfg(test)]
-mod tests {
- use crate::tests::substring;
-
- use super::*;
-
- #[test]
- fn forward() {
- substring::Runner::new().fwd(|h, n| Some(find(h, n))).run()
- }
-
- #[test]
- fn reverse() {
- substring::Runner::new().rev(|h, n| Some(rfind(h, n))).run()
- }
-}
diff --git a/vendor/memchr/src/tests/substring/prop.rs b/vendor/memchr/src/tests/substring/prop.rs
deleted file mode 100644
index a8352ec..0000000
--- a/vendor/memchr/src/tests/substring/prop.rs
+++ /dev/null
@@ -1,126 +0,0 @@
-/*!
-This module defines a few quickcheck properties for substring search.
-
-It also provides a forward and reverse macro for conveniently defining
-quickcheck tests that run these properties over any substring search
-implementation.
-*/
-
-use crate::tests::substring::naive;
-
-/// $fwd is a `impl FnMut(haystack, needle) -> Option<Option<usize>>`. When the
-/// routine returns `None`, then it's skipped, which is useful for substring
-/// implementations that don't work for all inputs.
-#[macro_export]
-macro_rules! define_substring_forward_quickcheck {
- ($fwd:expr) => {
- #[cfg(not(miri))]
- quickcheck::quickcheck! {
- fn qc_fwd_prefix_is_substring(bs: alloc::vec::Vec<u8>) -> bool {
- crate::tests::substring::prop::prefix_is_substring(&bs, $fwd)
- }
-
- fn qc_fwd_suffix_is_substring(bs: alloc::vec::Vec<u8>) -> bool {
- crate::tests::substring::prop::suffix_is_substring(&bs, $fwd)
- }
-
- fn qc_fwd_matches_naive(
- haystack: alloc::vec::Vec<u8>,
- needle: alloc::vec::Vec<u8>
- ) -> bool {
- crate::tests::substring::prop::same_as_naive(
- false,
- &haystack,
- &needle,
- $fwd,
- )
- }
- }
- };
-}
-
-/// $rev is a `impl FnMut(haystack, needle) -> Option<Option<usize>>`. When the
-/// routine returns `None`, then it's skipped, which is useful for substring
-/// implementations that don't work for all inputs.
-#[macro_export]
-macro_rules! define_substring_reverse_quickcheck {
- ($rev:expr) => {
- #[cfg(not(miri))]
- quickcheck::quickcheck! {
- fn qc_rev_prefix_is_substring(bs: alloc::vec::Vec<u8>) -> bool {
- crate::tests::substring::prop::prefix_is_substring(&bs, $rev)
- }
-
- fn qc_rev_suffix_is_substring(bs: alloc::vec::Vec<u8>) -> bool {
- crate::tests::substring::prop::suffix_is_substring(&bs, $rev)
- }
-
- fn qc_rev_matches_naive(
- haystack: alloc::vec::Vec<u8>,
- needle: alloc::vec::Vec<u8>
- ) -> bool {
- crate::tests::substring::prop::same_as_naive(
- true,
- &haystack,
- &needle,
- $rev,
- )
- }
- }
- };
-}
-
-/// Check that every prefix of the given byte string is a substring.
-pub(crate) fn prefix_is_substring(
- bs: &[u8],
- mut search: impl FnMut(&[u8], &[u8]) -> Option<Option<usize>>,
-) -> bool {
- for i in 0..bs.len().saturating_sub(1) {
- let prefix = &bs[..i];
- let result = match search(bs, prefix) {
- None => continue,
- Some(result) => result,
- };
- if !result.is_some() {
- return false;
- }
- }
- true
-}
-
-/// Check that every suffix of the given byte string is a substring.
-pub(crate) fn suffix_is_substring(
- bs: &[u8],
- mut search: impl FnMut(&[u8], &[u8]) -> Option<Option<usize>>,
-) -> bool {
- for i in 0..bs.len().saturating_sub(1) {
- let suffix = &bs[i..];
- let result = match search(bs, suffix) {
- None => continue,
- Some(result) => result,
- };
- if !result.is_some() {
- return false;
- }
- }
- true
-}
-
-/// Check that naive substring search matches the result of the given search
-/// algorithm.
-pub(crate) fn same_as_naive(
- reverse: bool,
- haystack: &[u8],
- needle: &[u8],
- mut search: impl FnMut(&[u8], &[u8]) -> Option<Option<usize>>,
-) -> bool {
- let result = match search(haystack, needle) {
- None => return true,
- Some(result) => result,
- };
- if reverse {
- result == naive::rfind(haystack, needle)
- } else {
- result == naive::find(haystack, needle)
- }
-}
diff --git a/vendor/memchr/src/tests/x86_64-soft_float.json b/vendor/memchr/src/tests/x86_64-soft_float.json
deleted file mode 100644
index b77649e..0000000
--- a/vendor/memchr/src/tests/x86_64-soft_float.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "llvm-target": "x86_64-unknown-none",
- "target-endian": "little",
- "target-pointer-width": "64",
- "target-c-int-width": "32",
- "os": "none",
- "arch": "x86_64",
- "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
- "linker-flavor": "ld.lld",
- "linker": "rust-lld",
- "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
- "executables": true,
- "disable-redzone": true,
- "panic-strategy": "abort"
-}
diff --git a/vendor/memchr/src/vector.rs b/vendor/memchr/src/vector.rs
deleted file mode 100644
index f360176..0000000
--- a/vendor/memchr/src/vector.rs
+++ /dev/null
@@ -1,515 +0,0 @@
-/// A trait for describing vector operations used by vectorized searchers.
-///
-/// The trait is highly constrained to low level vector operations needed.
-/// In general, it was invented mostly to be generic over x86's __m128i and
-/// __m256i types. At time of writing, it also supports wasm and aarch64
-/// 128-bit vector types as well.
-///
-/// # Safety
-///
-/// All methods are not safe since they are intended to be implemented using
-/// vendor intrinsics, which are also not safe. Callers must ensure that the
-/// appropriate target features are enabled in the calling function, and that
-/// the current CPU supports them. All implementations should avoid marking the
-/// routines with #[target_feature] and instead mark them as #[inline(always)]
-/// to ensure they get appropriately inlined. (inline(always) cannot be used
-/// with target_feature.)
-pub(crate) trait Vector: Copy + core::fmt::Debug {
- /// The number of bits in the vector.
- const BITS: usize;
- /// The number of bytes in the vector. That is, this is the size of the
- /// vector in memory.
- const BYTES: usize;
- /// The bits that must be zero in order for a `*const u8` pointer to be
- /// correctly aligned to read vector values.
- const ALIGN: usize;
-
- /// The type of the value returned by `Vector::movemask`.
- ///
- /// This supports abstracting over the specific representation used in
- /// order to accommodate different representations in different ISAs.
- type Mask: MoveMask;
-
- /// Create a vector with 8-bit lanes with the given byte repeated into each
- /// lane.
- unsafe fn splat(byte: u8) -> Self;
-
- /// Read a vector-size number of bytes from the given pointer. The pointer
- /// must be aligned to the size of the vector.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that at least `BYTES` bytes are readable from
- /// `data` and that `data` is aligned to a `BYTES` boundary.
- unsafe fn load_aligned(data: *const u8) -> Self;
-
- /// Read a vector-size number of bytes from the given pointer. The pointer
- /// does not need to be aligned.
- ///
- /// # Safety
- ///
- /// Callers must guarantee that at least `BYTES` bytes are readable from
- /// `data`.
- unsafe fn load_unaligned(data: *const u8) -> Self;
-
- /// _mm_movemask_epi8 or _mm256_movemask_epi8
- unsafe fn movemask(self) -> Self::Mask;
- /// _mm_cmpeq_epi8 or _mm256_cmpeq_epi8
- unsafe fn cmpeq(self, vector2: Self) -> Self;
- /// _mm_and_si128 or _mm256_and_si256
- unsafe fn and(self, vector2: Self) -> Self;
- /// _mm_or or _mm256_or_si256
- unsafe fn or(self, vector2: Self) -> Self;
- /// Returns true if and only if `Self::movemask` would return a mask that
- /// contains at least one non-zero bit.
- unsafe fn movemask_will_have_non_zero(self) -> bool {
- self.movemask().has_non_zero()
- }
-}
-
-/// A trait that abstracts over a vector-to-scalar operation called
-/// "move mask."
-///
-/// On x86-64, this is `_mm_movemask_epi8` for SSE2 and `_mm256_movemask_epi8`
-/// for AVX2. It takes a vector of `u8` lanes and returns a scalar where the
-/// `i`th bit is set if and only if the most significant bit in the `i`th lane
-/// of the vector is set. The simd128 ISA for wasm32 also supports this
-/// exact same operation natively.
-///
-/// ... But aarch64 doesn't. So we have to fake it with more instructions and
-/// a slightly different representation. We could do extra work to unify the
-/// representations, but then would require additional costs in the hot path
-/// for `memchr` and `packedpair`. So instead, we abstraction over the specific
-/// representation with this trait an ddefine the operations we actually need.
-pub(crate) trait MoveMask: Copy + core::fmt::Debug {
- /// Return a mask that is all zeros except for the least significant `n`
- /// lanes in a corresponding vector.
- fn all_zeros_except_least_significant(n: usize) -> Self;
-
- /// Returns true if and only if this mask has a a non-zero bit anywhere.
- fn has_non_zero(self) -> bool;
-
- /// Returns the number of bits set to 1 in this mask.
- fn count_ones(self) -> usize;
-
- /// Does a bitwise `and` operation between `self` and `other`.
- fn and(self, other: Self) -> Self;
-
- /// Does a bitwise `or` operation between `self` and `other`.
- fn or(self, other: Self) -> Self;
-
- /// Returns a mask that is equivalent to `self` but with the least
- /// significant 1-bit set to 0.
- fn clear_least_significant_bit(self) -> Self;
-
- /// Returns the offset of the first non-zero lane this mask represents.
- fn first_offset(self) -> usize;
-
- /// Returns the offset of the last non-zero lane this mask represents.
- fn last_offset(self) -> usize;
-}
-
-/// This is a "sensible" movemask implementation where each bit represents
-/// whether the most significant bit is set in each corresponding lane of a
-/// vector. This is used on x86-64 and wasm, but such a mask is more expensive
-/// to get on aarch64 so we use something a little different.
-///
-/// We call this "sensible" because this is what we get using native sse/avx
-/// movemask instructions. But neon has no such native equivalent.
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct SensibleMoveMask(u32);
-
-impl SensibleMoveMask {
- /// Get the mask in a form suitable for computing offsets.
- ///
- /// Basically, this normalizes to little endian. On big endian, this swaps
- /// the bytes.
- #[inline(always)]
- fn get_for_offset(self) -> u32 {
- #[cfg(target_endian = "big")]
- {
- self.0.swap_bytes()
- }
- #[cfg(target_endian = "little")]
- {
- self.0
- }
- }
-}
-
-impl MoveMask for SensibleMoveMask {
- #[inline(always)]
- fn all_zeros_except_least_significant(n: usize) -> SensibleMoveMask {
- debug_assert!(n < 32);
- SensibleMoveMask(!((1 << n) - 1))
- }
-
- #[inline(always)]
- fn has_non_zero(self) -> bool {
- self.0 != 0
- }
-
- #[inline(always)]
- fn count_ones(self) -> usize {
- self.0.count_ones() as usize
- }
-
- #[inline(always)]
- fn and(self, other: SensibleMoveMask) -> SensibleMoveMask {
- SensibleMoveMask(self.0 & other.0)
- }
-
- #[inline(always)]
- fn or(self, other: SensibleMoveMask) -> SensibleMoveMask {
- SensibleMoveMask(self.0 | other.0)
- }
-
- #[inline(always)]
- fn clear_least_significant_bit(self) -> SensibleMoveMask {
- SensibleMoveMask(self.0 & (self.0 - 1))
- }
-
- #[inline(always)]
- fn first_offset(self) -> usize {
- // We are dealing with little endian here (and if we aren't, we swap
- // the bytes so we are in practice), where the most significant byte
- // is at a higher address. That means the least significant bit that
- // is set corresponds to the position of our first matching byte.
- // That position corresponds to the number of zeros after the least
- // significant bit.
- self.get_for_offset().trailing_zeros() as usize
- }
-
- #[inline(always)]
- fn last_offset(self) -> usize {
- // We are dealing with little endian here (and if we aren't, we swap
- // the bytes so we are in practice), where the most significant byte is
- // at a higher address. That means the most significant bit that is set
- // corresponds to the position of our last matching byte. The position
- // from the end of the mask is therefore the number of leading zeros
- // in a 32 bit integer, and the position from the start of the mask is
- // therefore 32 - (leading zeros) - 1.
- 32 - self.get_for_offset().leading_zeros() as usize - 1
- }
-}
-
-#[cfg(target_arch = "x86_64")]
-mod x86sse2 {
- use core::arch::x86_64::*;
-
- use super::{SensibleMoveMask, Vector};
-
- impl Vector for __m128i {
- const BITS: usize = 128;
- const BYTES: usize = 16;
- const ALIGN: usize = Self::BYTES - 1;
-
- type Mask = SensibleMoveMask;
-
- #[inline(always)]
- unsafe fn splat(byte: u8) -> __m128i {
- _mm_set1_epi8(byte as i8)
- }
-
- #[inline(always)]
- unsafe fn load_aligned(data: *const u8) -> __m128i {
- _mm_load_si128(data as *const __m128i)
- }
-
- #[inline(always)]
- unsafe fn load_unaligned(data: *const u8) -> __m128i {
- _mm_loadu_si128(data as *const __m128i)
- }
-
- #[inline(always)]
- unsafe fn movemask(self) -> SensibleMoveMask {
- SensibleMoveMask(_mm_movemask_epi8(self) as u32)
- }
-
- #[inline(always)]
- unsafe fn cmpeq(self, vector2: Self) -> __m128i {
- _mm_cmpeq_epi8(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn and(self, vector2: Self) -> __m128i {
- _mm_and_si128(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn or(self, vector2: Self) -> __m128i {
- _mm_or_si128(self, vector2)
- }
- }
-}
-
-#[cfg(target_arch = "x86_64")]
-mod x86avx2 {
- use core::arch::x86_64::*;
-
- use super::{SensibleMoveMask, Vector};
-
- impl Vector for __m256i {
- const BITS: usize = 256;
- const BYTES: usize = 32;
- const ALIGN: usize = Self::BYTES - 1;
-
- type Mask = SensibleMoveMask;
-
- #[inline(always)]
- unsafe fn splat(byte: u8) -> __m256i {
- _mm256_set1_epi8(byte as i8)
- }
-
- #[inline(always)]
- unsafe fn load_aligned(data: *const u8) -> __m256i {
- _mm256_load_si256(data as *const __m256i)
- }
-
- #[inline(always)]
- unsafe fn load_unaligned(data: *const u8) -> __m256i {
- _mm256_loadu_si256(data as *const __m256i)
- }
-
- #[inline(always)]
- unsafe fn movemask(self) -> SensibleMoveMask {
- SensibleMoveMask(_mm256_movemask_epi8(self) as u32)
- }
-
- #[inline(always)]
- unsafe fn cmpeq(self, vector2: Self) -> __m256i {
- _mm256_cmpeq_epi8(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn and(self, vector2: Self) -> __m256i {
- _mm256_and_si256(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn or(self, vector2: Self) -> __m256i {
- _mm256_or_si256(self, vector2)
- }
- }
-}
-
-#[cfg(target_arch = "aarch64")]
-mod aarch64neon {
- use core::arch::aarch64::*;
-
- use super::{MoveMask, Vector};
-
- impl Vector for uint8x16_t {
- const BITS: usize = 128;
- const BYTES: usize = 16;
- const ALIGN: usize = Self::BYTES - 1;
-
- type Mask = NeonMoveMask;
-
- #[inline(always)]
- unsafe fn splat(byte: u8) -> uint8x16_t {
- vdupq_n_u8(byte)
- }
-
- #[inline(always)]
- unsafe fn load_aligned(data: *const u8) -> uint8x16_t {
- // I've tried `data.cast::<uint8x16_t>().read()` instead, but
- // couldn't observe any benchmark differences.
- Self::load_unaligned(data)
- }
-
- #[inline(always)]
- unsafe fn load_unaligned(data: *const u8) -> uint8x16_t {
- vld1q_u8(data)
- }
-
- #[inline(always)]
- unsafe fn movemask(self) -> NeonMoveMask {
- let asu16s = vreinterpretq_u16_u8(self);
- let mask = vshrn_n_u16(asu16s, 4);
- let asu64 = vreinterpret_u64_u8(mask);
- let scalar64 = vget_lane_u64(asu64, 0);
- NeonMoveMask(scalar64 & 0x8888888888888888)
- }
-
- #[inline(always)]
- unsafe fn cmpeq(self, vector2: Self) -> uint8x16_t {
- vceqq_u8(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn and(self, vector2: Self) -> uint8x16_t {
- vandq_u8(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn or(self, vector2: Self) -> uint8x16_t {
- vorrq_u8(self, vector2)
- }
-
- /// This is the only interesting implementation of this routine.
- /// Basically, instead of doing the "shift right narrow" dance, we use
- /// adajacent folding max to determine whether there are any non-zero
- /// bytes in our mask. If there are, *then* we'll do the "shift right
- /// narrow" dance. In benchmarks, this does lead to slightly better
- /// throughput, but the win doesn't appear huge.
- #[inline(always)]
- unsafe fn movemask_will_have_non_zero(self) -> bool {
- let low = vreinterpretq_u64_u8(vpmaxq_u8(self, self));
- vgetq_lane_u64(low, 0) != 0
- }
- }
-
- /// Neon doesn't have a `movemask` that works like the one in x86-64, so we
- /// wind up using a different method[1]. The different method also produces
- /// a mask, but 4 bits are set in the neon case instead of a single bit set
- /// in the x86-64 case. We do an extra step to zero out 3 of the 4 bits,
- /// but we still wind up with at least 3 zeroes between each set bit. This
- /// generally means that we need to do some division by 4 before extracting
- /// offsets.
- ///
- /// In fact, the existence of this type is the entire reason that we have
- /// the `MoveMask` trait in the first place. This basically lets us keep
- /// the different representations of masks without being forced to unify
- /// them into a single representation, which could result in extra and
- /// unnecessary work.
- ///
- /// [1]: https://community.arm.com/arm-community-blogs/b/infrastructure-solutions-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon
- #[derive(Clone, Copy, Debug)]
- pub(crate) struct NeonMoveMask(u64);
-
- impl NeonMoveMask {
- /// Get the mask in a form suitable for computing offsets.
- ///
- /// Basically, this normalizes to little endian. On big endian, this
- /// swaps the bytes.
- #[inline(always)]
- fn get_for_offset(self) -> u64 {
- #[cfg(target_endian = "big")]
- {
- self.0.swap_bytes()
- }
- #[cfg(target_endian = "little")]
- {
- self.0
- }
- }
- }
-
- impl MoveMask for NeonMoveMask {
- #[inline(always)]
- fn all_zeros_except_least_significant(n: usize) -> NeonMoveMask {
- debug_assert!(n < 16);
- NeonMoveMask(!(((1 << n) << 2) - 1))
- }
-
- #[inline(always)]
- fn has_non_zero(self) -> bool {
- self.0 != 0
- }
-
- #[inline(always)]
- fn count_ones(self) -> usize {
- self.0.count_ones() as usize
- }
-
- #[inline(always)]
- fn and(self, other: NeonMoveMask) -> NeonMoveMask {
- NeonMoveMask(self.0 & other.0)
- }
-
- #[inline(always)]
- fn or(self, other: NeonMoveMask) -> NeonMoveMask {
- NeonMoveMask(self.0 | other.0)
- }
-
- #[inline(always)]
- fn clear_least_significant_bit(self) -> NeonMoveMask {
- NeonMoveMask(self.0 & (self.0 - 1))
- }
-
- #[inline(always)]
- fn first_offset(self) -> usize {
- // We are dealing with little endian here (and if we aren't,
- // we swap the bytes so we are in practice), where the most
- // significant byte is at a higher address. That means the least
- // significant bit that is set corresponds to the position of our
- // first matching byte. That position corresponds to the number of
- // zeros after the least significant bit.
- //
- // Note that unlike `SensibleMoveMask`, this mask has its bits
- // spread out over 64 bits instead of 16 bits (for a 128 bit
- // vector). Namely, where as x86-64 will turn
- //
- // 0x00 0xFF 0x00 0x00 0xFF
- //
- // into 10010, our neon approach will turn it into
- //
- // 10000000000010000000
- //
- // And this happens because neon doesn't have a native `movemask`
- // instruction, so we kind of fake it[1]. Thus, we divide the
- // number of trailing zeros by 4 to get the "real" offset.
- //
- // [1]: https://community.arm.com/arm-community-blogs/b/infrastructure-solutions-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon
- (self.get_for_offset().trailing_zeros() >> 2) as usize
- }
-
- #[inline(always)]
- fn last_offset(self) -> usize {
- // See comment in `first_offset` above. This is basically the same,
- // but coming from the other direction.
- 16 - (self.get_for_offset().leading_zeros() >> 2) as usize - 1
- }
- }
-}
-
-#[cfg(target_arch = "wasm32")]
-mod wasm_simd128 {
- use core::arch::wasm32::*;
-
- use super::{SensibleMoveMask, Vector};
-
- impl Vector for v128 {
- const BITS: usize = 128;
- const BYTES: usize = 16;
- const ALIGN: usize = Self::BYTES - 1;
-
- type Mask = SensibleMoveMask;
-
- #[inline(always)]
- unsafe fn splat(byte: u8) -> v128 {
- u8x16_splat(byte)
- }
-
- #[inline(always)]
- unsafe fn load_aligned(data: *const u8) -> v128 {
- *data.cast()
- }
-
- #[inline(always)]
- unsafe fn load_unaligned(data: *const u8) -> v128 {
- v128_load(data.cast())
- }
-
- #[inline(always)]
- unsafe fn movemask(self) -> SensibleMoveMask {
- SensibleMoveMask(u8x16_bitmask(self).into())
- }
-
- #[inline(always)]
- unsafe fn cmpeq(self, vector2: Self) -> v128 {
- u8x16_eq(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn and(self, vector2: Self) -> v128 {
- v128_and(self, vector2)
- }
-
- #[inline(always)]
- unsafe fn or(self, vector2: Self) -> v128 {
- v128_or(self, vector2)
- }
- }
-}