more-itertools 0.1.6

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

#[derive(PartialEq)]
pub enum IncompleteType {
    Fill,
    Ignore,
    Strict
}

pub struct Grouper<T> {
    buf: Box<dyn Sequence<T>>,
    n: usize,
    incomplete: IncompleteType,
    fillvalue: Option<T>,
    cur: usize
}

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

    fn next(&mut self) -> Option<Self::Item> {
        if self.cur >= self.buf.len() {
            return None;
        }

        if self.n == 0 {
            return Some(Err(error::value_error("n should not be 0.".to_string())));
        }

        if self.incomplete == IncompleteType::Fill {
            match self.fillvalue {
                None => { return Some(Err(error::value_error("fillvalue should not be None when incomplete is Fill".to_string()))); },
                Some(_) => {}
            }
        }

        let mut ret = Vec::new();
        let mut cnt: usize = 0;
        while self.cur < self.buf.len() {
            if cnt == self.n {
                break;
            }
            cnt += 1;

            ret.push(self.buf.get(self.cur).unwrap().clone());
            self.cur += 1;
        }

        if ret.len() < self.n {
            match self.incomplete {
                IncompleteType::Fill => {
                    for _ in 0..(self.n - ret.len()) {
                        ret.push(self.fillvalue.as_ref().unwrap().clone());
                    }
                    return Some(Ok(ret));
                },
                IncompleteType::Ignore => {
                    return None;
                },
                IncompleteType::Strict => {
                    return Some(Err(error::value_error("length of buf should be divide by n".to_string())));
                }
            }
        } else {
            return Some(Ok(ret));
        }

        
    }
}

pub fn grouper<T>(seq: Box<dyn Sequence<T>>, n: usize, incomplete: IncompleteType, fillvalue: Option<T>) -> Box<dyn Iterator<Item = Result<Vec<T>,Error>>>
where T: Clone + 'static
{
    Box::new(Grouper {
        buf: seq,
        n: n,
        incomplete: incomplete,
        fillvalue: fillvalue,
        cur: 0
    })
}

#[cfg(test)]
mod tests {
    use crate::sequence::create_seq_from_vec;

    use super::*;

    #[test]
    fn test1() {
        let v = vec![1,2,3,4,5,6,7,8,9,10];

        let mut g = grouper(create_seq_from_vec(v), 3, IncompleteType::Fill, Some(0));
        assert_eq!(vec![1,2,3], g.next().unwrap().ok().unwrap());
        assert_eq!(vec![4,5,6], g.next().unwrap().ok().unwrap());
        assert_eq!(vec![7,8,9], g.next().unwrap().ok().unwrap());
        assert_eq!(vec![10,0,0], g.next().unwrap().ok().unwrap());

        let v = vec![1,2,3,4,5,6,7,8,9,10];

        let mut g = grouper(create_seq_from_vec(v), 3, IncompleteType::Ignore, Some(0));
        assert_eq!(vec![1,2,3], g.next().unwrap().ok().unwrap());
        assert_eq!(vec![4,5,6], g.next().unwrap().ok().unwrap());
        assert_eq!(vec![7,8,9], g.next().unwrap().ok().unwrap());
        assert_eq!(None, g.next());


        let v = vec![1,2,3,4,5,6,7,8,9,10];

        let mut g = grouper(create_seq_from_vec(v), 3, IncompleteType::Strict, Some(0));
        assert_eq!(vec![1,2,3], g.next().unwrap().ok().unwrap());
        assert_eq!(vec![4,5,6], g.next().unwrap().ok().unwrap());
        assert_eq!(vec![7,8,9], g.next().unwrap().ok().unwrap());
        match g.next() {
            Some(v) => {
                match v {
                    Ok(_) => { assert!(false); }
                    Err(_) => {assert!(true); }
                }
            }
            None => { assert!(false); }
        }
    }
}