windjammer_runtime/
regex_mod.rs1use regex::Regex as RegexImpl;
6use regex::RegexBuilder;
7
8pub use regex::Regex;
10
11pub fn new(pattern: &str) -> Result<Regex, String> {
13 RegexImpl::new(pattern).map_err(|e| e.to_string())
14}
15
16pub fn compile(pattern: &str) -> Result<Regex, String> {
18 RegexImpl::new(pattern).map_err(|e| e.to_string())
19}
20
21pub fn compile_with_flags(pattern: &str, flags: &str) -> Result<Regex, String> {
24 let mut builder = RegexBuilder::new(pattern);
25
26 for flag in flags.chars() {
27 match flag {
28 'i' => {
29 builder.case_insensitive(true);
30 }
31 'm' => {
32 builder.multi_line(true);
33 }
34 's' => {
35 builder.dot_matches_new_line(true);
36 }
37 _ => return Err(format!("Unknown regex flag: {}", flag)),
38 }
39 }
40
41 builder.build().map_err(|e| e.to_string())
42}
43
44pub fn escape(text: &str) -> String {
46 regex::escape(text)
47}
48
49pub fn is_match(pattern: &str, text: &str) -> Result<bool, String> {
51 let re = Regex::new(pattern).map_err(|e| e.to_string())?;
52 Ok(re.is_match(text))
53}
54
55pub fn is_match_compiled(re: &Regex, text: &str) -> bool {
57 re.is_match(text)
58}
59
60pub fn find(pattern: &str, text: &str) -> Result<Option<String>, String> {
62 let re = Regex::new(pattern).map_err(|e| e.to_string())?;
63 Ok(re.find(text).map(|m| m.as_str().to_string()))
64}
65
66pub fn find_compiled(re: &Regex, text: &str) -> Option<String> {
68 re.find(text).map(|m| m.as_str().to_string())
69}
70
71pub fn find_all(pattern: &str, text: &str) -> Result<Vec<String>, String> {
73 let re = Regex::new(pattern).map_err(|e| e.to_string())?;
74 Ok(re.find_iter(text).map(|m| m.as_str().to_string()).collect())
75}
76
77pub fn find_all_compiled(re: &Regex, text: &str) -> Vec<String> {
79 re.find_iter(text).map(|m| m.as_str().to_string()).collect()
80}
81
82pub fn replace(pattern: &str, text: &str, replacement: &str) -> Result<String, String> {
84 let re = Regex::new(pattern).map_err(|e| e.to_string())?;
85 Ok(re.replace(text, replacement).to_string())
86}
87
88pub fn replace_compiled(re: &Regex, text: &str, replacement: &str) -> String {
90 re.replace(text, replacement).to_string()
91}
92
93pub fn replace_all(pattern: &str, text: &str, replacement: &str) -> Result<String, String> {
95 let re = Regex::new(pattern).map_err(|e| e.to_string())?;
96 Ok(re.replace_all(text, replacement).to_string())
97}
98
99pub fn replace_all_compiled(re: &Regex, text: &str, replacement: &str) -> String {
101 re.replace_all(text, replacement).to_string()
102}
103
104pub fn split(pattern: &str, text: &str) -> Result<Vec<String>, String> {
106 let re = Regex::new(pattern).map_err(|e| e.to_string())?;
107 Ok(re.split(text).map(|s| s.to_string()).collect())
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_is_match() {
116 assert!(is_match(r"\d+", "123").unwrap());
117 assert!(!is_match(r"\d+", "abc").unwrap());
118 }
119
120 #[test]
121 fn test_find() {
122 assert_eq!(find(r"\d+", "abc123def").unwrap(), Some("123".to_string()));
123 assert_eq!(find(r"\d+", "abc").unwrap(), None);
124 }
125
126 #[test]
127 fn test_find_all() {
128 let matches = find_all(r"\d+", "a1b2c3").unwrap();
129 assert_eq!(matches, vec!["1", "2", "3"]);
130 }
131
132 #[test]
133 fn test_replace() {
134 assert_eq!(replace(r"\d+", "abc123def", "X").unwrap(), "abcXdef");
135 }
136
137 #[test]
138 fn test_replace_all() {
139 assert_eq!(replace_all(r"\d+", "a1b2c3", "X").unwrap(), "aXbXcX");
140 }
141
142 #[test]
143 fn test_split() {
144 let parts = split(r"\s+", "hello world\t\tfoo").unwrap();
145 assert_eq!(parts, vec!["hello", "world", "foo"]);
146 }
147}