grit_pattern_matcher/pattern/
map.rs

1use super::{
2    patterns::{Matcher, Pattern, PatternName},
3    resolved_pattern::ResolvedPattern,
4    state::State,
5};
6use crate::context::QueryContext;
7use grit_util::{error::GritResult, AnalysisLogs};
8use std::collections::BTreeMap;
9
10#[derive(Debug, Clone)]
11pub struct GritMap<Q: QueryContext> {
12    pub elements: BTreeMap<String, Pattern<Q>>,
13}
14
15impl<Q: QueryContext> GritMap<Q> {
16    pub fn new(elements: BTreeMap<String, Pattern<Q>>) -> Self {
17        Self { elements }
18    }
19
20    pub fn get(&self, key: &str) -> Option<&Pattern<Q>> {
21        self.elements.get(key)
22    }
23}
24
25impl<Q: QueryContext> PatternName for GritMap<Q> {
26    fn name(&self) -> &'static str {
27        "MAP"
28    }
29}
30
31impl<Q: QueryContext> Matcher<Q> for GritMap<Q> {
32    fn execute<'a>(
33        &'a self,
34        binding: &Q::ResolvedPattern<'a>,
35        state: &mut State<'a, Q>,
36        context: &'a Q::ExecContext<'a>,
37        logs: &mut AnalysisLogs,
38    ) -> GritResult<bool> {
39        let Some(map) = binding.get_map() else {
40            return Ok(false);
41        };
42
43        for element in map.iter() {
44            if let Some(pattern) = self.elements.get(element.0) {
45                if !pattern.execute(element.1, state, context, logs)? {
46                    return Ok(false);
47                }
48            } else {
49                return Ok(false);
50            }
51        }
52        for element in self.elements.iter() {
53            if !map.contains_key(element.0) {
54                return Ok(false);
55            }
56        }
57        Ok(true)
58    }
59}