use serde::{Deserialize, Serialize};
use std::fmt::Debug;
pub trait Aggregator: Send + Sync + Debug {
type Input: Clone;
type Output: Clone;
type Accumulator: Clone + Serialize + for<'de> Deserialize<'de>;
fn new() -> Self
where
Self: Sized;
fn update(&mut self, value: Self::Input) -> anyhow::Result<()>;
fn update_batch(&mut self, values: &[Self::Input]) -> anyhow::Result<()> {
for value in values {
self.update(value.clone())?;
}
Ok(())
}
fn finalize(&self) -> anyhow::Result<Self::Output>;
fn accumulator(&self) -> Self::Accumulator;
fn merge(&mut self, other: Self::Accumulator) -> anyhow::Result<()>;
fn reset(&mut self);
fn count(&self) -> u64;
fn is_empty(&self) -> bool {
self.count() == 0
}
}
pub trait CloneableAggregator: Aggregator {
fn clone_box(&self) -> Box<dyn CloneableAggregator<Input = Self::Input, Output = Self::Output, Accumulator = Self::Accumulator>>;
}
pub trait ToF64 {
fn to_f64(&self) -> f64;
}
impl ToF64 for f64 {
fn to_f64(&self) -> f64 {
*self
}
}
impl ToF64 for f32 {
fn to_f64(&self) -> f64 {
*self as f64
}
}
impl ToF64 for i64 {
fn to_f64(&self) -> f64 {
*self as f64
}
}
impl ToF64 for i32 {
fn to_f64(&self) -> f64 {
*self as f64
}
}
impl ToF64 for u64 {
fn to_f64(&self) -> f64 {
*self as f64
}
}
impl ToF64 for u32 {
fn to_f64(&self) -> f64 {
*self as f64
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_f64_conversions() {
assert_eq!(42_f64.to_f64(), 42.0);
assert_eq!(42_f32.to_f64(), 42.0);
assert_eq!(42_i64.to_f64(), 42.0);
assert_eq!(42_i32.to_f64(), 42.0);
assert_eq!(42_u64.to_f64(), 42.0);
assert_eq!(42_u32.to_f64(), 42.0);
}
}