use std::{fmt::Debug, marker::PhantomData};
use smallvec::SmallVec;
use crate::{
instrument::{InstrumentData, InstrumentSpec},
aggregation::Aggregator,
};
#[derive(Debug)]
pub struct FixedHotData<
'instrument_data,
'aggregated_data,
const COUNT: usize,
IS: InstrumentSpec,
AggregationData,
T: Aggregator<'instrument_data, 'aggregated_data, T, AggregationData, IS>
+ 'aggregated_data
+ Clone
+ Debug,
> {
data: SmallVec<[T; COUNT]>,
_aggregation_data: PhantomData<AggregationData>,
_instrument_spec: PhantomData<IS>,
_instrument_data: PhantomData<&'instrument_data ()>,
_a: PhantomData<&'aggregated_data ()>,
}
impl<
'instrument_data,
'aggregated_data,
const COUNT: usize,
IS: InstrumentSpec,
AggregationData,
T: Aggregator<'instrument_data, 'aggregated_data, T, AggregationData, IS>
+ 'aggregated_data
+ Clone
+ Debug,
> Default for FixedHotData<
'instrument_data,
'aggregated_data,
COUNT,
IS,
AggregationData,
T,
> {
fn default() -> Self {
Self {
data: SmallVec::default(),
_aggregation_data: PhantomData::default(),
_instrument_spec: PhantomData::default(),
_instrument_data: PhantomData::default(),
_a: PhantomData::default(),
}
}
}
impl<
'instrument_data,
'aggregated_data,
const COUNT: usize,
IS: InstrumentSpec,
AggregationData,
T: Aggregator<'instrument_data, 'aggregated_data, T, AggregationData, IS>
+ 'aggregated_data
+ Clone
+ Debug,
> FixedHotData<
'instrument_data,
'aggregated_data,
COUNT,
IS,
AggregationData,
T,
> {
pub fn len(
&self,
) -> usize {
self.data.len()
}
pub fn capacity(
&self,
) -> usize {
COUNT
}
pub fn is_empty(
&self,
) -> bool {
self.data.is_empty()
}
pub fn clear(
&mut self,
) {
self.data.clear();
}
pub fn remove_newest(
&mut self,
) -> Option<T> {
self.data.pop()
}
pub fn newest(
&self,
) -> Option<&T> {
self.data.last()
}
pub fn oldest(
&self,
) -> Option<&T> {
self.data.first()
}
pub fn data_update(
&mut self,
instrument_data: &'instrument_data InstrumentData<
'instrument_data,
'aggregated_data,
IS,
>,
) {
let aggregated_data: SmallVec<[T; 4]> = {
let aggregation_data = T::hot_data(instrument_data, self.iter_rev());
T::aggregate_hot(&aggregation_data).collect()
};
self.append_manual(aggregated_data.into_iter());
}
pub fn append_manual(
&mut self,
append_data: impl ExactSizeIterator<Item = T>,
) {
debug_assert!(self.data.len() <= COUNT);
let unused_capacity = COUNT - self.data.len();
let mut drain_count = append_data.len().saturating_sub(unused_capacity).min(
COUNT,
);
let data_skip_count = append_data.len().saturating_sub(COUNT).min(COUNT);
drain_count = drain_count.checked_sub(data_skip_count).unwrap();
self.data.drain(0..drain_count);
self.data.extend(append_data.into_iter().take(COUNT).skip(data_skip_count));
debug_assert!(!self.data.spilled());
}
pub fn get(
&self,
idx: usize,
) -> Option<&T> {
debug_assert!(idx < COUNT);
self.data.get(idx)
}
pub fn iter(
&self,
) -> impl Iterator<Item = &T> {
self.data.iter()
}
pub fn iter_rev(
&self,
) -> impl Iterator<Item = &T> + use<'_, COUNT, IS, AggregationData, T> {
self.data.iter().rev()
}
pub fn forward_slice_from<P: FnMut(&T) -> bool>(
&'aggregated_data self,
exclude: P,
) -> &'aggregated_data [T] {
let Some(
idx,
) = self.data.iter().rev().position(exclude) else {
return &self.data;
};
let idx = idx + 1;
if idx >= self.data.len() {
return &self.data;
}
&self.data[idx..]
}
pub fn forward_slice(
&'aggregated_data self,
) -> &'aggregated_data [T] {
&self.data
}
}