Skip to main content

rama_core/matcher/
iter.rs

1use crate::extensions::Extensions;
2
3use super::Matcher;
4
5/// Extension to apply matcher operations to an [`Iterator`] of [`Matcher`]s.
6pub trait IteratorMatcherExt<'a, M, Input>: Iterator<Item = &'a M> + 'a
7where
8    M: Matcher<Input>,
9{
10    /// Matches in case all [`Matcher`] elements match for the given `Input`
11    /// within the specified [`Extensions`].
12    fn matches_and(self, ext: Option<&Extensions>, input: &Input) -> bool;
13
14    /// Matches in case any of the [`Matcher`] elements match for the given `Input`
15    /// within the specified [`Extensions`].
16    fn matches_or(self, ext: Option<&Extensions>, input: &Input) -> bool;
17}
18
19impl<'a, I, M, Input> IteratorMatcherExt<'a, M, Input> for I
20where
21    I: Iterator<Item = &'a M> + 'a,
22    M: Matcher<Input>,
23{
24    fn matches_and(self, ext: Option<&Extensions>, input: &Input) -> bool {
25        match ext {
26            None => {
27                for matcher in self {
28                    if !matcher.matches(None, input) {
29                        return false;
30                    }
31                }
32                true
33            }
34            Some(ext) => {
35                let inner_ext = Extensions::new();
36                for matcher in self {
37                    if !matcher.matches(Some(&inner_ext), input) {
38                        return false;
39                    }
40                }
41                ext.extend(&inner_ext);
42                true
43            }
44        }
45    }
46
47    fn matches_or(self, ext: Option<&Extensions>, input: &Input) -> bool {
48        let mut it = self.peekable();
49        if it.peek().is_none() {
50            return true;
51        }
52
53        match ext {
54            None => {
55                for matcher in it {
56                    if matcher.matches(None, input) {
57                        return true;
58                    }
59                }
60                false
61            }
62            Some(ext) => {
63                for matcher in it {
64                    let inner_ext = Extensions::new();
65                    if matcher.matches(Some(&inner_ext), input) {
66                        ext.extend(&inner_ext);
67                        return true;
68                    }
69                }
70                false
71            }
72        }
73    }
74}