use std::cmp::Ordering;
use std::convert::Infallible;
use std::ops::AddAssign;
use crate::aggregate::Mergeable;
pub trait Reducer<V> {
type Error;
fn reduce(&mut self, accumulator: &mut V, value: V) -> Result<(), Self::Error>;
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct MergeReducer;
impl<V> Reducer<V> for MergeReducer
where
V: Mergeable,
{
type Error = V::Error;
fn reduce(&mut self, accumulator: &mut V, value: V) -> Result<(), Self::Error> {
accumulator.merge_from(value)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct SumReducer;
impl<V> Reducer<V> for SumReducer
where
V: AddAssign,
{
type Error = Infallible;
fn reduce(&mut self, accumulator: &mut V, value: V) -> Result<(), Self::Error> {
*accumulator += value;
Ok(())
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct MinReducer;
impl<V> Reducer<V> for MinReducer
where
V: Ord,
{
type Error = Infallible;
fn reduce(&mut self, accumulator: &mut V, value: V) -> Result<(), Self::Error> {
if value.cmp(accumulator) == Ordering::Less {
*accumulator = value;
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct MaxReducer;
impl<V> Reducer<V> for MaxReducer
where
V: Ord,
{
type Error = Infallible;
fn reduce(&mut self, accumulator: &mut V, value: V) -> Result<(), Self::Error> {
if value.cmp(accumulator) == Ordering::Greater {
*accumulator = value;
}
Ok(())
}
}