grit_pattern_matcher/pattern/
every.rs

1use super::{
2    patterns::{Matcher, Pattern, PatternName},
3    resolved_pattern::ResolvedPattern,
4    State,
5};
6use crate::{constant::Constant, context::QueryContext};
7use grit_util::{error::GritResult, AnalysisLogs};
8
9#[derive(Debug, Clone)]
10pub struct Every<Q: QueryContext> {
11    pub pattern: Pattern<Q>,
12}
13
14impl<Q: QueryContext> Every<Q> {
15    pub fn new(pattern: Pattern<Q>) -> Self {
16        Self { pattern }
17    }
18}
19
20impl<Q: QueryContext> PatternName for Every<Q> {
21    fn name(&self) -> &'static str {
22        "EVERY"
23    }
24}
25
26impl<Q: QueryContext> Matcher<Q> for Every<Q> {
27    fn execute<'a>(
28        &'a self,
29        binding: &Q::ResolvedPattern<'a>,
30        init_state: &mut State<'a, Q>,
31        context: &'a Q::ExecContext<'a>,
32        logs: &mut AnalysisLogs,
33    ) -> GritResult<bool> {
34        // might be necessary to clone init state at the top,
35        // but more performant to not, so leaving out for now.
36        if let Some(items) = binding.get_list_binding_items() {
37            let pattern = &self.pattern;
38            for item in items {
39                if !pattern.execute(&item, init_state, context, logs)? {
40                    return Ok(false);
41                }
42            }
43            Ok(true)
44        } else if let Some(items) = binding.get_list_items() {
45            let pattern = &self.pattern;
46            for item in items {
47                if !pattern.execute(item, init_state, context, logs)? {
48                    return Ok(false);
49                }
50            }
51            Ok(true)
52        } else if let Some(map) = binding.get_map() {
53            let pattern = &self.pattern;
54            for (key, value) in map {
55                let key = Q::ResolvedPattern::from_constant(Constant::String(key.clone()));
56                let resolved =
57                    Q::ResolvedPattern::from_list_parts([key, value.clone()].into_iter());
58                if !pattern.execute(&resolved, init_state, context, logs)? {
59                    return Ok(false);
60                }
61            }
62            Ok(true)
63        } else {
64            Ok(false)
65        }
66    }
67}