#![allow(private_bounds)]
use std::{fmt::Debug, marker::PhantomData};
use crate::aggregate::{AggregateOp, RefAggregateOp, assert_ref_op};
pub struct Count<K, T, C: SupportedCountTy = usize> {
_maker: PhantomData<fn(&K, T, &mut C) -> C>,
}
impl<K, T, C: SupportedCountTy> Count<K, T, C> {
#[inline]
pub const fn new() -> Self {
assert_ref_op(Self {
_maker: PhantomData,
})
}
}
impl<K, T, C: SupportedCountTy> Default for Count<K, T, C> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<K, T, C: SupportedCountTy> AggregateOp for Count<K, T, C> {
type Key = K;
type Value = C;
type Item = T;
#[inline]
fn new_value(&mut self, _key: &Self::Key, _item: Self::Item) -> Self::Value {
C::ONE
}
#[inline]
fn modify(&mut self, value: &mut Self::Value, _item: Self::Item) {
value.increment();
}
}
impl<K, T, C: SupportedCountTy> RefAggregateOp for Count<K, T, C> {
#[inline]
fn new_value_ref(&mut self, _key: &Self::Key, _item: &mut Self::Item) -> Self::Value {
C::ONE
}
#[inline]
fn modify_ref(&mut self, value: &mut Self::Value, _item: &mut Self::Item) {
value.increment();
}
}
impl<K, T, C: SupportedCountTy> Clone for Count<K, T, C> {
fn clone(&self) -> Self {
Self {
_maker: PhantomData,
}
}
}
impl<K, T, C: SupportedCountTy> Debug for Count<K, T, C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Count").finish()
}
}
trait SupportedCountTy {
const ONE: Self;
fn increment(&mut self);
}
macro_rules! supported_count_ty_impl {
($int:ty) => {
impl SupportedCountTy for $int {
const ONE: Self = 1 as _;
#[inline]
fn increment(&mut self) {
*self += 1;
}
}
};
}
macro_rules! supported_count_ty_impls {
($($ints:ty)*) => {
$(supported_count_ty_impl!($ints);)*
};
}
supported_count_ty_impls!(i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize);