vec-iter 0.1.1

Lazy collection of iterated element, implementing iterators for random access
Documentation
#![no_std]
#![doc = include_str!("../README.md")]

extern crate alloc;

use core::ops::{Deref, DerefMut};

use alloc::{vec, vec::Vec};

/// Create from [`IterVecIterExt::vec_iter`]
#[derive(Debug, Clone)]
pub struct VecIter<I: Iterator> {
    iter: I,
    collected: Vec<I::Item>,
}

impl<I: Iterator> Deref for VecIter<I> {
    type Target = [I::Item];

    fn deref(&self) -> &Self::Target {
        &self.collected
    }
}

impl<I: Iterator> DerefMut for VecIter<I> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.collected
    }
}

impl<I: Iterator> Iterator for VecIter<I>
where I::Item: Clone,
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        let elem = self.iter.next()?;
        self.init_capacity_push(elem.clone());
        Some(elem)
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        let elem = self.iter.next()?;
        self.init_capacity_push(elem);
        for _ in 1..n {
            self.collected.push(self.iter.next()?);
        }
        self.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (lo, hi) = self.iter.size_hint();
        (lo+self.collected_len(), hi.map(|hi| hi+self.collected_len()))
    }

    fn fold<B, F>(self, init: B, f: F) -> B
    where Self: Sized,
          F: FnMut(B, Self::Item) -> B,
    {
        self.collected.into_iter().chain(self.iter).fold(init, f)
    }
}

impl<I: Iterator> VecIter<I>
where I::Item: Clone,
{
    fn init_capacity(&mut self) {
        if self.collected_len() == 0 {
            self.collected.reserve(self.size_hint().0);
        }
    }

    fn init_capacity_push(&mut self, value: I::Item) {
        if self.collected_len() == 0 {
            self.collected.reserve(self.size_hint().0+1);
        }
        self.collected.push(value);
    }

    fn require(&mut self, i: usize) -> Option<&mut I::Item> {
        self.init_capacity();
        let n = i.saturating_sub(self.collected_len())+1;
        self.collected.extend(self.iter.by_ref().take(n));
        self.collected.get_mut(i)
    }

    #[inline]
    pub fn collected_len(&self) -> usize {
        self.collected.len()
    }

    /// Collect to `i+1`, and index `i`
    pub fn get_req(&mut self, i: usize) -> Option<&I::Item> {
        self.require(i).map(|value| &*value)
    }

    /// Collect to `i+1`, and index `i`
    pub fn get_req_mut(&mut self, i: usize) -> Option<&mut I::Item> {
        self.require(i)
    }

    /// Collect to `i+1`, and index `i`
    pub fn get_req_cloned(&mut self, i: usize) -> Option<I::Item> {
        self.require(i).cloned()
    }

    /// Collect all elements, and into inner collected buffer
    pub fn into_all_collected(mut self) -> Vec<I::Item> {
        self.collected.extend(self.iter);
        self.collected
    }
}

impl<I: Iterator + Default> Default for VecIter<I> {
    fn default() -> Self {
        Self {
            iter: I::default(),
            collected: vec![],
        }
    }
}

#[doc = include_str!("../README.md")]
pub trait IterVecIterExt: Iterator + Sized {
    /// Create a [`VecIter`]
    ///
    /// # Examples
    /// ```
    /// # use vec_iter::IterVecIterExt;
    /// let mut iter = [0, 1, 2, 3, 4].into_iter().vec_iter();
    ///
    /// assert_eq!(iter.next(), Some(0));
    /// assert_eq!(*iter, [0]);
    /// assert_eq!(iter.nth(1), Some(2));
    /// assert_eq!(*iter, [0, 1, 2]);
    /// assert_eq!(iter.get_req(3), Some(&3));
    /// assert_eq!(*iter, [0, 1, 2, 3]);
    /// assert_eq!(iter.into_all_collected(), [0, 1, 2, 3, 4]);
    /// ```
    fn vec_iter(self) -> VecIter<Self> {
        VecIter { iter: self, collected: vec![] }
    }
}
impl<I: Iterator> IterVecIterExt for I { }

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn basic_each() {
        assert_eq!((0..5).vec_iter().collect::<Vec<_>>(), vec![0, 1, 2, 3, 4]);
        assert_eq!((0..0).vec_iter().collect::<Vec<_>>(), vec![]);
    }

    #[test]
    fn capacity() {
        let mut iter = (0..5).vec_iter();
        assert_eq!(iter.collected.capacity(), 0);
        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.collected.capacity(), 5);
        assert_eq!(iter.collected_len(), 1);
    }

    #[test]
    fn nth() {
        let mut iter = (0..5).vec_iter();
        assert_eq!(iter.collected.capacity(), 0);
        assert_eq!(iter.nth(2), Some(2));
        assert_eq!(iter.collected.capacity(), 5);
        assert_eq!(*iter, [0, 1, 2]);
        assert_eq!(iter.next(), Some(3));
    }

    #[test]
    fn into_all_collected() {
        let mut iter = (0..5).vec_iter();
        assert_eq!(iter.collected.capacity(), 0);
        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.collected.capacity(), 5);
        assert_eq!(iter.collected_len(), 1);
        assert_eq!(iter.into_all_collected(), vec![0, 1, 2, 3, 4]);
    }

    #[test]
    fn get_req() {
        let mut iter = (0..5).vec_iter();
        assert_eq!(iter.collected.capacity(), 0);
        assert_eq!(iter.get_req_cloned(2), Some(2));
        assert_eq!(iter.collected.capacity(), 5);
        assert_eq!(iter.collected_len(), 3);
        assert_eq!(iter.into_all_collected(), vec![0, 1, 2, 3, 4]);
    }
}