use memchr::memmem::Finder;
use super::{fields, find, find_lit};
fn words(alphabet: &[u8], max: u32) -> Vec<Vec<u8>> {
(0..=max)
.flat_map(|len| {
(0..alphabet.len().pow(len)).map(move |code| {
(0..len)
.map(|i| alphabet[code / alphabet.len().pow(i) % alphabet.len()])
.collect()
})
})
.collect()
}
#[test]
fn find_is_the_first_window_equal_to_the_needle() {
let first_window = |h: &[u8], n: &[u8]| match n.is_empty() {
true => Some(0),
false => h.windows(n.len()).position(|w| w == n),
};
let short = words(b"ab", 10);
let long: Vec<Vec<u8>> = words(b"ab", 5)
.iter()
.filter(|h| !h.is_empty())
.flat_map(|h| {
let base: Vec<u8> = h.iter().copied().cycle().take(37).collect();
[[base.as_slice(), b"abbba"].concat(), base]
})
.collect();
let needles: Vec<Vec<u8>> = words(b"ab", 3)
.into_iter()
.chain([b"abbba".to_vec(), b"ababab".to_vec()])
.collect();
for n in &needles {
let finder = Finder::new(n).into_owned();
for h in short.iter().chain(&long) {
let want = first_window(h, n);
assert_eq!(find(h, n), want, "find {:?} in {:?}", n, h);
assert_eq!(find_lit(h, &finder), want, "find_lit {:?} in {:?}", n, h);
}
}
}
#[test]
fn fields_are_the_split_on_the_delimiter() {
for s in words(b"ab,", 7) {
let s = String::from_utf8(s).unwrap();
for d in [",", "a", "ab", ",,", "ba,"] {
let got: Vec<&str> = fields(s.as_bytes(), d.as_bytes()).map(|(a, b)| &s[a..b]).collect();
assert_eq!(got, s.split(d).collect::<Vec<_>>(), "{s:?} on {d:?}");
}
}
}