use std::fmt::Debug;
use super::{Matcher, Run};
use crate::datadog::search::{Comparison, ComparisonValue, Field};
use crate::path::PathParseError;
use dyn_clone::{DynClone, clone_trait_object};
pub trait Filter<V: Debug + Send + Sync + Clone + 'static>: DynClone {
fn exists(&self, field: Field) -> Result<Box<dyn Matcher<V>>, PathParseError>;
fn equals(&self, field: Field, to_match: &str) -> Result<Box<dyn Matcher<V>>, PathParseError>;
fn prefix(&self, field: Field, prefix: &str) -> Result<Box<dyn Matcher<V>>, PathParseError>;
fn wildcard(&self, field: Field, wildcard: &str)
-> Result<Box<dyn Matcher<V>>, PathParseError>;
fn compare(
&self,
field: Field,
comparator: Comparison,
comparison_value: ComparisonValue,
) -> Result<Box<dyn Matcher<V>>, PathParseError>;
fn range(
&self,
field: Field,
lower: ComparisonValue,
lower_inclusive: bool,
upper: ComparisonValue,
upper_inclusive: bool,
) -> Result<Box<dyn Matcher<V>>, PathParseError> {
match (&lower, &upper) {
(ComparisonValue::Unbounded, ComparisonValue::Unbounded) => self.exists(field),
(ComparisonValue::Unbounded, _) => {
let op = if upper_inclusive {
Comparison::Lte
} else {
Comparison::Lt
};
self.compare(field, op, upper)
}
(_, ComparisonValue::Unbounded) => {
let op = if lower_inclusive {
Comparison::Gte
} else {
Comparison::Gt
};
self.compare(field, op, lower)
}
_ => {
let lower_op = if lower_inclusive {
Comparison::Gte
} else {
Comparison::Gt
};
let upper_op = if upper_inclusive {
Comparison::Lte
} else {
Comparison::Lt
};
let lower_func = self.compare(field.clone(), lower_op, lower)?;
let upper_func = self.compare(field, upper_op, upper)?;
Ok(Run::boxed(move |value| {
lower_func.run(value) && upper_func.run(value)
}))
}
}
}
}
clone_trait_object!(<V>Filter<V>);