use std::fmt;
use std::cmp::PartialOrd;
use std::str::FromStr;
use std::ops::{AddAssign, MulAssign};
use crate::reduce::aggregate::{
Aggregate, Count, Avg, Last, Max, Min, Sum, Mul, Closure,
};
use crate::error;
pub struct Reducer {
name: String,
source: Option<String>,
}
impl Reducer {
pub fn with_name(name: &str) -> Reducer {
Reducer {
name: name.into(),
source: None,
}
}
pub fn count(self) -> Box<dyn Aggregate> {
Box::new(Count::new(self.name))
}
pub fn custom<'a, A>(reducer: A) -> Box<dyn Aggregate + 'a>
where
A: Aggregate + 'a,
{
Box::new(reducer)
}
pub fn of_column(mut self, name: &str) -> Reducer {
self.source = Some(name.into());
self
}
pub fn average(self) -> Option<Box<dyn Aggregate>> {
Some(Box::new(Avg::new(self.name, self.source?)))
}
pub fn last(self, init: &str) -> Option<Box<dyn Aggregate>> {
Some(Box::new(Last::new(self.name, self.source?, init.into())))
}
pub fn max<'a, T>(self, init: T) -> Option<Box<dyn Aggregate + 'a>>
where
T: fmt::Display + fmt::Debug + PartialOrd + FromStr + Copy + 'a,
<T as FromStr>::Err: fmt::Debug,
{
Some(Box::new(Max::new(self.name, self.source?, init)))
}
pub fn min<'a, T>(self, init: T) -> Option<Box<dyn Aggregate + 'a>>
where
T: fmt::Display + fmt::Debug + PartialOrd + FromStr + Copy + 'a,
<T as FromStr>::Err: fmt::Debug,
{
Some(Box::new(Min::new(self.name, self.source?, init)))
}
pub fn sum<'a, T>(self, init: T) -> Option<Box<dyn Aggregate + 'a>>
where
T: fmt::Display + fmt::Debug + AddAssign + FromStr + Copy + 'a,
<T as FromStr>::Err: fmt::Debug,
{
Some(Box::new(Sum::new(self.name, self.source?, init)))
}
pub fn product<'a, T>(self, init: T) -> Option<Box<dyn Aggregate + 'a>>
where
T: fmt::Display + fmt::Debug + MulAssign + FromStr + Copy + 'a,
<T as FromStr>::Err: fmt::Debug,
{
Some(Box::new(Mul::new(self.name, self.source?, init)))
}
pub fn with_closure<'a, F, C>(self, f: F, init: C) -> Option<Box<dyn Aggregate + 'a>>
where
F: FnMut(C, &str) -> error::Result<C> + 'a,
C: fmt::Display + 'a,
{
Some(Box::new(Closure::new(self.name, self.source?, f, init)))
}
}