pub(crate) fn regex_prefix_anchorable(src: &str) -> bool {
use regex_syntax::hir::literal::{ExtractKind, Extractor};
let Ok(hir) = regex_syntax::ParserBuilder::new().build().parse(src) else {
return false;
};
let mut ex = Extractor::new();
ex.kind(ExtractKind::Prefix);
let seq = ex.extract(&hir);
matches!(
(seq.is_finite(), seq.len(), seq.min_literal_len()),
(true, Some(n), Some(min)) if n > 0 && min >= 3
)
}
pub(crate) fn truncate_for_prefilter(src: &str) -> Option<String> {
use regex_syntax::ast::{Ast, RepetitionKind, RepetitionRange};
let ast = match regex_syntax::ast::parse::Parser::new().parse(src) {
Ok(ast) => ast,
Err(error) => {
tracing::warn!(
pattern = %src,
%error,
"prefilter regex truncation parse failed; using full pattern (perf-only impact)"
);
return None;
}
};
let single;
let nodes: &[Ast] = match &ast {
Ast::Concat(c) => &c.asts,
Ast::Repetition(_) => {
single = [ast.clone()];
&single
}
_ => return None,
};
for node in nodes {
let Ast::Repetition(rep) = node else { continue };
let b_start = rep.span.start.offset; let op_start = rep.op.span.start.offset; let truncated = match &rep.op.kind {
RepetitionKind::ZeroOrMore => src.get(..b_start)?.to_string(),
RepetitionKind::OneOrMore => src.get(..op_start)?.to_string(),
RepetitionKind::Range(RepetitionRange::AtLeast(n)) => {
format!("{}{{{}}}", src.get(..op_start)?, n)
}
_ => continue,
};
match regex::Regex::new(&truncated) {
Ok(_) => return Some(truncated),
Err(error) => {
tracing::warn!(
pattern = %src,
truncated = %truncated,
%error,
"prefilter regex truncation compile failed; using full pattern (perf-only impact)"
);
return None;
}
}
}
None
}
pub(crate) fn focus_floor_boundary(s: &str, idx: usize) -> usize {
crate::engine::floor_char_boundary(s, idx)
}
pub(crate) fn focus_ceil_boundary(s: &str, idx: usize) -> usize {
crate::engine::ceil_char_boundary(s, idx)
}
pub(crate) fn truncate_src(s: &str, n: usize) -> String {
if s.len() <= n {
return s.to_string();
}
let i = crate::engine::floor_char_boundary(s, n.min(s.len()));
format!("{}…", &s[..i])
}