1use crate::{PatternReplace, utils::{build_whole_word_pattern, build_word_pattern, build_optional_whole_word_pattern}, WordBounds, PatternMatch, PatternCapture};
2
3pub trait MatchWord<'a> where Self:PatternMatch, Self:PatternCapture<'a> {
8
9 fn match_word_bounds(&self, word: &str, bounds: WordBounds, case_insensitive: bool) -> bool {
11 let word_pattern = bounds.to_pattern(word);
12 self.pattern_match(&word_pattern, case_insensitive)
13 }
14
15 fn match_word(&self, word: &str, case_insensitive: bool) -> bool {
18 let pattern = build_whole_word_pattern(word);
19 self.pattern_match(&pattern, case_insensitive)
20 }
21
22 fn match_any_words(&self, words: &[&str], case_insensitive: bool) -> bool {
24 let pattern = build_optional_whole_word_pattern(words);
25 self.pattern_match(&pattern, case_insensitive)
26 }
27
28 fn match_word_start(&self, word: &str, case_insensitive: bool) -> bool {
30 let word_pattern = build_word_pattern(word, WordBounds::Start);
31 self.pattern_match(&word_pattern, case_insensitive)
32 }
33
34 fn match_word_end(&self, word: &str, case_insensitive: bool) -> bool {
36 let word_pattern = build_word_pattern(word, WordBounds::End);
37 self.pattern_match(&word_pattern, case_insensitive)
38 }
39
40 fn match_word_ci(&self, word: &str) -> bool {
43 self.match_word(word, true)
44 }
45
46 fn match_any_words_ci(&self, words: &[&str]) -> bool {
48 let pattern = build_optional_whole_word_pattern(words);
49 self.pattern_match(&pattern, true)
50 }
51
52 fn match_any_words_cs(&self, words: &[&str]) -> bool {
54 let pattern = build_optional_whole_word_pattern(words);
55 self.pattern_match(&pattern, false)
56 }
57
58 fn match_word_start_ci(&self, word: &str) -> bool {
60 self.match_word_start(word, true)
61 }
62
63 fn match_word_end_ci(&self, word: &str) -> bool {
65 self.match_word_end(word, true)
66 }
67 fn match_word_cs(&self, word: &str) -> bool {
70 self.match_word(word, false)
71 }
72
73 fn match_word_start_cs(&self, word: &str) -> bool {
75 self.match_word_start(word, false)
76 }
77
78 fn match_words_ci(&self, words: &[&str]) -> bool {
80 self.match_words_bounds(words, WordBounds::Both, true)
81 }
82
83 fn match_words_cs(&self, words: &[&str]) -> bool {
85 self.match_words_bounds(words, WordBounds::Both, false)
86 }
87
88 fn match_word_end_cs(&self, word: &str) -> bool {
90 self.match_word_end(word, false)
91 }
92
93 fn count_matched_words_bounds(&self, words: &[&str], bounds: WordBounds, case_insensitive: bool) -> usize {
95 let mut num_matched = 0;
96 for word in words {
97 let pattern = bounds.to_pattern(word);
98 if self.pattern_match(&pattern, case_insensitive) {
99 num_matched += 1;
100 }
101 }
102 num_matched
103 }
104
105 fn match_words_bounds(&self, words: &[&str], bounds: WordBounds, case_insensitive: bool) -> bool {
107 words.len() == self.count_matched_words_bounds(words, bounds, case_insensitive)
108 }
109
110 fn match_words(&self, words: &[&str], case_insensitive: bool) -> bool {
112 self.match_words_bounds(words, WordBounds::Both, case_insensitive)
113 }
114
115 fn match_words_sets_conditional(&self, sets: &[(bool, &str, bool)]) -> bool {
119 let num_words = sets.len();
120 let mut num_matched = 0;
121 for row in sets {
122 let (is_positive, word, case_insensitive) = *row;
123 let pattern = build_whole_word_pattern(word);
124 if self.pattern_match(&pattern, case_insensitive) == is_positive {
125 num_matched += 1;
126 }
127 }
128 num_matched == num_words
129 }
130
131 fn match_words_sets_conditional_ci(&self, tuples: &[(bool, &str)]) -> bool {
135 let num_words = tuples.len();
136 let mut num_matched = 0;
137 for row in tuples {
138 let (is_positive, word) = *row;
139 let pattern = build_whole_word_pattern(word);
140 if self.pattern_match(&pattern, true) == is_positive {
141 num_matched += 1;
142 }
143 }
144 num_matched == num_words
145 }
146
147}
148
149impl<'a> MatchWord<'a> for str {
151}
152
153pub trait ReplaceWord where Self:PatternReplace {
155
156 fn replace_word_bounds(&self, word: &str, replacement: &str, bounds: WordBounds, case_insensitive: bool) -> Self where Self:Sized;
158
159 fn replace_word(&self, word: &str, replacement: &str, case_insensitive: bool) -> Self where Self:Sized;
161
162 fn replace_word_ci(&self, word: &str, replacement: &str) -> Self where Self:Sized {
164 let pattern = build_whole_word_pattern(word);
165 self.pattern_replace(&pattern, replacement, true)
166 }
167
168 fn replace_word_cs(&self, word: &str, replacement: &str) -> Self where Self:Sized {
170 let pattern = build_whole_word_pattern(word);
171 self.pattern_replace(&pattern, replacement, false)
172 }
173
174 fn replace_words(&self, pairs: &[(&str, &str)], case_insensitive: bool) -> Self where Self:Sized;
176
177 fn replace_words_ci(&self, pairs: &[(&str, &str)]) -> Self where Self:Sized {
179 self.replace_words(pairs, true)
180 }
181
182 fn replace_words_cs(&self, pairs: &[(&str, &str)]) -> Self where Self:Sized {
184 self.replace_words(pairs, false)
185 }
186
187 fn replace_word_sets(&self, pairs: &[(&str, &str, bool)]) -> Self where Self:Sized;
189
190}
191
192
193impl ReplaceWord for String {
195
196 fn replace_word_bounds(&self, word: &str, replacement: &str, bounds: WordBounds, case_insensitive: bool) -> String {
198 let pattern = build_word_pattern(word, bounds);
199 self.pattern_replace(&pattern, replacement, case_insensitive)
200 }
201
202 fn replace_word(&self, word: &str, replacement: &str, case_insensitive: bool) -> String {
204 let pattern = build_whole_word_pattern(word);
205 self.pattern_replace(&pattern, replacement, case_insensitive)
206 }
207
208 fn replace_words(&self, pairs: &[(&str, &str)], case_insensitive: bool) -> String {
210 let mut output = self.clone();
211 for pair in pairs {
212 let (word, replacement) = *pair;
213 let pattern = build_whole_word_pattern(word);
214 output = output.pattern_replace(&pattern, replacement, case_insensitive);
215 }
216 output
217 }
218
219 fn replace_word_sets(&self, tuples: &[(&str, &str, bool)]) -> String {
221 let mut output = self.clone();
222 for row in tuples {
223 let (word, replacement, case_insensitive) = *row;
224 let pattern = build_whole_word_pattern(word);
225 output = output.pattern_replace(&pattern, replacement, case_insensitive);
226 }
227 output
228 }
229
230}