scepter 0.1.5

Composable primitives for planet-scale time-series routing, indexing, and aggregation.
Documentation
use std::cmp::Ordering;
use std::convert::Infallible;
use std::ops::AddAssign;

use crate::aggregate::Mergeable;

/// Combines incoming delta values into a bucket accumulator.
pub trait Reducer<V> {
    /// Error returned when two values cannot be reduced.
    type Error;

    /// Adds `value` into `accumulator`.
    fn reduce(&mut self, accumulator: &mut V, value: V) -> Result<(), Self::Error>;
}

/// Reducer that delegates to `Mergeable`.
#[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)
    }
}

/// Reducer that adds values with `AddAssign`.
#[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(())
    }
}

/// Reducer that keeps the smallest value.
#[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(())
    }
}

/// Reducer that keeps the largest value.
#[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(())
    }
}