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}