use super::prefix_table;
use crate::ops::string_matching::search_contract::{
to_u32_offset, validate_search_inputs, MatchError, NOT_FOUND,
};
pub fn kmp_find(haystack: &[u8], needle: &[u8]) -> Result<u32, MatchError> {
validate_search_inputs(haystack, needle)?;
if needle.is_empty() {
return Ok(0);
}
if needle.len() > haystack.len() {
return Ok(NOT_FOUND);
}
let table = prefix_table(needle);
let mut matched = 0usize;
for (index, &byte) in haystack.iter().enumerate() {
while matched > 0 && byte != needle[matched] {
matched = table[matched - 1];
}
if byte == needle[matched] {
matched += 1;
if matched == needle.len() {
return to_u32_offset(index + 1 - needle.len());
}
}
}
Ok(NOT_FOUND)
}