1use std::{borrow::Borrow, fmt};
13
14pub enum PatternElem<T> {
22 Value {
27 value: T,
28 min_repeat: Option<usize>,
29 max_repeat: Option<usize>,
30 capture_name: Option<String>,
31 },
32 Matcher {
34 matcher: Box<dyn Fn(&T) -> bool + 'static>,
35 min_repeat: Option<usize>,
36 max_repeat: Option<usize>,
37 capture_name: Option<String>,
38 },
39 Any {
41 min_repeat: Option<usize>,
42 max_repeat: Option<usize>,
43 capture_name: Option<String>,
44 },
45}
46
47impl<T: fmt::Debug> fmt::Debug for PatternElem<T> {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 match self {
50 PatternElem::Value { value, min_repeat, max_repeat, capture_name } => {
51 write!(f, "Value({:?}, min_repeat={:?}, max_repeat={:?}, capture_name={:?})", value, min_repeat, max_repeat, capture_name)
52 }
53 PatternElem::Matcher { min_repeat, max_repeat, capture_name, .. } => {
54 write!(f, "Matcher(.., min_repeat={:?}, max_repeat={:?}, capture_name={:?})", min_repeat, max_repeat, capture_name)
55 }
56 PatternElem::Any { min_repeat, max_repeat, capture_name } => {
57 write!(f, "Any(min_repeat={:?}, max_repeat={:?}, capture_name={:?})", min_repeat, max_repeat, capture_name)
58 }
59 }
60 }
61}
62
63impl<T: Clone> Clone for PatternElem<T> {
69 fn clone(&self) -> Self {
70 match self {
71 PatternElem::Value { value, min_repeat, max_repeat, capture_name } => PatternElem::Value {
72 value: value.clone(),
73 min_repeat: *min_repeat,
74 max_repeat: *max_repeat,
75 capture_name: capture_name.clone(),
76 },
77 PatternElem::Any { min_repeat, max_repeat, capture_name } => PatternElem::Any {
78 min_repeat: *min_repeat,
79 max_repeat: *max_repeat,
80 capture_name: capture_name.clone(),
81 },
82 PatternElem::Matcher { .. } => panic!("Cannot clone PatternElem::Matcher"),
83 }
84 }
85}
86
87pub struct Pattern<T> {
94 pub pattern: Vec<PatternElem<T>>,
95 pub callback: Option<SliceCallback<T>>,
96 pub overlap: bool,
97 pub deduplication: bool,
98 pub name: Option<String>,
99}
100
101impl<T> AsRef<Pattern<T>> for Pattern<T> {
103 fn as_ref(&self) -> &Pattern<T> {
104 self
105 }
106}
107
108impl<T: Clone> Clone for Pattern<T> {
109 fn clone(&self) -> Self {
110 Pattern {
111 pattern: self.pattern.clone(),
112 callback: None, overlap: self.overlap,
114 deduplication: self.deduplication,
115 name: self.name.clone(),
116 }
117 }
118}
119
120impl<T> Pattern<T> {
121 pub fn new(pattern: Vec<PatternElem<T>>) -> Self {
123 Self {
124 pattern,
125 callback: None,
126 overlap: true,
127 deduplication: false,
128 name: None,
129 }
130 }
131 pub fn with_name(mut self, name: impl Into<String>) -> Self {
133 self.name = Some(name.into());
134 self
135 }
136 pub fn with_callback(mut self, cb: SliceCallback<T>) -> Self {
138 self.callback = Some(cb);
139 self
140 }
141 pub fn overlap(mut self, allow: bool) -> Self {
143 self.overlap = allow;
144 self
145 }
146 pub fn deduplication(mut self, enable: bool) -> Self {
148 self.deduplication = enable;
149 self
150 }
151}
152
153pub type SliceCallback<T> = Box<dyn Fn(&[T]) + 'static>;
157
158pub struct PatternBuilderErased {
162 overlap: bool,
163 deduplication: bool,
164 name: Option<String>,
165}
166
167impl PatternBuilderErased {
168 pub fn new() -> Self {
170 Self {
171 overlap: true,
172 deduplication: false,
173 name: None,
174 }
175 }
176
177 pub fn value_elem<T>(self, value: T) -> PatternBuilder<T> {
180 PatternBuilder {
181 pattern: vec![PatternElem::Value {
182 value,
183 min_repeat: None,
184 max_repeat: None,
185 capture_name: None,
186 }],
187 callback: None,
188 overlap: self.overlap,
189 deduplication: self.deduplication,
190 name: self.name,
191 }
192 }
193
194 pub fn matcher_elem<T, F>(self, matcher: F) -> PatternBuilder<T>
197 where
198 F: Fn(&T) -> bool + 'static,
199 {
200 PatternBuilder {
201 pattern: vec![PatternElem::Matcher {
202 matcher: Box::new(matcher),
203 min_repeat: None,
204 max_repeat: None,
205 capture_name: None,
206 }],
207 callback: None,
208 overlap: self.overlap,
209 deduplication: self.deduplication,
210 name: self.name,
211 }
212 }
213
214 pub fn any_elem<T>(self) -> PatternBuilder<T> {
217 PatternBuilder {
218 pattern: vec![PatternElem::Any {
219 min_repeat: None,
220 max_repeat: None,
221 capture_name: None,
222 }],
223 callback: None,
224 overlap: self.overlap,
225 deduplication: self.deduplication,
226 name: self.name,
227 }
228 }
229
230 pub fn name(mut self, name: impl Into<String>) -> Self {
233 self.name = Some(name.into());
234 self
235 }
236
237 pub fn overlap(mut self, allow: bool) -> Self {
240 self.overlap = allow;
241 self
242 }
243
244 pub fn deduplication(mut self, enable: bool) -> Self {
247 self.deduplication = enable;
248 self
249 }
250}
251
252pub struct PatternBuilder<T> {
256 pub pattern: Vec<PatternElem<T>>,
257 pub callback: Option<SliceCallback<T>>,
258 pub overlap: bool,
259 pub deduplication: bool,
260 pub name: Option<String>,
261}
262
263impl<T> PatternBuilder<T> {
264 pub fn min_repeat(mut self, min: usize) -> Self {
266 if let Some(last) = self.pattern.last_mut() {
267 match last {
268 PatternElem::Value { min_repeat, .. } => *min_repeat = Some(min),
269 PatternElem::Matcher { min_repeat, .. } => *min_repeat = Some(min),
270 PatternElem::Any { min_repeat, .. } => *min_repeat = Some(min),
271 }
272 }
273 self
274 }
275 pub fn max_repeat(mut self, max: usize) -> Self {
277 if let Some(last) = self.pattern.last_mut() {
278 match last {
279 PatternElem::Value { max_repeat, .. } => *max_repeat = Some(max),
280 PatternElem::Matcher { max_repeat, .. } => *max_repeat = Some(max),
281 PatternElem::Any { max_repeat, .. } => *max_repeat = Some(max),
282 }
283 }
284 self
285 }
286 pub fn capture_name(mut self, name: impl Into<String>) -> Self {
288 if let Some(last) = self.pattern.last_mut() {
289 match last {
290 PatternElem::Value { capture_name, .. } => *capture_name = Some(name.into()),
291 PatternElem::Matcher { capture_name, .. } => *capture_name = Some(name.into()),
292 PatternElem::Any { capture_name, .. } => *capture_name = Some(name.into()),
293 }
294 }
295 self
296 }
297 pub fn callback(mut self, cb: SliceCallback<T>) -> Self {
299 self.callback = Some(cb);
300 self
301 }
302 pub fn value_elem(mut self, value: T) -> Self {
303 self.pattern.push(PatternElem::Value {
304 value,
305 min_repeat: None,
306 max_repeat: None,
307 capture_name: None,
308 });
309 self
310 }
311 pub fn matcher_elem<F>(mut self, matcher: F) -> Self
312 where
313 F: Fn(&T) -> bool + 'static,
314 {
315 self.pattern.push(PatternElem::Matcher {
316 matcher: Box::new(matcher),
317 min_repeat: None,
318 max_repeat: None,
319 capture_name: None,
320 });
321 self
322 }
323 pub fn any_elem(mut self) -> Self {
324 self.pattern.push(PatternElem::Any {
325 min_repeat: None,
326 max_repeat: None,
327 capture_name: None,
328 });
329 self
330 }
331 pub fn build(self) -> Pattern<T> {
332 Pattern {
333 pattern: self.pattern,
334 callback: self.callback,
335 overlap: self.overlap,
336 deduplication: self.deduplication,
337 name: self.name,
338 }
339 }
340 pub fn name(mut self, name: impl Into<String>) -> Self {
341 self.name = Some(name.into());
342 self
343 }
344 pub fn overlap(mut self, allow: bool) -> Self {
345 self.overlap = allow;
346 self
347 }
348 pub fn deduplication(mut self, enable: bool) -> Self {
349 self.deduplication = enable;
350 self
351 }
352}
353
354#[derive(Debug, Clone)]
358pub struct ScrollingWindowPatternMatcherRef {
359 pub window_len: usize,
360}
361
362impl ScrollingWindowPatternMatcherRef {
363 pub fn find_matches<T>(&self, window: &[T], patterns: &[Pattern<T>]) -> std::collections::HashMap<String, Vec<std::collections::HashMap<String, Vec<T>>>>
371 where
372 T: PartialEq + Clone + std::fmt::Debug,
373 {
374 use std::collections::HashMap;
375 let mut results: HashMap<String, Vec<HashMap<String, Vec<T>>>> = HashMap::new();
376 for (p_idx, pat) in patterns.iter().enumerate() {
377 let pat_name = pat.name.clone().unwrap_or_else(|| format!("pattern_{}", p_idx));
378 let pat_len = pat.pattern.len();
379 if pat_len == 0 || window.is_empty() {
380 continue;
381 }
382 let mut w_idx = 0;
383 while w_idx < window.len() {
384 let mut win_pos = w_idx;
385 let mut captures: HashMap<String, Vec<T>> = HashMap::new();
386 let mut matched = true;
387 let mut match_indices = Vec::new();
388 for elem in pat.pattern.iter() {
389 let min_repeat = match elem {
391 PatternElem::Value { min_repeat, .. } => min_repeat,
392 PatternElem::Matcher { min_repeat, .. } => min_repeat,
393 PatternElem::Any { min_repeat, .. } => min_repeat,
394 };
395 let max_repeat = match elem {
396 PatternElem::Value { max_repeat, .. } => max_repeat,
397 PatternElem::Matcher { max_repeat, .. } => max_repeat,
398 PatternElem::Any { max_repeat, .. } => max_repeat,
399 };
400 let repeat_min = min_repeat.unwrap_or(1);
401 let repeat_max = max_repeat.unwrap_or(1);
402 let mut repeat_count = 0;
403 let mut repeat_indices = Vec::new();
404 while repeat_count < repeat_max && win_pos < window.len() {
405 let elem_match = match elem {
406 PatternElem::Value { value, .. } => &window[win_pos] == value,
407 PatternElem::Matcher { matcher, .. } => matcher(&window[win_pos]),
408 PatternElem::Any { .. } => true,
409 };
410 if elem_match {
411 repeat_indices.push(win_pos);
412 repeat_count += 1;
413 win_pos += 1;
414 } else {
415 break;
416 }
417 }
418 if repeat_count < repeat_min {
419 matched = false;
420 break;
421 }
422 match_indices.extend(repeat_indices.iter().copied());
423 let capture_name = match elem {
425 PatternElem::Value { capture_name, .. } => capture_name,
426 PatternElem::Matcher { capture_name, .. } => capture_name,
427 PatternElem::Any { capture_name, .. } => capture_name,
428 };
429 if let Some(name) = capture_name {
430 let captured: Vec<T> = repeat_indices.iter().map(|&i| window[i].clone()).collect();
431 captures.insert(name.clone(), captured);
432 }
433 }
434 if matched && !match_indices.is_empty() {
435 if let Some(cb) = &pat.callback {
437 let matched_slice: Vec<T> = match_indices.iter().map(|&i| window[i].clone()).collect();
439 cb(&matched_slice);
440 }
441 results.entry(pat_name.clone()).or_default().push(captures);
442 }
443 w_idx += 1;
444 }
445 }
446 results
447 }
448 pub fn new(window_len: usize) -> Self {
450 Self { window_len }
451 }
452
453 pub fn find_matches_flexible<T, W, P>(&self, window: W, patterns: P) -> std::collections::HashMap<String, Vec<std::collections::HashMap<String, Vec<T>>>>
482 where
483 W: IntoIterator,
484 W::Item: Borrow<T>,
485 T: Clone + PartialEq + std::fmt::Debug,
486 P: IntoIterator,
487 P::Item: AsRef<Pattern<T>>,
488 Pattern<T>: Clone,
489 {
490 let window_vec: Vec<T> = window.into_iter()
491 .map(|x| x.borrow().clone())
492 .collect();
493 let patterns_vec: Vec<Pattern<T>> = patterns
494 .into_iter()
495 .map(|p| p.as_ref().clone())
496 .collect();
497 self.find_matches(&window_vec, &patterns_vec)
499 }
500}
501
502