more-itertools 0.1.6

A rust implementation of python more-itertools
Documentation
use std::collections::VecDeque;
use std::fmt::Debug;
use crate::utils::are_same;

pub struct GroupBy<T> 
where T: Clone + Debug + PartialEq
{
    cur_key: Option<T>,
    buf: VecDeque<T>,
    emitted_first: bool,
    iter: Box<dyn Iterator<Item = T>>,
    iter_finished: bool,
    stop_next: bool,
}


impl<T> GroupBy<T> 
where T: Clone + Debug + PartialEq
{
    pub fn next_group(&mut self) -> Option<T> {
        loop {
            if self.iter_finished {
                return None;
            }

            let _next;
            if self.buf.len() > 0 {
                _next = self.buf.pop_front();
            } else {
                _next = self.iter.next();
            }
            
            match _next {
                None => {
                    self.iter_finished = true;
                    continue;
                },
                Some(v) => {
                    if self.cur_key.is_none() || !are_same(Some(&v), Some(self.cur_key.as_mut().unwrap())) {
                        self.cur_key = Some(v.clone());
                        self.emitted_first = false;
                        self.stop_next = false;
                        return Some(v);
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    pub fn collect0(&mut self) -> Vec<T> {
        return self.collect();
    }
}

impl<T> Iterator for GroupBy<T> 
where
T: PartialEq + Clone + Debug
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.iter_finished {
                return None;
            }

            if self.stop_next {
                return None;
            }

            if self.cur_key.is_none() {
                return None;
            }

            if !self.emitted_first {
                self.emitted_first = true;
                return Some(self.cur_key.as_ref().unwrap().clone());
            }

            let _next = self.iter.next();
            match _next {
                None => {
                    self.iter_finished = true;
                    continue;
                },
                Some(v) => {
                    if !are_same(Some(&v), Some(self.cur_key.as_mut().unwrap())) {
                        self.buf.push_back(v.clone());
                        self.stop_next = true;
                        continue;
                    } else {
                        return Some(v);
                    }
                }
            }
        }
    }
}

pub fn groupby<T>(iter: Box<dyn Iterator<Item = T>>) -> GroupBy<T> 
where
T: PartialEq + Clone + Debug
{
    return GroupBy {
        cur_key: None,
        buf: VecDeque::new(),
        emitted_first: false,
        iter,
        iter_finished: false,
        stop_next: true
    }
}


#[cfg(test)]
mod tests {
    use crate::itertools::iter::iter_from_vec;

    use super::*;

    #[test]
    fn test1() {
        let mut ret = groupby(iter_from_vec("AAAAbbbcccC".chars().collect::<Vec<char>>()));
        assert_eq!('A', ret.next_group().unwrap());
        assert_eq!(vec!['A','A','A','A'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('b', ret.next_group().unwrap());
        assert_eq!(vec!['b','b','b'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('c', ret.next_group().unwrap());
        assert_eq!(vec!['c','c','c'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('C', ret.next_group().unwrap());
        assert_eq!(vec!['C'], ret.collect0());
        assert_eq!(None, ret.next());
    }

    #[test]
    fn test2() {
        let mut ret = groupby(iter_from_vec("0AAAAbbbcccCC".chars().collect::<Vec<char>>()));
        assert_eq!('0', ret.next_group().unwrap());
        assert_eq!(vec!['0'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('A', ret.next_group().unwrap());
        assert_eq!(vec!['A','A','A','A'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('b', ret.next_group().unwrap());
        assert_eq!(vec!['b','b','b'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('c', ret.next_group().unwrap());
        assert_eq!(vec!['c','c','c'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('C', ret.next_group().unwrap());
        assert_eq!(vec!['C','C'], ret.collect0());
        assert_eq!(None, ret.next());
    }

    #[test]
    fn test3() {
        let mut ret = groupby(iter_from_vec("0AAAAbbbcccCC".chars().collect::<Vec<char>>()));
        assert_eq!('0', ret.next_group().unwrap());

        assert_eq!('A', ret.next_group().unwrap());

        assert_eq!(vec!['A','A','A','A'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('b', ret.next_group().unwrap());
        assert_eq!(vec!['b','b','b'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('c', ret.next_group().unwrap());
        assert_eq!(vec!['c','c','c'], ret.collect0());
        assert_eq!(None, ret.next());

        assert_eq!('C', ret.next_group().unwrap());
        assert_eq!(vec!['C','C'], ret.collect0());
        assert_eq!(None, ret.next());
    }
}