itertools-wild 0.1.1

Extra wild iterator adaptors, wild iterator methods, wild free functions, and wild macros.
Documentation


use std::iter::Fuse;

pub struct ClampToExactLength<I, F> {
    pub(crate) iter: Fuse<I>,
    pub(crate) filler: F,
    pub(crate) index: usize,
    pub(crate) size: usize,
}

impl<I, F> Iterator for ClampToExactLength<I, F>
    where I: Iterator,
          F: FnMut(usize) -> I::Item,
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index >= self.size {
            None
        } else {
            let index = self.index;
            self.index += 1;
            match self.iter.next() {
                None => Some((self.filler)(index)),
                elt => elt,
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.size - self.index;
        (len, Some(len))
    }
}


pub struct AssertExactSize<I> {
    pub(crate) iter: I,
    pub(crate) size: usize,
}

impl<I> AssertExactSize<I>
    where I: Iterator,
{
    fn get_next<F>(&mut self, next: F) -> Option<I::Item>
        where F: FnOnce(&mut I) -> Option<I::Item>
    {
        let elt = next(&mut self.iter);
        if let Some(_) = elt {
            debug_assert!(self.size > 0, "AssertExactSize: length mismatch, iterator\
                produced at least one element more than the asserted size");
            self.size -= 1;
        } else {
            debug_assert_eq!(0, self.size, "AssertExactSize: length mismatch, iterator\
                produced {} elements less than the asserted size", self.size);
        }
        elt
    }
}

impl<I> Iterator for AssertExactSize<I> where I: Iterator
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        self.get_next(|iter| iter.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.size, Some(self.size))
    }
}

impl<I> ExactSizeIterator for AssertExactSize<I> where I: Iterator { }
impl<I> DoubleEndedIterator for AssertExactSize<I>
    where I: DoubleEndedIterator
{
    fn next_back(&mut self) -> Option<Self::Item> {
        self.get_next(|iter| iter.next_back())
    }

}