use std::{fmt::Debug, marker::PhantomData};
use smallvec::SmallVec;
use crate::{
aggregation::Aggregator,
instrument::{InstrumentData, InstrumentSpec},
};
#[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
}
}