rbe/
rbe1_matcher.rs

1use std::collections::HashSet;
2use tracing::debug;
3
4use crate::{rbe1::Rbe, Key, Ref, Value};
5use crate::{rbe_error::RbeError, Pending};
6
7#[derive(Default)]
8pub struct RbeMatcher<K, V, R>
9where
10    K: Key,
11    V: Value,
12    R: Ref,
13{
14    rbe: Rbe<K, V, R>,
15    open: bool,
16    controlled: HashSet<K>,
17}
18
19impl<K, V, R> RbeMatcher<K, V, R>
20where
21    K: Key,
22    V: Value,
23    R: Ref,
24{
25    pub fn new() -> RbeMatcher<K, V, R> {
26        RbeMatcher::default()
27    }
28
29    pub fn with_rbe(mut self, rbe: &Rbe<K, V, R>) -> Self {
30        self.rbe = (*rbe).clone();
31        self.controlled = rbe.symbols();
32        self
33    }
34
35    pub fn extend_controlled(mut self, controlled: HashSet<K>) -> Self {
36        self.controlled.extend(controlled);
37        self
38    }
39
40    pub fn with_open(mut self, open: bool) -> Self {
41        self.open = open;
42        self
43    }
44
45    pub fn matches<T: IntoIterator<Item = (K, V)>>(
46        &self,
47        iter: T,
48    ) -> Result<Pending<V, R>, RbeError<K, V, R>> {
49        let mut pending = Pending::new();
50        let mut processed: Vec<(K, V)> = Vec::new();
51        match self.matches_iter(iter, &mut pending, &mut processed) {
52            Rbe::Fail { error } => Err(error.clone()),
53            d => {
54                if d.nullable() {
55                    Ok(pending)
56                } else {
57                    Err(RbeError::NonNullableMatch {
58                        non_nullable_rbe: Box::new(d.clone()),
59                        expr: Box::new(self.rbe.clone()),
60                    })
61                }
62            }
63        }
64    }
65
66    fn matches_iter<T: IntoIterator<Item = (K, V)>>(
67        &self,
68        iter: T,
69        pending: &mut Pending<V, R>,
70        processed: &mut Vec<(K, V)>,
71    ) -> Rbe<K, V, R> {
72        let mut current = self.rbe.clone();
73        for (key, value) in iter {
74            let deriv = current.deriv(&key, &value, 1, self.open, &self.controlled, pending);
75            match deriv {
76                Rbe::Fail { error } => {
77                    current = Rbe::Fail {
78                        error: RbeError::DerivIterError {
79                            error_msg: format!("{error}"),
80                            processed: processed.clone(),
81                            expr: Box::new(self.rbe.clone()),
82                            current: Box::new(current.clone()),
83                            key: key.clone(),
84                            open: self.open,
85                        },
86                    };
87                    break;
88                }
89                _ => {
90                    debug!("Processing: {key}/{value}\ncurrent:{current}\nderiv:{deriv}");
91                    processed.push((key.clone(), value.clone()));
92                    current = deriv;
93                }
94            }
95        }
96        current
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103    use crate::{MatchCond, Max, Min, SingleCond};
104
105    impl Value for i32 {}
106    impl Ref for String {}
107
108    fn is_even(v: &i32) -> Result<Pending<i32, String>, RbeError<char, i32, String>> {
109        if v % 2 == 0 {
110            Ok(Pending::new())
111        } else {
112            Err(RbeError::MsgError {
113                msg: format!("Value {v} is not even"),
114            })
115        }
116    }
117
118    fn ref_x(v: &i32) -> Result<Pending<i32, String>, RbeError<char, i32, String>> {
119        let ps = vec![(*v, vec!["X".to_string()])].into_iter();
120        Ok(Pending::from(ps))
121    }
122
123    impl Value for String {}
124
125    fn cond_name(name: String) -> MatchCond<char, String, String> {
126        MatchCond::single(SingleCond::new().with_cond(move |v: &String| {
127            if *v == name {
128                Ok(Pending::new())
129            } else {
130                Err(RbeError::MsgError {
131                    msg: format!("Value {v} is not equal to {name}"),
132                })
133            }
134        }))
135    }
136
137    fn cond_len(len: usize) -> MatchCond<char, String, String> {
138        MatchCond::single(SingleCond::new().with_cond(move |v: &String| {
139            if v.len() == len {
140                Ok(Pending::new())
141            } else {
142                Err(RbeError::MsgError {
143                    msg: format!("Value {v} has no length {len}"),
144                })
145            }
146        }))
147    }
148
149    #[test]
150    fn test_rbe_matcher_len_name() {
151        let rbe: Rbe<char, String, String> = Rbe::and(vec![
152            Rbe::symbol_cond('a', cond_len(3), Min::from(1), Max::IntMax(1)),
153            Rbe::symbol_cond(
154                'b',
155                cond_name("foo".to_string()),
156                Min::from(0),
157                Max::IntMax(1),
158            ),
159        ]);
160        let expected = Pending::new();
161        let rbe_matcher = RbeMatcher::new().with_rbe(&rbe);
162
163        assert_eq!(
164            rbe_matcher.matches(vec![('a', "baz".to_string())].into_iter()),
165            Ok(expected)
166        );
167    }
168
169    #[test]
170    fn test_rbe_matcher_even_ref() {
171        let cond_even = MatchCond::single(SingleCond::new().with_cond(is_even));
172        let cond_ref_x = MatchCond::single(SingleCond::new().with_cond(ref_x));
173
174        let rbe: Rbe<char, i32, String> = Rbe::and(vec![
175            Rbe::symbol_cond('a', cond_even, Min::from(1), Max::IntMax(1)),
176            Rbe::symbol_cond('b', cond_ref_x, Min::from(0), Max::IntMax(1)),
177        ]);
178        let expected = Pending::from(vec![(42, vec!["X".to_string()])]);
179        let rbe_matcher = RbeMatcher::new().with_rbe(&rbe);
180
181        assert_eq!(
182            rbe_matcher.matches(vec![('a', 2), ('b', 42)].into_iter()),
183            Ok(expected)
184        );
185    }
186
187    #[test]
188    fn test_rbe_matcher_even_ref_unordered() {
189        let cond_even = MatchCond::single(SingleCond::new().with_cond(is_even));
190        let cond_ref_x = MatchCond::single(SingleCond::new().with_cond(ref_x));
191
192        let rbe: Rbe<char, i32, String> = Rbe::and(vec![
193            Rbe::symbol_cond('a', cond_even, Min::from(1), Max::IntMax(1)),
194            Rbe::symbol_cond('b', cond_ref_x, Min::from(0), Max::IntMax(1)),
195        ]);
196        let expected = Pending::from(vec![(42, vec!["X".to_string()])]);
197        let rbe_matcher = RbeMatcher::new().with_rbe(&rbe);
198
199        assert_eq!(
200            rbe_matcher.matches(vec![('b', 42), ('a', 2)].into_iter()),
201            Ok(expected)
202        );
203    }
204
205    #[test]
206    fn test_rbe_matcher_even_fails_odd() {
207        let cond_even = MatchCond::single(SingleCond::new().with_cond(is_even));
208        let cond_ref_x = MatchCond::single(SingleCond::new().with_cond(ref_x));
209
210        let rbe: Rbe<char, i32, String> = Rbe::and(vec![
211            Rbe::symbol_cond('a', cond_even, Min::from(1), Max::IntMax(1)),
212            Rbe::symbol_cond('b', cond_ref_x, Min::from(0), Max::IntMax(1)),
213        ]);
214        let rbe_matcher = RbeMatcher::new().with_rbe(&rbe);
215        let iter = vec![('b', 42), ('a', 3)].into_iter();
216        assert!(rbe_matcher.matches(iter).is_err());
217    }
218}