use crate::{
Reducer,
time_based::storage::{TimeLevel, TimeStorage, TimeWriter},
};
use alloc::vec::Vec;
use core::{marker::PhantomData, num::NonZeroUsize};
#[derive(Clone, Copy)]
struct LevelInfo<Tick, T> {
bucket_count: NonZeroUsize,
bucket_width: Tick,
reducer: Reducer<T>,
}
pub struct Builder<Tick, T> {
raw_capacity: NonZeroUsize,
levels: Vec<LevelInfo<Tick, T>>,
_data: PhantomData<T>,
}
impl<Tick, T> Builder<Tick, T>
where
Tick: Copy,
{
pub fn new(raw_capacity: NonZeroUsize) -> Self {
Self {
raw_capacity,
levels: Vec::new(),
_data: PhantomData,
}
}
pub fn level(mut self, bucket_count: NonZeroUsize, bucket_width: Tick, reducer: Reducer<T>) -> Self {
self.levels.push(LevelInfo {
bucket_count,
bucket_width,
reducer,
});
self
}
pub fn build(self) -> TimeWriter<Tick, T> {
let mut levels = Vec::with_capacity(self.levels.len());
let mut reducers = Vec::with_capacity(self.levels.len());
for level in self.levels {
levels.push(TimeLevel::new(level.bucket_count, level.bucket_width));
reducers.push(level.reducer);
}
TimeWriter {
storage: TimeStorage {
data: Vec::with_capacity(self.raw_capacity.get()),
levels,
},
reducers,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::reducers;
use core::num::NonZeroUsize;
const fn nz(value: usize) -> NonZeroUsize {
match NonZeroUsize::new(value) {
Some(value) => value,
None => panic!("expected non-zero value"),
}
}
#[test]
fn build_with_integer_ticks() {
let writer = Builder::<u64, f32>::new(nz(128))
.level(nz(60), 1_000_000_000, reducers::average_f32())
.build();
assert_eq!(writer.storage().level_count(), 1);
assert_eq!(
writer.storage().level_metadata(0).unwrap().bucket_width(),
1_000_000_000
);
}
}