use std::fmt::Display;
use crate::{
query::{
expression::PathExpression,
parser::{Column, Parser},
},
Any, Dapt, Path,
};
use super::{
super::{expression::Expression, QueryResult},
Aggregation,
};
#[derive(Clone)]
pub struct ExpressionAggregation {
expr: Box<dyn Expression>,
value: Option<Any<'static>>,
}
impl ExpressionAggregation {
fn new(expr: Box<dyn Expression>) -> Self {
Self { expr, value: None }
}
pub fn from_parser(parser: &mut Parser) -> QueryResult<ExpressionAggregation> {
let expr = parser.parse_expression()?;
Ok(ExpressionAggregation::new(expr))
}
}
impl From<Path> for ExpressionAggregation {
fn from(path: Path) -> Self {
Self::new(Box::new(PathExpression::new(path)))
}
}
impl Aggregation for ExpressionAggregation {
fn process<'a>(&'a mut self, d: &Dapt) {
if self.value.is_some() {
return;
}
self.value = match self.expr.evaluate(d) {
Some(v) => Some(v.force_owned()),
None => return,
};
}
fn result<'a>(&'a mut self) -> Option<Any<'a>> {
let v = self.value.take()?;
Some(Any::from(v))
}
fn composable(&self, path: &Path) -> (Vec<Column>, Box<dyn Aggregation>) {
let composable = Column::new(Box::new(self.clone()), path.clone());
let combine = Box::new(ExpressionAggregation::from(path.clone()));
(vec![composable], combine)
}
}
impl Display for ExpressionAggregation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.expr)
}
}