pub const MAX_HAYSTACK_LEN: usize = 64 * 1024 * 1024;
pub const MAX_NEEDLE_LEN: usize = 4 * 1024;
pub const MAX_PATTERN_COUNT: usize = 4096;
pub const NOT_FOUND: u32 = u32::MAX;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Match {
pub pattern_id: u32,
pub start: u32,
pub end: u32,
}
pub type MatchError = String;
pub fn validate_search_inputs(haystack: &[u8], needle: &[u8]) -> Result<(), MatchError> {
validate_haystack(haystack)?;
validate_needle(needle)
}
pub fn validate_haystack(haystack: &[u8]) -> Result<(), MatchError> {
if haystack.len() > MAX_HAYSTACK_LEN {
return Err(format!(
"Fix: reduce haystack/input length to <= {MAX_HAYSTACK_LEN} bytes, got {}",
haystack.len()
));
}
Ok(())
}
pub fn validate_needle(needle: &[u8]) -> Result<(), MatchError> {
if needle.len() > MAX_NEEDLE_LEN {
return Err(format!(
"Fix: reduce needle/pattern length to <= {MAX_NEEDLE_LEN} bytes, got {}",
needle.len()
));
}
Ok(())
}
pub fn validate_patterns(patterns: &[&[u8]]) -> Result<(), MatchError> {
if patterns.len() > MAX_PATTERN_COUNT {
return Err(format!(
"Fix: reduce pattern count to <= {MAX_PATTERN_COUNT}, got {}",
patterns.len()
));
}
for (index, pattern) in patterns.iter().enumerate() {
if pattern.len() > MAX_NEEDLE_LEN {
return Err(format!(
"Fix: reduce pattern {index} length to <= {MAX_NEEDLE_LEN} bytes, got {}",
pattern.len()
));
}
}
Ok(())
}
pub fn to_u32_offset(offset: usize) -> Result<u32, MatchError> {
u32::try_from(offset)
.map_err(|_| format!("Fix: reduce input length so offset {offset} fits in U32"))
}