use crate::errors::{Result, RunjucksError};
use regex::RegexBuilder;
pub fn unescape_js_regex_pattern(s: &str) -> String {
let mut out = String::with_capacity(s.len());
let mut chars = s.chars().peekable();
while let Some(c) = chars.next() {
if c == '\\' {
match chars.next() {
Some('/') => out.push('/'),
Some('\\') => out.push('\\'),
Some('n') => out.push('\n'),
Some('r') => out.push('\r'),
Some('t') => out.push('\t'),
Some(x) => {
out.push('\\');
out.push(x);
}
None => out.push('\\'),
}
} else {
out.push(c);
}
}
out
}
pub fn compile_js_regex(pattern: &str, flags: &str) -> Result<regex::Regex> {
let p = unescape_js_regex_pattern(pattern);
let mut b = RegexBuilder::new(&p);
if flags.contains('i') {
b.case_insensitive(true);
}
if flags.contains('m') {
b.multi_line(true);
}
b.build()
.map_err(|e| RunjucksError::new(format!("invalid regex: {e}")))
}
pub fn regexp_test(pattern: &str, flags: &str, haystack: &str) -> Result<bool> {
let re = compile_js_regex(pattern, flags)?;
Ok(re.is_match(haystack))
}