pub mod memchr;
pub mod packedpair;
pub mod rabinkarp;
#[cfg(feature = "alloc")]
pub mod shiftor;
pub mod twoway;
#[inline(always)]
pub fn is_prefix(haystack: &[u8], needle: &[u8]) -> bool {
needle.len() <= haystack.len()
&& is_equal(&haystack[..needle.len()], needle)
}
#[inline(always)]
pub fn is_suffix(haystack: &[u8], needle: &[u8]) -> bool {
needle.len() <= haystack.len()
&& is_equal(&haystack[haystack.len() - needle.len()..], needle)
}
#[inline(always)]
pub fn is_equal(x: &[u8], y: &[u8]) -> bool {
if x.len() != y.len() {
return false;
}
unsafe { is_equal_raw(x.as_ptr(), y.as_ptr(), x.len()) }
}
#[inline(always)]
pub unsafe fn is_equal_raw(
mut x: *const u8,
mut y: *const u8,
mut n: usize,
) -> bool {
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 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"));
}
}