dcbor_pattern/pattern/meta/
and_pattern.rs1use dcbor::prelude::*;
2
3use crate::pattern::{Matcher, Path, Pattern, vm::Instr};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct AndPattern(Vec<Pattern>);
8
9impl AndPattern {
10 pub fn new(patterns: Vec<Pattern>) -> Self { AndPattern(patterns) }
12
13 pub fn patterns(&self) -> &[Pattern] { &self.0 }
15}
16
17impl Matcher for AndPattern {
18 fn paths(&self, haystack: &CBOR) -> Vec<Path> {
19 if self.patterns().iter().all(|pattern| pattern.matches(haystack)) {
20 vec![vec![haystack.clone()]]
21 } else {
22 vec![]
23 }
24 }
25
26 fn paths_with_captures(
27 &self,
28 haystack: &CBOR,
29 ) -> (Vec<Path>, std::collections::HashMap<String, Vec<Path>>) {
30 let mut all_captures = std::collections::HashMap::new();
32
33 for pattern in self.patterns() {
34 let (paths, captures) = pattern.paths_with_captures(haystack);
35 if paths.is_empty() {
36 return (vec![], std::collections::HashMap::new());
38 }
39
40 for (name, capture_paths) in captures {
42 all_captures
43 .entry(name)
44 .or_insert_with(Vec::new)
45 .extend(capture_paths);
46 }
47 }
48
49 (vec![vec![haystack.clone()]], all_captures)
51 }
52
53 fn compile(
55 &self,
56 code: &mut Vec<Instr>,
57 lits: &mut Vec<Pattern>,
58 captures: &mut Vec<String>,
59 ) {
60 for pattern in self.patterns() {
62 pattern.compile(code, lits, captures);
63 }
64 }
65
66 fn collect_capture_names(&self, names: &mut Vec<String>) {
67 for pattern in self.patterns() {
69 pattern.collect_capture_names(names);
70 }
71 }
72
73 fn is_complex(&self) -> bool {
74 self.patterns().len() > 1
77 || self.patterns().iter().any(|p| p.is_complex())
78 }
79}
80
81impl std::fmt::Display for AndPattern {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 write!(
84 f,
85 "{}",
86 self.patterns()
87 .iter()
88 .map(|p| p.to_string())
89 .collect::<Vec<_>>()
90 .join(" & ")
91 )
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn test_and_pattern_display() {
101 let pattern1 = Pattern::number_greater_than(5);
102 let pattern2 = Pattern::number_less_than(10);
103 let and_pattern = AndPattern::new(vec![pattern1, pattern2]);
104 assert_eq!(and_pattern.to_string(), ">5 & <10");
105 }
106
107 #[test]
108 fn test_and_pattern_matches_when_all_patterns_match() {
109 let pattern = AndPattern::new(vec![
110 Pattern::number_greater_than(5),
111 Pattern::number_less_than(10),
112 ]);
113
114 let cbor_7 = CBOR::from(7);
115 assert!(pattern.matches(&cbor_7));
116 }
117
118 #[test]
119 fn test_and_pattern_fails_when_any_pattern_fails() {
120 let pattern = AndPattern::new(vec![
121 Pattern::number_greater_than(5),
122 Pattern::number_less_than(10),
123 ]);
124
125 let cbor_12 = CBOR::from(12); assert!(!pattern.matches(&cbor_12));
127
128 let cbor_3 = CBOR::from(3); assert!(!pattern.matches(&cbor_3));
130 }
131
132 #[test]
133 fn test_and_pattern_empty_returns_true() {
134 let pattern = AndPattern::new(vec![]);
135 let cbor = CBOR::from("any value");
136 assert!(pattern.matches(&cbor));
137 }
138}