vrl/datadog/filter/
matcher.rs1use std::{fmt, marker::PhantomData};
2
3use super::{BooleanType, Filter, QueryNode, Resolver};
4use crate::path::PathParseError;
5use dyn_clone::{DynClone, clone_trait_object};
6
7pub trait Matcher<V>: DynClone + fmt::Debug + Send + Sync {
10 fn run(&self, value: &V) -> bool;
11}
12
13clone_trait_object!(<V>Matcher<V>);
14
15impl<V> Matcher<V> for bool {
17 fn run(&self, _value: &V) -> bool {
18 *self
19 }
20}
21
22#[derive(Clone)]
25pub struct Run<V, T>
26where
27 V: fmt::Debug + Send + Sync + Clone,
28 T: Fn(&V) -> bool + Send + Sync + Clone,
29{
30 func: T,
31 _phantom: PhantomData<V>, }
33
34impl<V, T> Run<V, T>
35where
36 V: fmt::Debug + Send + Sync + Clone,
37 T: Fn(&V) -> bool + Send + Sync + Clone,
38{
39 pub fn boxed(func: T) -> Box<Self> {
41 Box::new(Self {
42 func,
43 _phantom: PhantomData,
44 })
45 }
46}
47
48impl<V, T> Matcher<V> for Run<V, T>
49where
50 V: fmt::Debug + Send + Sync + Clone,
51 T: Fn(&V) -> bool + Send + Sync + Clone,
52{
53 fn run(&self, obj: &V) -> bool {
55 (self.func)(obj)
56 }
57}
58
59impl<V, T> fmt::Debug for Run<V, T>
60where
61 V: fmt::Debug + Send + Sync + Clone,
62 T: Fn(&V) -> bool + Send + Sync + Clone,
63{
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 write!(f, "Datadog matcher fn")
66 }
67}
68
69fn not<V>(matcher: Box<dyn Matcher<V>>) -> Box<dyn Matcher<V>>
71where
72 V: fmt::Debug + Send + Sync + Clone + 'static,
73{
74 Run::boxed(move |value| !matcher.run(value))
75}
76
77fn any<V>(matchers: Vec<Box<dyn Matcher<V>>>) -> Box<dyn Matcher<V>>
79where
80 V: fmt::Debug + Send + Sync + Clone + 'static,
81{
82 Run::boxed(move |value| matchers.iter().any(|func| func.run(value)))
83}
84
85fn all<V>(matchers: Vec<Box<dyn Matcher<V>>>) -> Box<dyn Matcher<V>>
87where
88 V: fmt::Debug + Send + Sync + Clone + 'static,
89{
90 Run::boxed(move |value| matchers.iter().all(|func| func.run(value)))
91}
92
93pub fn build_matcher<V, F>(
99 node: &QueryNode,
100 filter: &F,
101) -> Result<Box<dyn Matcher<V>>, PathParseError>
102where
103 V: fmt::Debug + Send + Sync + Clone + 'static,
104 F: Filter<V> + Resolver,
105{
106 node.build_matcher(filter)
107}
108
109impl QueryNode {
110 #[allow(clippy::module_name_repetitions)] pub fn build_matcher<V, F>(&self, filter: &F) -> Result<Box<dyn Matcher<V>>, PathParseError>
121 where
122 V: fmt::Debug + Send + Sync + Clone + 'static,
123 F: Filter<V> + Resolver,
124 {
125 match self {
126 Self::MatchNoDocs => Ok(Box::new(false)),
127 Self::MatchAllDocs => Ok(Box::new(true)),
128 Self::AttributeExists { attr } => {
129 let matchers: Result<Vec<_>, _> = filter
130 .build_fields(attr)
131 .into_iter()
132 .map(|field| filter.exists(field))
133 .collect();
134
135 Ok(any(matchers?))
136 }
137 Self::AttributeMissing { attr } => {
138 let matchers: Result<Vec<_>, _> = filter
139 .build_fields(attr)
140 .into_iter()
141 .map(|field| filter.exists(field).map(|matcher| not(matcher)))
142 .collect();
143
144 Ok(all(matchers?))
145 }
146 Self::AttributeTerm { attr, value }
147 | Self::QuotedAttribute {
148 attr,
149 phrase: value,
150 } => {
151 let matchers: Result<Vec<_>, _> = filter
152 .build_fields(attr)
153 .into_iter()
154 .map(|field| filter.equals(field, value))
155 .collect();
156
157 Ok(any(matchers?))
158 }
159 Self::AttributePrefix { attr, prefix } => {
160 let matchers: Result<Vec<_>, _> = filter
161 .build_fields(attr)
162 .into_iter()
163 .map(|field| filter.prefix(field, prefix))
164 .collect();
165
166 Ok(any(matchers?))
167 }
168 Self::AttributeWildcard { attr, wildcard } => {
169 let matchers: Result<Vec<_>, _> = filter
170 .build_fields(attr)
171 .into_iter()
172 .map(|field| filter.wildcard(field, wildcard))
173 .collect();
174
175 Ok(any(matchers?))
176 }
177 Self::AttributeComparison {
178 attr,
179 comparator,
180 value,
181 } => {
182 let matchers: Result<Vec<_>, _> = filter
183 .build_fields(attr)
184 .into_iter()
185 .map(|field| filter.compare(field, *comparator, value.clone()))
186 .collect();
187
188 Ok(any(matchers?))
189 }
190 Self::AttributeRange {
191 attr,
192 lower,
193 lower_inclusive,
194 upper,
195 upper_inclusive,
196 } => {
197 let matchers: Result<Vec<_>, _> = filter
198 .build_fields(attr)
199 .into_iter()
200 .map(|field| {
201 filter.range(
202 field,
203 lower.clone(),
204 *lower_inclusive,
205 upper.clone(),
206 *upper_inclusive,
207 )
208 })
209 .collect();
210
211 Ok(any(matchers?))
212 }
213 Self::NegatedNode { node } => Ok(not(node.build_matcher(filter)?)),
214 Self::Boolean { oper, nodes } => {
215 let funcs: Result<Vec<_>, _> = nodes
216 .iter()
217 .map(|node| node.build_matcher(filter))
218 .collect();
219
220 match oper {
221 BooleanType::And => Ok(all(funcs?)),
222 BooleanType::Or => Ok(any(funcs?)),
223 }
224 }
225 }
226 }
227}