use core::fmt::Debug;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[cfg(feature = "all")]
pub mod all;
#[cfg(feature = "avg")]
pub mod avg;
#[cfg(feature = "max")]
pub mod max;
#[cfg(feature = "min")]
pub mod min;
#[cfg(feature = "min_max")]
pub mod min_max;
#[cfg(feature = "sum")]
pub mod sum;
#[cfg(feature = "top_n")]
pub mod top_n;
#[cfg(feature = "bloom")]
pub mod bloom;
#[cfg(feature = "roaring")]
pub mod roaring;
pub type CombineSimdFn<P> = fn(&[P]) -> P;
pub type InverseFn<P> = fn(P, P) -> P;
pub trait Aggregator: Default + Debug + Clone + 'static {
const IDENTITY: Self::PartialAggregate;
type Input: InputBounds;
type MutablePartialAggregate: MutablePartialAggregateType;
type PartialAggregate: PartialAggregateType;
type Aggregate: Debug + Send;
fn lift(input: Self::Input) -> Self::MutablePartialAggregate;
fn combine_mutable(a: &mut Self::MutablePartialAggregate, input: Self::Input);
fn freeze(a: Self::MutablePartialAggregate) -> Self::PartialAggregate;
fn combine(a: Self::PartialAggregate, b: Self::PartialAggregate) -> Self::PartialAggregate;
fn lower(a: Self::PartialAggregate) -> Self::Aggregate;
#[inline]
#[doc(hidden)]
fn combine_slice(slice: &[Self::PartialAggregate]) -> Option<Self::PartialAggregate> {
match Self::combine_simd() {
Some(combine_simd) => Some(combine_simd(slice)),
None => Some(
slice
.iter()
.cloned()
.fold(Self::IDENTITY.clone(), Self::combine),
),
}
}
#[inline]
#[doc(hidden)]
fn merge(s1: &mut [Self::PartialAggregate], s2: &[Self::PartialAggregate]) {
for (self_slot, other_slot) in s1.iter_mut().zip(s2.iter()).take(s2.len()) {
let left = core::mem::take(self_slot);
let combined = Self::combine(left, other_slot.clone());
*self_slot = combined;
}
}
#[doc(hidden)]
#[inline]
fn build_prefix(slice: &[Self::PartialAggregate]) -> Vec<Self::PartialAggregate> {
let mut acc = Self::IDENTITY.clone();
slice
.iter()
.map(|item| {
let combined = Self::combine(acc.clone(), item.clone());
acc = combined.clone();
combined
})
.collect::<Vec<_>>()
}
#[doc(hidden)]
#[inline]
fn prefix_query(
slice: &[Self::PartialAggregate],
start: usize,
end: usize,
) -> Option<Self::PartialAggregate> {
Self::combine_inverse().map(|inverse| {
let end_value = slice[end].clone();
if start == 0 {
end_value
} else {
let start_value = slice[start - 1].clone();
inverse(end_value, start_value)
}
})
}
fn combine_inverse() -> Option<InverseFn<Self::PartialAggregate>> {
None
}
fn combine_simd() -> Option<CombineSimdFn<Self::PartialAggregate>> {
None
}
fn compression() -> Option<Compression<Self::PartialAggregate>> {
None
}
#[doc(hidden)]
fn invertible() -> bool {
Self::combine_inverse().is_some()
}
#[doc(hidden)]
fn simd_support() -> bool {
Self::combine_simd().is_some()
}
#[doc(hidden)]
fn compression_support() -> bool {
Self::compression().is_some()
}
}
pub struct Compression<T> {
pub(crate) compressor: Compressor<T>,
pub(crate) decompressor: Decompressor<T>,
}
impl<T> Compression<T> {
pub fn new(compressor: Compressor<T>, decompressor: Decompressor<T>) -> Self {
Self {
compressor,
decompressor,
}
}
}
pub type Compressor<T> = fn(&[T]) -> Vec<u8>;
pub type Decompressor<T> = fn(&[u8]) -> Vec<T>;
#[cfg(not(feature = "serde"))]
pub trait InputBounds: Debug + Clone + Copy + Send {}
#[cfg(feature = "serde")]
pub trait InputBounds:
Debug + Clone + Copy + Send + serde::Serialize + for<'a> serde::Deserialize<'a>
{
}
#[cfg(not(feature = "serde"))]
impl<T> InputBounds for T where T: Debug + Clone + Copy + Send {}
#[cfg(feature = "serde")]
impl<T> InputBounds for T where
T: Debug + Clone + Copy + Send + serde::Serialize + for<'a> serde::Deserialize<'a>
{
}
#[cfg(not(feature = "serde"))]
pub trait MutablePartialAggregateType: Clone {}
#[cfg(feature = "serde")]
pub trait MutablePartialAggregateType:
Clone + serde::Serialize + for<'a> serde::Deserialize<'a>
{
}
#[cfg(not(feature = "serde"))]
impl<T> MutablePartialAggregateType for T where T: Clone {}
#[cfg(feature = "serde")]
impl<T> MutablePartialAggregateType for T where
T: Clone + serde::Serialize + for<'a> serde::Deserialize<'a> + 'static
{
}
#[cfg(not(feature = "serde"))]
pub trait PartialAggregateBounds: Default + Debug + Clone + Send {}
#[cfg(feature = "serde")]
pub trait PartialAggregateBounds:
Default + Debug + Clone + Send + serde::Serialize + for<'a> serde::Deserialize<'a>
{
}
#[cfg(not(feature = "serde"))]
impl<T> PartialAggregateBounds for T where T: Default + Debug + Clone + Send {}
#[cfg(feature = "serde")]
impl<T> PartialAggregateBounds for T where
T: Default + Debug + Clone + Send + serde::Serialize + for<'a> serde::Deserialize<'a>
{
}
pub trait PartialAggregateType: PartialAggregateBounds {}
macro_rules! primitive_partial {
($type:ty) => {
impl PartialAggregateType for $type {}
};
}
primitive_partial!(u8);
primitive_partial!(u16);
primitive_partial!(u32);
primitive_partial!(u64);
primitive_partial!(i8);
primitive_partial!(i16);
primitive_partial!(i32);
primitive_partial!(i64);
primitive_partial!(f32);
primitive_partial!(f64);
primitive_partial!(i128);
primitive_partial!(u128);
macro_rules! tuple_partial {
( $( $name:ident )+ ) => {
impl<$($name: PartialAggregateType),+> PartialAggregateType for ($($name,)+)
{
}
};
}
tuple_partial!(A B);
tuple_partial!(A B C);
tuple_partial!(A B C D);
tuple_partial!(A B C D E);
tuple_partial!(A B C D E F);