use regex::Regex;
#[derive(Debug, Clone, Default)]
pub struct RegexMatch {
pub matched: bool,
pub full: String,
pub captures: Vec<String>,
}
pub fn match_regex(text: &str, pat: &str, case_insensitive: bool) -> RegexMatch {
let actual_pat = if case_insensitive {
format!("(?i){}", pat)
} else {
pat.to_string()
};
let re = match Regex::new(&actual_pat) {
Ok(r) => r,
Err(_) => return RegexMatch::default(),
};
let Some(caps) = re.captures(text) else {
return RegexMatch::default();
};
let full = caps
.get(0)
.map(|m| m.as_str().to_string())
.unwrap_or_default();
let captures: Vec<String> = caps
.iter()
.skip(1)
.map(|m| m.map(|m| m.as_str().to_string()).unwrap_or_default())
.collect();
RegexMatch {
matched: true,
full,
captures,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matches_simple_pattern() {
let r = match_regex("hello world", "wor.d", false);
assert!(r.matched);
assert_eq!(r.full, "world");
}
#[test]
fn captures_subgroups() {
let r = match_regex("foo=42", "([a-z]+)=([0-9]+)", false);
assert!(r.matched);
assert_eq!(r.captures, vec!["foo".to_string(), "42".to_string()]);
}
#[test]
fn case_insensitive_flag() {
let r = match_regex("HELLO", "hello", true);
assert!(r.matched);
}
#[test]
fn returns_unmatched_for_invalid_pattern() {
let r = match_regex("anything", "[", false);
assert!(!r.matched);
}
}