forkable 0.1.0

Fork-able iterators and asynchronous streams.
Documentation
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
{
    /// The farthest 
    iter_index: usize,
    /// The backing iterator storage.
    iter_storage: Circular<<I as Iterator>::Item, WINDOW_SIZE>,
    /// The original iterator.
    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]
    /// Gets the oldest stored index.
    pub const fn oldest_index(&self) -> usize {
        self.iter_index
    }

    #[inline]
    /// Gets the oldest element `index`.
    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
        }
    }
}