#[derive(Clone, Copy, Debug, Default)]
pub(crate) struct RareNeedleBytes {
rare1i: u8,
rare2i: u8,
}
impl RareNeedleBytes {
#[cfg(all(test, feature = "std"))]
pub(crate) fn new(rare1i: u8, rare2i: u8) -> RareNeedleBytes {
RareNeedleBytes { rare1i, rare2i }
}
pub(crate) fn forward(needle: &[u8]) -> RareNeedleBytes {
if needle.len() <= 1 || needle.len() > core::u8::MAX as usize {
return RareNeedleBytes { rare1i: 0, rare2i: 0 };
}
let (mut rare1, mut rare1i) = (needle[0], 0);
let (mut rare2, mut rare2i) = (needle[1], 1);
if rank(rare2) < rank(rare1) {
core::mem::swap(&mut rare1, &mut rare2);
core::mem::swap(&mut rare1i, &mut rare2i);
}
for (i, &b) in needle.iter().enumerate().skip(2) {
if rank(b) < rank(rare1) {
rare2 = rare1;
rare2i = rare1i;
rare1 = b;
rare1i = i as u8;
} else if b != rare1 && rank(b) < rank(rare2) {
rare2 = b;
rare2i = i as u8;
}
}
assert_ne!(rare1i, rare2i);
RareNeedleBytes { rare1i, rare2i }
}
pub(crate) fn as_rare_bytes(&self, needle: &[u8]) -> (u8, u8) {
(needle[self.rare1i as usize], needle[self.rare2i as usize])
}
#[cfg(memchr_runtime_simd)]
pub(crate) fn as_rare_ordered_usize(&self) -> (usize, usize) {
let (rare1i, rare2i) = self.as_rare_ordered_u8();
(rare1i as usize, rare2i as usize)
}
#[cfg(memchr_runtime_simd)]
pub(crate) fn as_rare_ordered_u8(&self) -> (u8, u8) {
if self.rare1i <= self.rare2i {
(self.rare1i, self.rare2i)
} else {
(self.rare2i, self.rare1i)
}
}
pub(crate) fn as_rare_usize(&self) -> (usize, usize) {
(self.rare1i as usize, self.rare2i as usize)
}
pub(crate) fn as_ranks(&self, needle: &[u8]) -> (usize, usize) {
let (b1, b2) = self.as_rare_bytes(needle);
(rank(b1), rank(b2))
}
}
fn rank(b: u8) -> usize {
crate::memmem::byte_frequencies::BYTE_FREQUENCIES[b as usize] as usize
}