use vantage_expressions::{Expression, Expressive, ExpressiveEnum};
#[derive(Clone)]
pub struct ConditionGroup<T> {
operator: &'static str,
operands: Vec<Expression<T>>,
}
impl<T> std::fmt::Debug for ConditionGroup<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ConditionGroup")
.field("operator", &self.operator)
.field("operands", &self.operands.len())
.finish()
}
}
impl<T: Clone> ConditionGroup<T> {
pub(crate) fn new(operator: &'static str, operands: Vec<Expression<T>>) -> Self {
Self { operator, operands }
}
pub fn or_(self, other: impl Expressive<T>) -> Self {
self.extend("OR", other.expr())
}
pub fn and_(self, other: impl Expressive<T>) -> Self {
self.extend("AND", other.expr())
}
fn extend(mut self, operator: &'static str, other: Expression<T>) -> Self {
if self.operator == operator {
self.operands.push(other);
self
} else {
Self::new(operator, vec![self.expr(), other])
}
}
}
impl<T: Clone> Expressive<T> for ConditionGroup<T> {
fn expr(&self) -> Expression<T> {
let separator = format!(" {} ", self.operator);
let template = std::iter::repeat_n("{}", self.operands.len())
.collect::<Vec<_>>()
.join(&separator);
Expression::new(
format!("({template})"),
self.operands
.iter()
.cloned()
.map(ExpressiveEnum::Nested)
.collect(),
)
}
}
pub fn or_<T: Clone>(lhs: impl Expressive<T>, rhs: impl Expressive<T>) -> ConditionGroup<T> {
ConditionGroup::new("OR", vec![lhs.expr(), rhs.expr()])
}
pub fn and_<T: Clone>(lhs: impl Expressive<T>, rhs: impl Expressive<T>) -> ConditionGroup<T> {
ConditionGroup::new("AND", vec![lhs.expr(), rhs.expr()])
}