1use crate::ast::{BinaryOperator, Expression, LogicalExpression, Predicate, Value};
2use crate::context::{Context, Match};
3
4pub trait Execute {
5 fn execute(&self, ctx: &mut Context, m: &mut Match) -> bool;
6}
7
8impl Execute for Expression {
9 fn execute(&self, ctx: &mut Context, m: &mut Match) -> bool {
10 match self {
11 Expression::Logical(l) => match l.as_ref() {
12 LogicalExpression::And(l, r) => l.execute(ctx, m) && r.execute(ctx, m),
13 LogicalExpression::Or(l, r) => l.execute(ctx, m) || r.execute(ctx, m),
14 LogicalExpression::Not(r) => !r.execute(ctx, m),
15 },
16 Expression::Predicate(p) => p.execute(ctx, m),
17 }
18 }
19}
20
21impl Execute for Predicate {
22 fn execute(&self, ctx: &mut Context, m: &mut Match) -> bool {
23 let lhs_values = match ctx.value_of(&self.lhs.var_name) {
24 None => return false,
25 Some(v) => v,
26 };
27
28 let (lower, any) = self.lhs.get_transformations();
29
30 for mut lhs_value in lhs_values.iter() {
34 let lhs_value_transformed;
35
36 if lower {
37 match lhs_value {
38 Value::String(s) => {
39 lhs_value_transformed = Value::String(s.to_lowercase());
40 lhs_value = &lhs_value_transformed;
41 }
42 _ => unreachable!(),
43 }
44 }
45
46 let mut matched = false;
47 match self.op {
48 BinaryOperator::Equals => {
49 if lhs_value == &self.rhs {
50 m.matches
51 .insert(self.lhs.var_name.clone(), self.rhs.clone());
52
53 if any {
54 return true;
55 }
56
57 matched = true;
58 }
59 }
60 BinaryOperator::NotEquals => {
61 if lhs_value != &self.rhs {
62 if any {
63 return true;
64 }
65
66 matched = true;
67 }
68 }
69 BinaryOperator::Regex => {
70 let rhs = match &self.rhs {
71 Value::Regex(r) => r,
72 _ => unreachable!(),
73 };
74 let lhs = match lhs_value {
75 Value::String(s) => s,
76 _ => unreachable!(),
77 };
78
79 if rhs.is_match(lhs) {
80 let reg_cap = rhs.captures(lhs).unwrap();
81
82 m.matches.insert(
83 self.lhs.var_name.clone(),
84 Value::String(reg_cap.get(0).unwrap().as_str().to_string()),
85 );
86
87 for (i, c) in reg_cap.iter().enumerate() {
88 if let Some(c) = c {
89 m.captures.insert(i.to_string(), c.as_str().to_string());
90 }
91 }
92
93 for n in rhs.capture_names().flatten() {
95 if let Some(value) = reg_cap.name(n) {
96 m.captures.insert(n.to_string(), value.as_str().to_string());
97 }
98 }
99
100 if any {
101 return true;
102 }
103
104 matched = true;
105 }
106 }
107 BinaryOperator::Prefix => {
108 let rhs = match &self.rhs {
109 Value::String(s) => s,
110 _ => unreachable!(),
111 };
112 let lhs = match lhs_value {
113 Value::String(s) => s,
114 _ => unreachable!(),
115 };
116
117 if lhs.starts_with(rhs) {
118 m.matches
119 .insert(self.lhs.var_name.clone(), self.rhs.clone());
120 if any {
121 return true;
122 }
123
124 matched = true;
125 }
126 }
127 BinaryOperator::Postfix => {
128 let rhs = match &self.rhs {
129 Value::String(s) => s,
130 _ => unreachable!(),
131 };
132 let lhs = match lhs_value {
133 Value::String(s) => s,
134 _ => unreachable!(),
135 };
136
137 if lhs.ends_with(rhs) {
138 m.matches
139 .insert(self.lhs.var_name.clone(), self.rhs.clone());
140 if any {
141 return true;
142 }
143
144 matched = true;
145 }
146 }
147 BinaryOperator::Greater => {
148 let rhs = match &self.rhs {
149 Value::Int(i) => i,
150 _ => unreachable!(),
151 };
152 let lhs = match lhs_value {
153 Value::Int(i) => i,
154 _ => unreachable!(),
155 };
156
157 if lhs > rhs {
158 if any {
159 return true;
160 }
161
162 matched = true;
163 }
164 }
165 BinaryOperator::GreaterOrEqual => {
166 let rhs = match &self.rhs {
167 Value::Int(i) => i,
168 _ => unreachable!(),
169 };
170 let lhs = match lhs_value {
171 Value::Int(i) => i,
172 _ => unreachable!(),
173 };
174
175 if lhs >= rhs {
176 if any {
177 return true;
178 }
179
180 matched = true;
181 }
182 }
183 BinaryOperator::Less => {
184 let rhs = match &self.rhs {
185 Value::Int(i) => i,
186 _ => unreachable!(),
187 };
188 let lhs = match lhs_value {
189 Value::Int(i) => i,
190 _ => unreachable!(),
191 };
192
193 if lhs < rhs {
194 if any {
195 return true;
196 }
197
198 matched = true;
199 }
200 }
201 BinaryOperator::LessOrEqual => {
202 let rhs = match &self.rhs {
203 Value::Int(i) => i,
204 _ => unreachable!(),
205 };
206 let lhs = match lhs_value {
207 Value::Int(i) => i,
208 _ => unreachable!(),
209 };
210
211 if lhs <= rhs {
212 if any {
213 return true;
214 }
215
216 matched = true;
217 }
218 }
219 BinaryOperator::In => match (lhs_value, &self.rhs) {
220 (Value::IpAddr(l), Value::IpCidr(r)) => {
221 if r.contains(l) {
222 matched = true;
223 if any {
224 return true;
225 }
226 }
227 }
228 _ => unreachable!(),
229 },
230 BinaryOperator::NotIn => match (lhs_value, &self.rhs) {
231 (Value::IpAddr(l), Value::IpCidr(r)) => {
232 if !r.contains(l) {
233 matched = true;
234 if any {
235 return true;
236 }
237 }
238 }
239 _ => unreachable!(),
240 },
241 BinaryOperator::Contains => {
242 let rhs = match &self.rhs {
243 Value::String(s) => s,
244 _ => unreachable!(),
245 };
246 let lhs = match lhs_value {
247 Value::String(s) => s,
248 _ => unreachable!(),
249 };
250
251 if lhs.contains(rhs) {
252 if any {
253 return true;
254 }
255
256 matched = true;
257 }
258 }
259 } if !any && !matched {
262 return false;
264 }
265 } !any && !lhs_values.is_empty()
271 }
272}
273
274#[test]
275fn test_predicate() {
276 use crate::ast;
277 use crate::schema;
278
279 let mut mat = Match::new();
280 let mut schema = schema::Schema::default();
281 schema.add_field("my_key", ast::Type::String);
282 let mut ctx = Context::new(&schema);
283
284 let p = Predicate {
287 lhs: ast::Lhs {
288 var_name: "my_key".to_string(),
289 transformations: vec![],
290 },
291 rhs: Value::String("foo".to_string()),
292 op: BinaryOperator::Prefix,
293 };
294
295 assert_eq!(p.execute(&mut ctx, &mut mat), false);
296
297 let p = Predicate {
299 lhs: ast::Lhs {
300 var_name: "my_key".to_string(),
301 transformations: vec![],
302 },
303 rhs: Value::String("foo".to_string()),
304 op: BinaryOperator::Prefix,
305 };
306
307 assert_eq!(p.execute(&mut ctx, &mut mat), false);
308
309 let lhs_values = vec![
311 Value::String("foofoo".to_string()),
312 Value::String("foobar".to_string()),
313 Value::String("foocar".to_string()),
314 Value::String("fooban".to_string()),
315 ];
316
317 for v in lhs_values {
318 ctx.add_value("my_key", v);
319 }
320
321 let p = Predicate {
323 lhs: ast::Lhs {
324 var_name: "my_key".to_string(),
325 transformations: vec![],
326 },
327 rhs: Value::String("foo".to_string()),
328 op: BinaryOperator::Prefix,
329 };
330
331 assert_eq!(p.execute(&mut ctx, &mut mat), true);
332
333 let p = Predicate {
335 lhs: ast::Lhs {
336 var_name: "my_key".to_string(),
337 transformations: vec![],
338 },
339 rhs: Value::String("foo".to_string()),
340 op: BinaryOperator::Postfix,
341 };
342
343 assert_eq!(p.execute(&mut ctx, &mut mat), false);
344
345 let p = Predicate {
347 lhs: ast::Lhs {
348 var_name: "my_key".to_string(),
349 transformations: vec![ast::LhsTransformations::Any],
350 },
351 rhs: Value::String("foo".to_string()),
352 op: BinaryOperator::Postfix,
353 };
354
355 assert_eq!(p.execute(&mut ctx, &mut mat), true);
356
357 let p = Predicate {
359 lhs: ast::Lhs {
360 var_name: "my_key".to_string(),
361 transformations: vec![ast::LhsTransformations::Any],
362 },
363 rhs: Value::String("foo".to_string()),
364 op: BinaryOperator::Prefix,
365 };
366
367 assert_eq!(p.execute(&mut ctx, &mut mat), true);
368
369 let p = Predicate {
371 lhs: ast::Lhs {
372 var_name: "my_key".to_string(),
373 transformations: vec![ast::LhsTransformations::Any],
374 },
375 rhs: Value::String("nar".to_string()),
376 op: BinaryOperator::Postfix,
377 };
378
379 assert_eq!(p.execute(&mut ctx, &mut mat), false);
380
381 let p = Predicate {
383 lhs: ast::Lhs {
384 var_name: "my_key".to_string(),
385 transformations: vec![ast::LhsTransformations::Any],
386 },
387 rhs: Value::String("".to_string()),
388 op: BinaryOperator::Postfix,
389 };
390
391 assert_eq!(p.execute(&mut ctx, &mut mat), true);
392
393 let p = Predicate {
395 lhs: ast::Lhs {
396 var_name: "my_key".to_string(),
397 transformations: vec![ast::LhsTransformations::Any],
398 },
399 rhs: Value::String("".to_string()),
400 op: BinaryOperator::Prefix,
401 };
402
403 assert_eq!(p.execute(&mut ctx, &mut mat), true);
404
405 let p = Predicate {
407 lhs: ast::Lhs {
408 var_name: "my_key".to_string(),
409 transformations: vec![ast::LhsTransformations::Any],
410 },
411 rhs: Value::String("ob".to_string()),
412 op: BinaryOperator::Contains,
413 };
414
415 assert_eq!(p.execute(&mut ctx, &mut mat), true);
416
417 let p = Predicate {
419 lhs: ast::Lhs {
420 var_name: "my_key".to_string(),
421 transformations: vec![ast::LhsTransformations::Any],
422 },
423 rhs: Value::String("ok".to_string()),
424 op: BinaryOperator::Contains,
425 };
426
427 assert_eq!(p.execute(&mut ctx, &mut mat), false);
428}