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
20 .patterns()
21 .iter()
22 .all(|pattern| pattern.matches(haystack))
23 {
24 vec![vec![haystack.clone()]]
25 } else {
26 vec![]
27 }
28 }
29
30 fn paths_with_captures(
31 &self,
32 haystack: &CBOR,
33 ) -> (Vec<Path>, std::collections::HashMap<String, Vec<Path>>) {
34 let mut all_captures = std::collections::HashMap::new();
36
37 for pattern in self.patterns() {
38 let (paths, captures) = pattern.paths_with_captures(haystack);
39 if paths.is_empty() {
40 return (vec![], std::collections::HashMap::new());
42 }
43
44 for (name, capture_paths) in captures {
46 all_captures
47 .entry(name)
48 .or_insert_with(Vec::new)
49 .extend(capture_paths);
50 }
51 }
52
53 (vec![vec![haystack.clone()]], all_captures)
55 }
56
57 fn compile(
59 &self,
60 code: &mut Vec<Instr>,
61 lits: &mut Vec<Pattern>,
62 captures: &mut Vec<String>,
63 ) {
64 for pattern in self.patterns() {
66 pattern.compile(code, lits, captures);
67 }
68 }
69
70 fn collect_capture_names(&self, names: &mut Vec<String>) {
71 for pattern in self.patterns() {
73 pattern.collect_capture_names(names);
74 }
75 }
76
77 fn is_complex(&self) -> bool {
78 self.patterns().len() > 1
81 || self.patterns().iter().any(|p| p.is_complex())
82 }
83}
84
85impl std::fmt::Display for AndPattern {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 write!(
88 f,
89 "{}",
90 self.patterns()
91 .iter()
92 .map(|p| p.to_string())
93 .collect::<Vec<_>>()
94 .join(" & ")
95 )
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_and_pattern_display() {
105 let pattern1 = Pattern::number_greater_than(5);
106 let pattern2 = Pattern::number_less_than(10);
107 let and_pattern = AndPattern::new(vec![pattern1, pattern2]);
108 assert_eq!(and_pattern.to_string(), ">5 & <10");
109 }
110
111 #[test]
112 fn test_and_pattern_matches_when_all_patterns_match() {
113 let pattern = AndPattern::new(vec![
114 Pattern::number_greater_than(5),
115 Pattern::number_less_than(10),
116 ]);
117
118 let cbor_7 = CBOR::from(7);
119 assert!(pattern.matches(&cbor_7));
120 }
121
122 #[test]
123 fn test_and_pattern_fails_when_any_pattern_fails() {
124 let pattern = AndPattern::new(vec![
125 Pattern::number_greater_than(5),
126 Pattern::number_less_than(10),
127 ]);
128
129 let cbor_12 = CBOR::from(12); assert!(!pattern.matches(&cbor_12));
131
132 let cbor_3 = CBOR::from(3); assert!(!pattern.matches(&cbor_3));
134 }
135
136 #[test]
137 fn test_and_pattern_empty_returns_true() {
138 let pattern = AndPattern::new(vec![]);
139 let cbor = CBOR::from("any value");
140 assert!(pattern.matches(&cbor));
141 }
142}