more-itertools 0.1.6

A rust implementation of python more-itertools
Documentation
use crate::error::Error;

pub struct Substrings<T> 
where
T: Clone
{
    iter: Box<dyn Iterator<Item = Result<T,Error>>>,
    substring_len: usize,
    cur: usize,
    vec: Vec<T>,
    upstream_error: Option<Error>,
    iter_finished: bool,
}


impl<T> Iterator for Substrings<T> 
where 
T: Clone
{
    type Item = Result<Vec<T>, Error>;

    fn next(&mut self) -> Option<Self::Item> {

        if self.iter_finished {
            return None;
        }

        if let Some(v_upstream_error) = &self.upstream_error {
            self.iter_finished = true;
            return Some(Err(v_upstream_error.clone()));
        }

        loop {
            if self.substring_len > self.vec.len() {
                return None;
            }
    
            if self.cur + self.substring_len > self.vec.len() {
                self.cur = 0;
                self.substring_len += 1;
                continue;
            } else {
                let mut ret = Vec::new();
                for ele in self.vec[self.cur..self.cur+self.substring_len].iter() {
                    ret.push(ele.clone())
                }
                self.cur += 1;
                return Some(Ok(ret));
            }
        }
    }
}


pub fn substrings<T>(iter: Box<dyn Iterator<Item = Result<T,Error>>>) -> Box<dyn Iterator<Item = Result<Vec<T>, Error>>>
where
T: Clone + 'static
{
    let mut ret = Substrings {
        iter,
        substring_len: 1,
        cur: 0,
        vec: Vec::new(),
        upstream_error: None,
        iter_finished: false
    };

    loop {
        if let Some(item) = ret.iter.next() {
            match item {
                Ok(ok_item) => {
                    ret.vec.push(ok_item);
                },
                Err(err_item) => {
                    ret.upstream_error = Some(err_item);
                    break;
                }
            }
        } else {
            break;
        }
    }

    return Box::new(ret);
}


#[cfg(test)]
mod tests {
    use crate::utils::generate_okok_iterator;

    use super::*;

    #[test]
    fn test1() {
        let v = vec![1,2,3,4];
        let mut ss = substrings(generate_okok_iterator(v));

        assert_eq!(Some(vec![1]), ss.next().unwrap().ok());
        assert_eq!(Some(vec![2]), ss.next().unwrap().ok());
        assert_eq!(Some(vec![3]), ss.next().unwrap().ok());
        assert_eq!(Some(vec![4]), ss.next().unwrap().ok());

        assert_eq!(Some(vec![1,2]), ss.next().unwrap().ok());
        assert_eq!(Some(vec![2,3]), ss.next().unwrap().ok());
        assert_eq!(Some(vec![3,4]), ss.next().unwrap().ok());

        assert_eq!(Some(vec![1,2,3]), ss.next().unwrap().ok());
        assert_eq!(Some(vec![2,3,4]), ss.next().unwrap().ok());

        assert_eq!(Some(vec![1,2,3,4]), ss.next().unwrap().ok());

        assert_eq!(None, ss.next());
        assert_eq!(None, ss.next());
    }
}