use core::iter::FusedIterator;
use circularing::Circular;
pub struct Nucleus<I, const WINDOW_SIZE: usize>
where
I: Iterator + FusedIterator,
<I as Iterator>::Item: Clone + Copy
{
iter_index: usize,
iter_storage: Circular<<I as Iterator>::Item, WINDOW_SIZE>,
iter: I
}
impl<I, const S: usize> Nucleus<I, S>
where
I: Iterator + FusedIterator,
<I as Iterator>::Item: Clone + Copy
{
#[inline]
pub const fn new(iter: I) -> Self {
let iter_index = 0;
let iter_storage = Circular::new();
Self {
iter_index,
iter_storage,
iter
}
}
#[inline]
pub const fn oldest_index(&self) -> usize {
self.iter_index
}
#[inline]
pub fn at(&self, target_index: usize) -> Option<<I as Iterator>::Item> {
self.iter_storage.top(target_index)
}
}
impl<I, const S: usize> Iterator for Nucleus<I, S>
where
I: Iterator + FusedIterator,
<I as Iterator>::Item: Clone + Copy
{
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.iter_storage.is_full() {
self.iter_index = self.iter_index.saturating_add(1);
}
match self.iter.next() {
target_item @ Some(target_value) => {
self.iter_storage.push(target_value);
target_item
},
None => None
}
}
}