1use std::collections::HashMap;
2use std::fmt;
3
4use aho_corasick::AhoCorasick;
5use tracing::debug;
6
7use crate::document::Document;
8use crate::parser::{Expression, Match, MatchType, Search};
9use crate::rule::Detection;
10use crate::tokeniser::{BoolSym, ModSym};
11use crate::value::Value;
12
13struct Cache<'a>(&'a Vec<Option<Value<'a>>>);
14
15impl Document for Cache<'_> {
16 fn find(&self, key: &str) -> Option<Value> {
17 let i = key.chars().nth(0).expect("could not get key") as u32;
18 self.0[i as usize].clone()
19 }
20}
21
22struct Passthrough<'a>(Option<Value<'a>>);
23
24impl Document for Passthrough<'_> {
25 fn find(&self, _: &str) -> Option<Value> {
26 self.0.clone()
27 }
28}
29
30#[derive(Debug, PartialEq)]
31pub(crate) enum SolverResult {
32 True,
33 False,
34 Missing,
35}
36impl fmt::Display for SolverResult {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 Self::True => write!(f, "true"),
40 Self::False => write!(f, "false"),
41 Self::Missing => write!(f, "missing"),
42 }
43 }
44}
45
46pub fn solve(detection: &Detection, document: &dyn Document) -> bool {
48 match solve_expression(&detection.expression, &detection.identifiers, document) {
49 SolverResult::True => true,
50 SolverResult::False | SolverResult::Missing => false,
51 }
52}
53
54pub(crate) fn solve_expression(
55 expression: &Expression,
56 identifiers: &HashMap<String, Expression>,
57 document: &dyn Document,
58) -> SolverResult {
59 match *expression {
60 Expression::BooleanGroup(BoolSym::And, ref group) => {
61 for expression in group {
62 match solve_expression(expression, identifiers, document) {
63 SolverResult::True => {}
64 SolverResult::False => return SolverResult::False,
65 SolverResult::Missing => return SolverResult::Missing,
66 }
67 }
68 SolverResult::True
69 }
70 Expression::BooleanGroup(BoolSym::Or, ref group) => {
71 let mut res = SolverResult::Missing;
72 for expression in group {
73 match solve_expression(expression, identifiers, document) {
74 SolverResult::True => return SolverResult::True,
75 SolverResult::False => res = SolverResult::False,
76 SolverResult::Missing => {}
77 }
78 }
79 res
80 }
81 Expression::BooleanExpression(ref left, ref op, ref right) => {
82 match (&**left, op, &**right) {
84 (
85 Expression::Cast(left, ModSym::Str),
86 BoolSym::Equal,
87 Expression::Cast(right, ModSym::Str),
88 ) => {
89 let x = match document.find(left) {
90 Some(x) => x,
91 None => {
92 debug!("evaluating missing, no left hand side for {}", expression);
93 return SolverResult::Missing;
94 }
95 };
96 let x = match x.to_string() {
97 Some(v) => v,
98 None => {
99 debug!(
100 "evaluating false, could not cast left field to string for {}",
101 expression
102 );
103 return SolverResult::False;
104 }
105 };
106 let y = match document.find(right) {
107 Some(x) => x,
108 None => {
109 debug!("evaluating missing, no right hand side for {}", expression);
110 return SolverResult::Missing;
111 }
112 };
113 let y = match y.to_string() {
114 Some(v) => v,
115 None => {
116 debug!(
117 "evaluating false, could not cast right field to string for {}",
118 expression
119 );
120 return SolverResult::False;
121 }
122 };
123 if x == y {
124 return SolverResult::True;
125 } else {
126 return SolverResult::False;
127 }
128 }
129 (Expression::Field(left), BoolSym::Equal, Expression::Boolean(b)) => {
130 let x = match document.find(left) {
131 Some(x) => x,
132 None => {
133 debug!("evaluating missing, no left hand side for {}", expression);
134 return SolverResult::Missing;
135 }
136 };
137 let x = match x.as_bool() {
138 Some(v) => v,
139 None => {
140 debug!(
141 "evaluating false, could not cast left field to boolean for {}",
142 expression
143 );
144 return SolverResult::False;
145 }
146 };
147 if x == *b {
148 return SolverResult::True;
149 } else {
150 return SolverResult::False;
151 }
152 }
153 (Expression::Field(left), BoolSym::Equal, Expression::Null) => {
154 let x = match document.find(left) {
155 Some(x) => x,
156 None => {
157 debug!("evaluating missing, no left hand side for {}", expression);
158 return SolverResult::Missing;
159 }
160 };
161 if x.is_null() {
162 return SolverResult::True;
163 } else {
164 return SolverResult::False;
165 }
166 }
167 _ => {}
168 }
169 match *op {
171 BoolSym::Equal
172 | BoolSym::GreaterThan
173 | BoolSym::GreaterThanOrEqual
174 | BoolSym::LessThan
175 | BoolSym::LessThanOrEqual => {
176 let x = match left.as_ref() {
177 Expression::Field(f) => {
178 let i = match document.find(f) {
179 Some(i) => i,
180 None => {
181 debug!(
182 "evaluating missing, no left hand side for {}",
183 expression
184 );
185 return SolverResult::Missing;
186 }
187 };
188 match i {
189 Value::Float(_) | Value::Int(_) | Value::UInt(_) => i,
190 _ => {
191 debug!(
192 "evaluating false, no left hand side for {}",
193 expression
194 );
195 return SolverResult::False;
196 }
197 }
198 }
199 Expression::Cast(field, ModSym::Flt) => {
200 let i = match document.find(field) {
201 Some(i) => i,
202 None => {
203 debug!(
204 "evaluating missing, no left hand side for {}",
205 expression
206 );
207 return SolverResult::Missing;
208 }
209 };
210 match i {
211 Value::Bool(x) => {
212 if x {
213 Value::Float(1.0)
214 } else {
215 Value::Float(0.0)
216 }
217 }
218 Value::Float(x) => Value::Float(x),
219 Value::Int(x) => {
220 if x <= f64::MAX as i64 {
221 Value::Float(x as f64)
222 } else {
223 debug!(
224 "evaluating false, could not cast left hand side for {} - {}",
225 expression, x
226 );
227 return SolverResult::False;
228 }
229 }
230 Value::String(x) => match x.parse::<f64>() {
231 Ok(i) => Value::Float(i),
232 Err(e) => {
233 debug!(
234 "evaluating false, could not cast left hand side for {} - {}",
235 expression, e
236 );
237 return SolverResult::False;
238 }
239 },
240 Value::UInt(x) => {
241 if x <= f64::MAX as u64 {
242 Value::Float(x as f64)
243 } else {
244 debug!(
245 "evaluating false, could not cast left hand side for {} - {}",
246 expression, x
247 );
248 return SolverResult::False;
249 }
250 }
251 _ => {
252 debug!(
253 "evaluating false, invalid type on left hand side for {}",
254 expression
255 );
256 return SolverResult::False;
257 }
258 }
259 }
260 Expression::Cast(field, ModSym::Int) => {
261 let i = match document.find(field) {
262 Some(i) => i,
263 None => {
264 debug!(
265 "evaluating missing, no left hand side for {}",
266 expression
267 );
268 return SolverResult::Missing;
269 }
270 };
271 match i {
272 Value::Bool(x) => {
273 if x {
274 Value::Int(1)
275 } else {
276 Value::Int(0)
277 }
278 }
279 Value::Float(x) => Value::Int(x.round() as i64),
280 Value::Int(x) => Value::Int(x),
281 Value::String(x) => match x.parse::<i64>() {
282 Ok(i) => Value::Int(i),
283 Err(e) => {
284 debug!(
285 "evaluating false, could not cast left hand side for {} - {}",
286 expression, e
287 );
288 return SolverResult::False;
289 }
290 },
291 Value::UInt(x) => {
292 if x <= i64::MAX as u64 {
293 Value::Int(x as i64)
294 } else {
295 debug!(
296 "evaluating false, could not cast left hand side for {} - {}",
297 expression, x
298 );
299 return SolverResult::False;
300 }
301 }
302 _ => {
303 debug!(
304 "evaluating false, invalid type on left hand side for {}",
305 expression
306 );
307 return SolverResult::False;
308 }
309 }
310 }
311 Expression::Boolean(i) => Value::Bool(*i),
312 Expression::Float(i) => Value::Float(*i),
313 Expression::Integer(i) => Value::Int(*i),
314 _ => {
315 debug!("encountered invalid left hand side for {}", expression);
316 return SolverResult::False;
317 }
318 };
319 let y = match right.as_ref() {
320 Expression::Field(f) => {
321 let i = match document.find(f) {
322 Some(i) => i,
323 None => {
324 debug!(
325 "evaluating missing, no right hand side for {}",
326 expression
327 );
328 return SolverResult::Missing;
329 }
330 };
331 match i {
332 Value::Float(_) | Value::Int(_) | Value::UInt(_) => i,
333 _ => {
334 debug!(
335 "evaluating false, no right hand side for {}",
336 expression
337 );
338 return SolverResult::False;
339 }
340 }
341 }
342 Expression::Cast(field, ModSym::Flt) => {
343 let i = match document.find(field) {
344 Some(i) => i,
345 None => {
346 debug!(
347 "evaluating missing, no right hand side for {}",
348 expression
349 );
350 return SolverResult::Missing;
351 }
352 };
353 match i {
354 Value::Bool(x) => {
355 if x {
356 Value::Float(1.0)
357 } else {
358 Value::Float(0.0)
359 }
360 }
361 Value::Float(x) => Value::Float(x),
362 Value::Int(x) => {
363 if x <= f64::MAX as i64 {
364 Value::Float(x as f64)
365 } else {
366 debug!(
367 "evaluating false, could not cast right hand side for {} - {}",
368 expression, x
369 );
370 return SolverResult::False;
371 }
372 }
373 Value::String(x) => match x.parse::<f64>() {
374 Ok(i) => Value::Float(i),
375 Err(e) => {
376 debug!(
377 "evaluating false, could not cast right hand side for {} - {}",
378 expression, e
379 );
380 return SolverResult::False;
381 }
382 },
383 Value::UInt(x) => {
384 if x <= f64::MAX as u64 {
385 Value::Float(x as f64)
386 } else {
387 debug!(
388 "evaluating false, could not cast right hand side for {} - {}",
389 expression, x
390 );
391 return SolverResult::False;
392 }
393 }
394 _ => {
395 debug!(
396 "evaluating false, invalid type on right hand side for {}",
397 expression
398 );
399 return SolverResult::False;
400 }
401 }
402 }
403 Expression::Cast(field, ModSym::Int) => {
404 let i = match document.find(field) {
405 Some(i) => i,
406 None => {
407 debug!(
408 "evaluating missing, no right hand side for {}",
409 expression
410 );
411 return SolverResult::Missing;
412 }
413 };
414 match i {
415 Value::Bool(x) => {
416 if x {
417 Value::Int(1)
418 } else {
419 Value::Int(0)
420 }
421 }
422 Value::Float(x) => Value::Int(x.round() as i64),
423 Value::Int(x) => Value::Int(x),
424 Value::String(x) => match x.parse::<i64>() {
425 Ok(i) => Value::Int(i),
426 Err(e) => {
427 debug!(
428 "evaluating false, could not cast right hand side for {} - {}",
429 expression, e
430 );
431 return SolverResult::False;
432 }
433 },
434 Value::UInt(x) => {
435 if x <= i64::MAX as u64 {
436 Value::Int(x as i64)
437 } else {
438 debug!(
439 "evaluating false, could not cast right hand side for {} - {}",
440 expression, x
441 );
442 return SolverResult::False;
443 }
444 }
445 _ => {
446 debug!(
447 "evaluating false, invalid type on right hand side for {}",
448 expression
449 );
450 return SolverResult::False;
451 }
452 }
453 }
454 Expression::Boolean(i) => Value::Bool(*i),
455 Expression::Float(i) => Value::Float(*i),
456 Expression::Integer(i) => Value::Int(*i),
457 _ => {
458 debug!("encountered invalid right hand side for {}", expression);
459 return SolverResult::False;
460 }
461 };
462 let res = match (x, *op, y) {
463 (Value::Bool(x), BoolSym::Equal, Value::Bool(y)) => x == y,
464 (Value::Float(x), BoolSym::Equal, Value::Float(y)) => x == y,
465 (Value::Int(x), BoolSym::Equal, Value::Int(y)) => x == y,
466 (Value::UInt(x), BoolSym::Equal, Value::UInt(y)) => x == y,
467 (Value::UInt(x), BoolSym::Equal, Value::Int(y)) if x <= i64::MAX as u64 => {
468 x as i64 == y
469 }
470 (Value::Int(x), BoolSym::Equal, Value::UInt(y)) if y <= i64::MAX as u64 => {
471 x == y as i64
472 }
473 (_, BoolSym::Equal, _) => false,
474 (Value::Float(x), BoolSym::GreaterThan, Value::Float(y)) => x > y,
475 (Value::Int(x), BoolSym::GreaterThan, Value::Int(y)) => x > y,
476 (Value::UInt(x), BoolSym::GreaterThan, Value::UInt(y)) => x > y,
477 (Value::UInt(x), BoolSym::GreaterThan, Value::Int(y))
478 if x <= i64::MAX as u64 =>
479 {
480 x as i64 > y
481 }
482 (Value::Int(x), BoolSym::GreaterThan, Value::UInt(y))
483 if y <= i64::MAX as u64 =>
484 {
485 x > y as i64
486 }
487 (_, BoolSym::GreaterThan, _) => false,
488 (Value::Float(x), BoolSym::GreaterThanOrEqual, Value::Float(y)) => x >= y,
489 (Value::Int(x), BoolSym::GreaterThanOrEqual, Value::Int(y)) => x >= y,
490 (Value::UInt(x), BoolSym::GreaterThanOrEqual, Value::UInt(y)) => x >= y,
491 (Value::UInt(x), BoolSym::GreaterThanOrEqual, Value::Int(y))
492 if x <= i64::MAX as u64 =>
493 {
494 x as i64 >= y
495 }
496 (Value::Int(x), BoolSym::GreaterThanOrEqual, Value::UInt(y))
497 if y <= i64::MAX as u64 =>
498 {
499 x >= y as i64
500 }
501 (_, BoolSym::GreaterThanOrEqual, _) => false,
502 (Value::Float(x), BoolSym::LessThan, Value::Float(y)) => x < y,
503 (Value::Int(x), BoolSym::LessThan, Value::Int(y)) => x < y,
504 (Value::UInt(x), BoolSym::LessThan, Value::UInt(y)) => x < y,
505 (Value::UInt(x), BoolSym::LessThan, Value::Int(y))
506 if x <= i64::MAX as u64 =>
507 {
508 (x as i64) < y
509 }
510 (Value::Int(x), BoolSym::LessThan, Value::UInt(y))
511 if y <= i64::MAX as u64 =>
512 {
513 x < y as i64
514 }
515 (_, BoolSym::LessThan, _) => false,
516 (Value::Float(x), BoolSym::LessThanOrEqual, Value::Float(y)) => x <= y,
517 (Value::Int(x), BoolSym::LessThanOrEqual, Value::Int(y)) => x <= y,
518 (Value::UInt(x), BoolSym::LessThanOrEqual, Value::UInt(y)) => x <= y,
519 (Value::UInt(x), BoolSym::LessThanOrEqual, Value::Int(y))
520 if x <= i64::MAX as u64 =>
521 {
522 x as i64 <= y
523 }
524 (Value::Int(x), BoolSym::LessThanOrEqual, Value::UInt(y))
525 if y <= i64::MAX as u64 =>
526 {
527 x <= y as i64
528 }
529 (_, BoolSym::LessThanOrEqual, _) => false,
530 _ => unreachable!(),
531 };
532 match res {
533 true => SolverResult::True,
534 _ => SolverResult::False,
535 }
536 }
537 BoolSym::And => {
538 let x = match solve_expression(left, identifiers, document) {
539 SolverResult::True => (true, false),
540 SolverResult::False => return SolverResult::False,
541 SolverResult::Missing => return SolverResult::Missing,
542 };
543 let y = match solve_expression(right, identifiers, document) {
544 SolverResult::True => (true, false),
545 SolverResult::False => (false, false),
546 SolverResult::Missing => (false, true),
547 };
548 debug!(
549 "evaluating {} ({}) for {}",
550 x.0 && y.0,
551 x.1 || y.1,
552 expression
553 );
554 if x.1 || y.1 {
555 SolverResult::Missing
556 } else if x.0 && y.0 {
557 SolverResult::True
558 } else {
559 SolverResult::False
560 }
561 }
562 BoolSym::Or => {
563 let x = match solve_expression(left, identifiers, document) {
564 SolverResult::True => return SolverResult::True,
565 SolverResult::False => (false, false),
566 SolverResult::Missing => (false, true),
567 };
568 let y = match solve_expression(right, identifiers, document) {
569 SolverResult::True => (true, false),
570 SolverResult::False => (false, false),
571 SolverResult::Missing => (false, true),
572 };
573 debug!(
574 "evaluating {} ({}) for {}",
575 x.0 || y.0,
576 x.1 || y.1,
577 expression
578 );
579 if x.0 || y.0 {
580 SolverResult::True
581 } else if x.1 && y.1 {
582 SolverResult::Missing
583 } else {
584 SolverResult::False
585 }
586 }
587 }
588 }
589 Expression::Identifier(ref i) => match identifiers.get(i) {
590 Some(e) => solve_expression(e, identifiers, document),
591 None => unreachable!(),
592 },
593 Expression::Match(Match::All, ref e) => {
594 let (_, group) = match **e {
595 Expression::Identifier(ref i) => match identifiers.get(i) {
596 Some(Expression::BooleanGroup(o, g)) => (o, g),
597 Some(e) => return match_all(e, identifiers, document),
598 _ => unreachable!(),
599 },
600 Expression::BooleanGroup(ref o, ref g) => (o, g),
601 _ => return match_all(e, identifiers, document),
602 };
603 for expression in group {
604 match solve_expression(expression, identifiers, document) {
605 SolverResult::True => {}
606 SolverResult::False => return SolverResult::False,
607 SolverResult::Missing => return SolverResult::Missing,
608 }
609 }
610 SolverResult::True
611 }
612 Expression::Match(Match::Of(c), ref e) => {
613 let (_, group) = match **e {
614 Expression::Identifier(ref identifier) => match identifiers.get(identifier) {
615 Some(Expression::BooleanGroup(o, g)) => (o, g),
616 Some(e) => return match_of(e, identifiers, document, c),
617 _ => {
618 unreachable!();
619 }
620 },
621 Expression::BooleanGroup(ref o, ref g) => (o, g),
622 _ => return match_of(e, identifiers, document, c),
623 };
624 let mut count = 0;
625 let mut res = SolverResult::Missing;
626 for expression in group {
627 if c == 0 {
628 match solve_expression(expression, identifiers, document) {
629 SolverResult::True => return SolverResult::False,
630 SolverResult::False => {
631 res = SolverResult::True;
632 }
633 SolverResult::Missing => {}
634 }
635 } else {
636 match solve_expression(expression, identifiers, document) {
637 SolverResult::True => {
638 count += 1;
639 if count >= c {
640 return SolverResult::True;
641 }
642 }
643 SolverResult::False => res = SolverResult::False,
644 SolverResult::Missing => {}
645 }
646 }
647 }
648 res
649 }
650 Expression::Matrix(ref columns, ref rows) => {
651 let size = columns.len();
656 let mut cache: Vec<Option<Value>> = Vec::with_capacity(size);
657 for _ in 0..size {
658 cache.push(None);
659 }
660
661 let mut res = SolverResult::Missing;
662 for row in rows {
663 let mut hit = SolverResult::True;
664 for (i, expression) in row.iter().enumerate() {
665 if let Some(expression) = expression {
666 if cache[i].is_none() {
667 let value = match document.find(&columns[i]) {
668 Some(v) => v,
669 None => {
670 debug!(
671 "evaluating missing, field not found for {}",
672 expression
673 );
674 hit = SolverResult::Missing;
675 break;
676 }
677 };
678 let _ = std::mem::replace(&mut cache[i], Some(value));
679 }
680 match solve_expression(expression, identifiers, &Cache(&cache)) {
681 SolverResult::True => {}
682 SolverResult::False => {
683 hit = SolverResult::False;
684 break;
685 }
686 SolverResult::Missing => {
687 hit = SolverResult::Missing;
688 break;
689 }
690 }
691 }
692 }
693 match hit {
694 SolverResult::True => return SolverResult::True,
695 SolverResult::False => res = SolverResult::False,
696 SolverResult::Missing => {}
697 }
698 }
699 res
700 }
701 Expression::Negate(ref e) => {
702 let res = match solve_expression(e.as_ref(), identifiers, document) {
703 SolverResult::True => SolverResult::False,
704 SolverResult::False => SolverResult::True,
705 SolverResult::Missing => SolverResult::False,
706 };
707 debug!("evaluating {} for {}", res, expression);
708 res
709 }
710 Expression::Nested(ref s, ref e) => {
711 let value = match document.find(s) {
712 Some(v) => v,
713 None => {
714 debug!("evaluating missing, field not found for {}", expression);
715 return SolverResult::Missing;
716 }
717 };
718 match value {
719 Value::Object(o) => solve_expression(e, identifiers, &o),
720 Value::Array(a) => {
721 if let Expression::Match(Match::All, expression) = &**e {
722 if let Expression::BooleanGroup(BoolSym::Or, expressions) = &**expression {
723 for expression in expressions {
724 let mut res = SolverResult::Missing;
725 for v in a.iter() {
726 if let Some(x) = v.as_object() {
727 match solve_expression(expression, identifiers, &x) {
728 SolverResult::True => {
729 res = SolverResult::True;
730 break;
731 }
732 SolverResult::False => res = SolverResult::False,
733 SolverResult::Missing => {}
734 }
735 }
736 }
737 if res != SolverResult::True {
738 return res;
739 }
740 }
741 return SolverResult::True;
742 } else if let Expression::Matrix(columns, rows) = &**expression {
743 for row in rows {
747 let mut res = SolverResult::Missing;
748 for v in a.iter() {
749 let mut hit = SolverResult::True;
750 for (i, expression) in row.iter().enumerate() {
751 if let Some(expression) = expression {
752 if let Some(x) = v.as_object() {
753 let value = x.find(&columns[i]);
754 match solve_expression(
755 expression,
756 identifiers,
757 &Passthrough(value),
758 ) {
759 SolverResult::True => {}
760 SolverResult::False => {
761 hit = SolverResult::False;
762 break;
763 }
764 SolverResult::Missing => {
765 hit = SolverResult::Missing;
766 break;
767 }
768 }
769 }
770 }
771 }
772 if hit == SolverResult::True {
773 res = SolverResult::True;
774 break;
775 }
776 }
777 if res != SolverResult::True {
778 return res;
779 }
780 }
781 return SolverResult::True;
782 }
783 }
784 for v in a.iter() {
785 if let Some(x) = v.as_object() {
786 if solve_expression(e, identifiers, &x) == SolverResult::True {
787 return SolverResult::True;
788 }
789 }
790 }
791 SolverResult::False
792 }
793 _ => {
794 debug!(
795 "evaluating false, field is not an array of objects or object for {}",
796 expression
797 );
798 SolverResult::False
799 }
800 }
801 }
802 Expression::Search(ref s, ref f, ref c) => {
803 let value = match document.find(f) {
804 Some(v) => v,
805 None => {
806 debug!("evaluating missing, field not found for {}", expression);
807 return SolverResult::Missing;
808 }
809 };
810 let res = match (value, c) {
811 (Value::String(ref x), _) => search(s, x),
812 (Value::Array(a), _) => {
813 let mut res = SolverResult::False;
814 for v in a.iter() {
815 if let Some(x) = v.as_str() {
816 if search(s, x) == SolverResult::True {
817 res = SolverResult::True;
818 break;
819 }
820 } else if *c {
821 let x = match v {
822 Value::Bool(x) => x.to_string(),
823 Value::Float(x) => x.to_string(),
824 Value::Int(x) => x.to_string(),
825 Value::UInt(x) => x.to_string(),
826 _ => continue,
827 };
828 if search(s, x.as_str()) == SolverResult::True {
829 res = SolverResult::True;
830 break;
831 }
832 }
833 }
834 res
835 }
836 (Value::Bool(x), true) => {
837 let x = x.to_string();
838 search(s, x.as_str())
839 }
840 (Value::Float(x), true) => {
841 let x = x.to_string();
842 search(s, x.as_str())
843 }
844 (Value::Int(x), true) => {
845 let x = x.to_string();
846 search(s, x.as_str())
847 }
848 (Value::UInt(x), true) => {
849 let x = x.to_string();
850 search(s, x.as_str())
851 }
852 _ => {
853 debug!(
854 "evaluating false, field is not an array of strings, or a string for {}",
855 expression
856 );
857 return SolverResult::Missing;
858 }
859 };
860 debug!("evaluating {} for {}", res, expression);
861 res
862 }
863 Expression::BooleanGroup(_, _)
864 | Expression::Boolean(_)
865 | Expression::Cast(_, _)
866 | Expression::Field(_)
867 | Expression::Float(_)
868 | Expression::Integer(_)
869 | Expression::Null => unreachable!(),
870 }
871}
872
873#[inline]
874fn match_all(
875 expression: &Expression,
876 identifiers: &HashMap<String, Expression>,
877 document: &dyn Document,
878) -> SolverResult {
879 if let Expression::Search(Search::AhoCorasick(a, m, _), i, c) = expression {
880 let value = match document.find(i) {
881 Some(v) => v,
882 None => {
883 debug!("evaluating missing, field not found for {}", expression);
884 return SolverResult::Missing;
885 }
886 };
887 match (value, c) {
888 (Value::String(ref x), _) => {
889 if slow_aho(a, m, x) != m.len() as u64 {
890 return SolverResult::False;
891 }
892 }
893 (Value::Array(x), _) => {
894 let mut found = false;
895 for v in x.iter() {
896 if let Some(x) = v.as_str() {
897 if slow_aho(a, m, x) == m.len() as u64 {
898 found = true;
899 break;
900 }
901 } else if *c {
902 let x = match v {
903 Value::Bool(x) => x.to_string(),
904 Value::Float(x) => x.to_string(),
905 Value::Int(x) => x.to_string(),
906 Value::UInt(x) => x.to_string(),
907 _ => continue,
908 };
909 if slow_aho(a, m, x.as_str()) == m.len() as u64 {
910 found = true;
911 break;
912 }
913 }
914 }
915 if !found {
916 return SolverResult::False;
917 }
918 }
919 (Value::Bool(x), true) => {
920 let x = x.to_string();
921 if slow_aho(a, m, x.as_str()) != m.len() as u64 {
922 return SolverResult::False;
923 }
924 }
925 (Value::Float(x), true) => {
926 let x = x.to_string();
927 if slow_aho(a, m, x.as_str()) != m.len() as u64 {
928 return SolverResult::False;
929 }
930 }
931 (Value::Int(x), true) => {
932 let x = x.to_string();
933 if slow_aho(a, m, x.as_str()) != m.len() as u64 {
934 return SolverResult::False;
935 }
936 }
937 (Value::UInt(x), true) => {
938 let x = x.to_string();
939 if slow_aho(a, m, x.as_str()) != m.len() as u64 {
940 return SolverResult::False;
941 }
942 }
943 (_, _) => {
944 debug!(
945 "evaluating false, field is not an array of strings, or a string for {}",
946 expression
947 );
948 return SolverResult::Missing;
949 }
950 }
951 } else if let Expression::Search(Search::RegexSet(s, _), i, c) = expression {
952 let value = match document.find(i) {
953 Some(v) => v,
954 None => {
955 debug!("evaluating missing, field not found for {}", expression);
956 return SolverResult::Missing;
957 }
958 };
959 match (value, c) {
960 (Value::String(ref x), _) => {
961 let mut hits = 0;
962 for _ in s.matches(x).iter() {
963 hits += 1;
964 }
965 if hits != s.patterns().len() {
966 return SolverResult::False;
967 }
968 }
969 (Value::Array(x), _) => {
970 let mut found = false;
971 for v in x.iter() {
972 if let Some(x) = v.as_str() {
973 let mut hits = 0;
974 for _ in s.matches(x).iter() {
975 hits += 1;
976 }
977 if hits == s.patterns().len() {
978 found = true;
979 break;
980 }
981 } else if *c {
982 let x = match v {
983 Value::Bool(x) => x.to_string(),
984 Value::Float(x) => x.to_string(),
985 Value::Int(x) => x.to_string(),
986 Value::UInt(x) => x.to_string(),
987 _ => continue,
988 };
989 let mut hits = 0;
990 for _ in s.matches(x.as_str()).iter() {
991 hits += 1;
992 }
993 if hits == s.patterns().len() {
994 found = true;
995 break;
996 }
997 }
998 }
999 if !found {
1000 return SolverResult::False;
1001 }
1002 }
1003 (Value::Bool(x), true) => {
1004 let x = x.to_string();
1005 let mut hits = 0;
1006 for _ in s.matches(x.as_str()).iter() {
1007 hits += 1;
1008 }
1009 if hits != s.patterns().len() {
1010 return SolverResult::False;
1011 }
1012 }
1013 (Value::Float(x), true) => {
1014 let x = x.to_string();
1015 let mut hits = 0;
1016 for _ in s.matches(x.as_str()).iter() {
1017 hits += 1;
1018 }
1019 if hits != s.patterns().len() {
1020 return SolverResult::False;
1021 }
1022 }
1023 (Value::Int(x), true) => {
1024 let x = x.to_string();
1025 let mut hits = 0;
1026 for _ in s.matches(x.as_str()).iter() {
1027 hits += 1;
1028 }
1029 if hits != s.patterns().len() {
1030 return SolverResult::False;
1031 }
1032 }
1033 (Value::UInt(x), true) => {
1034 let x = x.to_string();
1035 let mut hits = 0;
1036 for _ in s.matches(x.as_str()).iter() {
1037 hits += 1;
1038 }
1039 if hits != s.patterns().len() {
1040 return SolverResult::False;
1041 }
1042 }
1043 _ => {
1044 debug!(
1045 "evaluating false, field is not an array of strings, or a string for {}",
1046 expression
1047 );
1048 return SolverResult::Missing;
1049 }
1050 }
1051 } else if let Expression::Matrix(columns, rows) = expression {
1052 let size = columns.len();
1057 let mut cache: Vec<Option<Value>> = Vec::with_capacity(size);
1058 for _ in 0..size {
1059 cache.push(None);
1060 }
1061 for row in rows {
1062 let mut hit = SolverResult::True;
1063 for (i, expression) in row.iter().enumerate() {
1064 if let Some(expression) = expression {
1065 if cache[i].is_none() {
1066 let value = match document.find(&columns[i]) {
1067 Some(v) => v,
1068 None => {
1069 debug!("evaluating missing, field not found for {}", expression);
1070 hit = SolverResult::Missing;
1071 break;
1072 }
1073 };
1074 let _ = std::mem::replace(&mut cache[i], Some(value));
1075 }
1076 match solve_expression(expression, identifiers, &Cache(&cache)) {
1077 SolverResult::True => {}
1078 SolverResult::False => {
1079 hit = SolverResult::False;
1080 break;
1081 }
1082 SolverResult::Missing => {
1083 hit = SolverResult::Missing;
1084 break;
1085 }
1086 }
1087 }
1088 }
1089 match hit {
1090 SolverResult::True => {}
1091 SolverResult::False => return SolverResult::False,
1092 SolverResult::Missing => return SolverResult::Missing,
1093 }
1094 }
1095 } else {
1096 return solve_expression(expression, identifiers, document);
1097 }
1098 SolverResult::True
1099}
1100
1101#[inline]
1102fn match_of(
1103 expression: &Expression,
1104 identifiers: &HashMap<String, Expression>,
1105 document: &dyn Document,
1106 count: u64,
1107) -> SolverResult {
1108 if count == 0 {
1109 return match solve_expression(expression, identifiers, document) {
1110 SolverResult::True => SolverResult::False,
1111 SolverResult::False => SolverResult::True,
1112 SolverResult::Missing => return SolverResult::Missing,
1113 };
1114 } else if let Expression::Search(Search::AhoCorasick(a, m, _), i, cast) = expression {
1115 let value = match document.find(i) {
1116 Some(v) => v,
1117 None => {
1118 debug!("evaluating missing, field not found for {}", expression);
1119 return SolverResult::Missing;
1120 }
1121 };
1122 match (value, cast) {
1123 (Value::String(ref x), _) => {
1124 let c = slow_aho(a, m, x);
1125 if c >= count {
1126 return SolverResult::True;
1127 }
1128 }
1129 (Value::Array(x), _) => {
1130 for v in x.iter() {
1131 if let Some(x) = v.as_str() {
1132 let hits = slow_aho(a, m, x);
1133 if hits >= count {
1134 return SolverResult::True;
1135 }
1136 } else if *cast {
1137 let x = match v {
1138 Value::Bool(x) => x.to_string(),
1139 Value::Float(x) => x.to_string(),
1140 Value::Int(x) => x.to_string(),
1141 Value::UInt(x) => x.to_string(),
1142 _ => continue,
1143 };
1144 let hits = slow_aho(a, m, x.as_str());
1145 if hits >= count {
1146 return SolverResult::True;
1147 }
1148 }
1149 }
1150 }
1151 (Value::Bool(x), true) => {
1152 let x = x.to_string();
1153 let c = slow_aho(a, m, x.as_str());
1154 if c >= count {
1155 return SolverResult::True;
1156 }
1157 }
1158 (Value::Float(x), true) => {
1159 let x = x.to_string();
1160 let c = slow_aho(a, m, x.as_str());
1161 if c >= count {
1162 return SolverResult::True;
1163 }
1164 }
1165 (Value::Int(x), true) => {
1166 let x = x.to_string();
1167 let c = slow_aho(a, m, x.as_str());
1168 if c >= count {
1169 return SolverResult::True;
1170 }
1171 }
1172 (Value::UInt(x), true) => {
1173 let x = x.to_string();
1174 let c = slow_aho(a, m, x.as_str());
1175 if c >= count {
1176 return SolverResult::True;
1177 }
1178 }
1179 _ => {
1180 debug!(
1181 "evaluating false, field is not an array of strings, or a string for {}",
1182 expression
1183 );
1184 return SolverResult::Missing;
1185 }
1186 }
1187 } else if let Expression::Search(Search::RegexSet(s, _), i, cast) = expression {
1188 let value = match document.find(i) {
1189 Some(v) => v,
1190 None => {
1191 debug!("evaluating missing, field not found for {}", expression);
1192 return SolverResult::Missing;
1193 }
1194 };
1195 match (value, cast) {
1196 (Value::String(ref x), _) => {
1197 let mut c = 0;
1198 for _ in s.matches(x).iter() {
1199 c += 1;
1200 }
1201 if c >= count {
1202 return SolverResult::True;
1203 }
1204 }
1205 (Value::Array(x), _) => {
1206 for v in x.iter() {
1207 if let Some(x) = v.as_str() {
1208 let mut hits = 0;
1209 for _ in s.matches(x).iter() {
1210 hits += 1;
1211 }
1212 if hits >= count {
1213 return SolverResult::True;
1214 }
1215 } else if *cast {
1216 let x = match v {
1217 Value::Bool(x) => x.to_string(),
1218 Value::Float(x) => x.to_string(),
1219 Value::Int(x) => x.to_string(),
1220 Value::UInt(x) => x.to_string(),
1221 _ => continue,
1222 };
1223 let mut hits = 0;
1224 for _ in s.matches(x.as_str()).iter() {
1225 hits += 1;
1226 }
1227 if hits >= count {
1228 return SolverResult::True;
1229 }
1230 }
1231 }
1232 }
1233 (Value::Bool(x), true) => {
1234 let x = x.to_string();
1235 let mut c = 0;
1236 for _ in s.matches(x.as_str()).iter() {
1237 c += 1;
1238 }
1239 if c >= count {
1240 return SolverResult::True;
1241 }
1242 }
1243 (Value::Float(x), true) => {
1244 let x = x.to_string();
1245 let mut c = 0;
1246 for _ in s.matches(x.as_str()).iter() {
1247 c += 1;
1248 }
1249 if c >= count {
1250 return SolverResult::True;
1251 }
1252 }
1253 (Value::Int(x), true) => {
1254 let x = x.to_string();
1255 let mut c = 0;
1256 for _ in s.matches(x.as_str()).iter() {
1257 c += 1;
1258 }
1259 if c >= count {
1260 return SolverResult::True;
1261 }
1262 }
1263 (Value::UInt(x), true) => {
1264 let x = x.to_string();
1265 let mut c = 0;
1266 for _ in s.matches(x.as_str()).iter() {
1267 c += 1;
1268 }
1269 if c >= count {
1270 return SolverResult::True;
1271 }
1272 }
1273 _ => {
1274 debug!(
1275 "evaluating false, field is not an array of strings, or a string for {}",
1276 expression
1277 );
1278 return SolverResult::Missing;
1279 }
1280 }
1281 } else if let Expression::Matrix(columns, rows) = expression {
1282 let size = columns.len();
1287 let mut cache: Vec<Option<Value>> = Vec::with_capacity(size);
1288 for _ in 0..size {
1289 cache.push(None);
1290 }
1291 let mut hits = 0;
1292 let mut res = SolverResult::Missing;
1293 for row in rows {
1294 let mut hit = SolverResult::True;
1295 for (i, expression) in row.iter().enumerate() {
1296 if let Some(expression) = expression {
1297 if cache[i].is_none() {
1298 let value = match document.find(&columns[i]) {
1299 Some(v) => v,
1300 None => {
1301 debug!("evaluating missing, field not found for {}", expression);
1302 hit = SolverResult::Missing;
1303 break;
1304 }
1305 };
1306 let _ = std::mem::replace(&mut cache[i], Some(value));
1307 }
1308 match solve_expression(expression, identifiers, &Cache(&cache)) {
1309 SolverResult::True => {}
1310 SolverResult::False => {
1311 hit = SolverResult::False;
1312 break;
1313 }
1314 SolverResult::Missing => {
1315 hit = SolverResult::Missing;
1316 break;
1317 }
1318 }
1319 }
1320 }
1321 match hit {
1322 SolverResult::True => {
1323 hits += 1;
1324 if hits >= count {
1325 return SolverResult::True;
1326 }
1327 }
1328 SolverResult::False => res = SolverResult::False,
1329 SolverResult::Missing => {}
1330 }
1331 }
1332 return res;
1333 } else {
1334 return solve_expression(expression, identifiers, document);
1335 }
1336 SolverResult::False
1337}
1338
1339#[inline]
1340fn search(kind: &Search, value: &str) -> SolverResult {
1341 match kind {
1342 Search::Any => {
1343 return SolverResult::True;
1344 }
1345 Search::Exact(i) => {
1346 if i == value {
1347 return SolverResult::True;
1348 }
1349 }
1350 Search::Contains(i) => {
1351 if value.contains(i) {
1352 return SolverResult::True;
1353 }
1354 }
1355 Search::EndsWith(i) => {
1356 if value.ends_with(i) {
1357 return SolverResult::True;
1358 }
1359 }
1360 Search::StartsWith(i) => {
1361 if value.starts_with(i) {
1362 return SolverResult::True;
1363 }
1364 }
1365 Search::Regex(i, _) => {
1366 if i.is_match(value) {
1367 return SolverResult::True;
1368 }
1369 }
1370 Search::RegexSet(i, _) => {
1371 if i.is_match(value) {
1372 return SolverResult::True;
1373 }
1374 }
1375 Search::AhoCorasick(a, m, _) => {
1376 for i in a.find_overlapping_iter(value) {
1377 match m[i.pattern()] {
1378 MatchType::Contains(_) => return SolverResult::True,
1379 MatchType::EndsWith(_) => {
1380 if i.end() == value.len() {
1381 return SolverResult::True;
1382 }
1383 }
1384 MatchType::Exact(_) => {
1385 if i.start() == 0 && i.end() == value.len() {
1386 return SolverResult::True;
1387 }
1388 }
1389 MatchType::StartsWith(_) => {
1390 if i.start() == 0 {
1391 return SolverResult::True;
1392 }
1393 }
1394 }
1395 }
1396 return SolverResult::False;
1397 }
1398 }
1399 SolverResult::False
1400}
1401
1402#[inline]
1403fn slow_aho(a: &AhoCorasick, m: &[MatchType], value: &str) -> u64 {
1404 let len = m.len();
1406 if len < 64 {
1407 let mut map = 0;
1408 for i in a.find_overlapping_iter(value) {
1409 let p = i.pattern();
1410 match m[p] {
1411 MatchType::Contains(_) => {
1412 map |= 1 << p.as_u64();
1413 }
1414 MatchType::EndsWith(_) => {
1415 if i.end() == value.len() {
1416 map |= 1 << p.as_u64();
1417 }
1418 }
1419 MatchType::Exact(_) => {
1420 if i.start() == 0 && i.end() == value.len() {
1421 map |= 1 << p.as_u64();
1422 }
1423 }
1424 MatchType::StartsWith(_) => {
1425 if i.start() == 0 {
1426 map |= 1 << p.as_u64();
1427 }
1428 }
1429 }
1430 }
1431 let mut hits = 0;
1432 for i in 0..len {
1433 hits += (map >> i) & 0x1;
1434 }
1435 hits
1436 } else {
1437 let mut hits = std::collections::HashSet::with_capacity(len);
1438 for i in a.find_overlapping_iter(value) {
1439 let p = i.pattern();
1440 match m[p] {
1441 MatchType::Contains(_) => {
1442 hits.insert(p);
1443 }
1444 MatchType::EndsWith(_) => {
1445 if i.end() == value.len() {
1446 hits.insert(p);
1447 }
1448 }
1449 MatchType::Exact(_) => {
1450 if i.start() == 0 && i.end() == value.len() {
1451 hits.insert(p);
1452 }
1453 }
1454 MatchType::StartsWith(_) => {
1455 if i.start() == 0 {
1456 hits.insert(p);
1457 }
1458 }
1459 }
1460 }
1461 hits.len() as u64
1462 }
1463}