use regex::Regex as RegexImpl;
use regex::RegexBuilder;
pub use regex::Regex;
pub fn new(pattern: &str) -> Result<Regex, String> {
RegexImpl::new(pattern).map_err(|e| e.to_string())
}
pub fn compile(pattern: &str) -> Result<Regex, String> {
RegexImpl::new(pattern).map_err(|e| e.to_string())
}
pub fn compile_with_flags(pattern: &str, flags: &str) -> Result<Regex, String> {
let mut builder = RegexBuilder::new(pattern);
for flag in flags.chars() {
match flag {
'i' => {
builder.case_insensitive(true);
}
'm' => {
builder.multi_line(true);
}
's' => {
builder.dot_matches_new_line(true);
}
_ => return Err(format!("Unknown regex flag: {}", flag)),
}
}
builder.build().map_err(|e| e.to_string())
}
pub fn escape(text: &str) -> String {
regex::escape(text)
}
pub fn is_match(pattern: &str, text: &str) -> Result<bool, String> {
let re = Regex::new(pattern).map_err(|e| e.to_string())?;
Ok(re.is_match(text))
}
pub fn is_match_compiled(re: &Regex, text: &str) -> bool {
re.is_match(text)
}
pub fn find(pattern: &str, text: &str) -> Result<Option<String>, String> {
let re = Regex::new(pattern).map_err(|e| e.to_string())?;
Ok(re.find(text).map(|m| m.as_str().to_string()))
}
pub fn find_compiled(re: &Regex, text: &str) -> Option<String> {
re.find(text).map(|m| m.as_str().to_string())
}
pub fn find_all(pattern: &str, text: &str) -> Result<Vec<String>, String> {
let re = Regex::new(pattern).map_err(|e| e.to_string())?;
Ok(re.find_iter(text).map(|m| m.as_str().to_string()).collect())
}
pub fn find_all_compiled(re: &Regex, text: &str) -> Vec<String> {
re.find_iter(text).map(|m| m.as_str().to_string()).collect()
}
pub fn replace(pattern: &str, text: &str, replacement: &str) -> Result<String, String> {
let re = Regex::new(pattern).map_err(|e| e.to_string())?;
Ok(re.replace(text, replacement).to_string())
}
pub fn replace_compiled(re: &Regex, text: &str, replacement: &str) -> String {
re.replace(text, replacement).to_string()
}
pub fn replace_all(pattern: &str, text: &str, replacement: &str) -> Result<String, String> {
let re = Regex::new(pattern).map_err(|e| e.to_string())?;
Ok(re.replace_all(text, replacement).to_string())
}
pub fn replace_all_compiled(re: &Regex, text: &str, replacement: &str) -> String {
re.replace_all(text, replacement).to_string()
}
pub fn split(pattern: &str, text: &str) -> Result<Vec<String>, String> {
let re = Regex::new(pattern).map_err(|e| e.to_string())?;
Ok(re.split(text).map(|s| s.to_string()).collect())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_match() {
assert!(is_match(r"\d+", "123").unwrap());
assert!(!is_match(r"\d+", "abc").unwrap());
}
#[test]
fn test_find() {
assert_eq!(find(r"\d+", "abc123def").unwrap(), Some("123".to_string()));
assert_eq!(find(r"\d+", "abc").unwrap(), None);
}
#[test]
fn test_find_all() {
let matches = find_all(r"\d+", "a1b2c3").unwrap();
assert_eq!(matches, vec!["1", "2", "3"]);
}
#[test]
fn test_replace() {
assert_eq!(replace(r"\d+", "abc123def", "X").unwrap(), "abcXdef");
}
#[test]
fn test_replace_all() {
assert_eq!(replace_all(r"\d+", "a1b2c3", "X").unwrap(), "aXbXcX");
}
#[test]
fn test_split() {
let parts = split(r"\s+", "hello world\t\tfoo").unwrap();
assert_eq!(parts, vec!["hello", "world", "foo"]);
}
}