pub(super) const RANK: [u8; 256] = [
55, 52, 51, 50, 49, 48, 47, 46, 45, 103, 242, 66, 67, 229, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 56, 32, 31, 30, 29, 28, 255, 148, 164, 149, 136, 160, 155, 173, 221, 222, 134, 122, 232, 202, 215, 224, 208, 220, 204, 187, 183, 179, 177, 168, 178, 200, 226, 195, 154, 184, 174, 126, 120, 191, 157, 194, 170, 189, 162, 161, 150, 193, 142, 137, 171, 176, 185, 167, 186, 112, 175, 192, 188, 156, 140, 143, 123, 133, 128, 147, 138, 146, 114, 223, 151, 249, 216, 238, 236, 253, 227, 218, 230, 247, 135, 180, 241, 233, 246, 244, 231, 139, 245, 243, 251, 235, 201, 196, 240, 214, 152, 182, 205, 181, 127, 27, 212, 211, 210, 213, 228, 197, 169, 159, 131, 172, 105, 80, 98, 96, 97, 81, 207, 145, 116, 115, 144, 130, 153, 121, 107, 132, 109, 110, 124, 111, 82, 108, 118, 141, 113, 129, 119, 125, 165, 117, 92, 106, 83, 72, 99, 93, 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, ];
pub(super) fn rare_byte_offsets(needle: &[u8]) -> (usize, usize) {
debug_assert!(
needle.len() >= 2,
"rare_byte_offsets requires at least two bytes"
);
let rank = |byte: u8| RANK[byte as usize];
let (mut rare1, mut offset1) = (needle[0], 0usize);
let (mut rare2, mut offset2) = (needle[1], 1usize);
if rank(rare2) < rank(rare1) {
std::mem::swap(&mut rare1, &mut rare2);
std::mem::swap(&mut offset1, &mut offset2);
}
for (offset, &byte) in needle.iter().enumerate().skip(2) {
if rank(byte) < rank(rare1) {
rare2 = rare1;
offset2 = offset1;
rare1 = byte;
offset1 = offset;
} else if byte != rare1 && rank(byte) < rank(rare2) {
rare2 = byte;
offset2 = offset;
}
}
if offset1 <= offset2 {
(offset1, offset2)
} else {
(offset2, offset1)
}
}
#[cfg(test)]
mod tests {
use super::{RANK, rare_byte_offsets};
#[test]
fn returns_two_distinct_ordered_offsets() {
let (a, b) = rare_byte_offsets(b"abcd");
assert!(
a < b && b < 4,
"expected ordered distinct offsets, got ({a}, {b})"
);
}
#[test]
fn prefers_rarer_bytes_over_position() {
assert!(RANK[b'z' as usize] < RANK[b'a' as usize]);
let (a, b) = rare_byte_offsets(b"aazaa");
assert!(
a == 2 || b == 2,
"expected the 'z' at offset 2 to be a seed, got ({a}, {b})"
);
}
#[test]
fn all_identical_bytes_fall_back_to_adjacent_offsets() {
assert_eq!(rare_byte_offsets(b"aaaa"), (0, 1));
}
}