#![allow(missing_docs)]
use std::fmt::Debug;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use crate::{traits::Aggregate, traits::Coalesce};
use super::{
Counter,
shared::{MinMax, Sampler},
};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct NumberContext<T: Orderly> {
pub count: Counter,
pub samples: Sampler<T::Ordered>,
#[serde(flatten)]
pub min_max: MinMax<T>,
}
impl Aggregate<i128> for NumberContext<i128> {
fn aggregate(&mut self, value: &i128) {
self.count.aggregate(value);
self.samples.aggregate(value);
self.min_max.aggregate(value);
}
}
impl Aggregate<f64> for NumberContext<f64> {
fn aggregate(&mut self, value: &'_ f64) {
self.count.aggregate(value);
self.samples.aggregate(value.into()); if !value.is_nan() {
self.min_max.aggregate(value);
}
}
}
impl<T: Clone + PartialOrd + Orderly> Coalesce for NumberContext<T> {
fn coalesce(&mut self, other: Self) {
self.count.coalesce(other.count);
self.samples.coalesce(other.samples);
self.min_max.coalesce(other.min_max);
}
}
impl<T: PartialEq + Orderly> PartialEq for NumberContext<T> {
fn eq(&self, other: &Self) -> bool {
self.count == other.count && self.min_max == other.min_max
}
}
pub trait Orderly: Sized {
type Ordered: Ord + Clone + Serialize + DeserializeOwned;
}
impl Orderly for i128 {
type Ordered = i128;
}
impl Orderly for usize {
type Ordered = usize;
}
impl Orderly for f64 {
type Ordered = ordered_float::OrderedFloat<f64>;
}
impl Orderly for f32 {
type Ordered = ordered_float::OrderedFloat<f32>;
}