more-itertools 0.1.6

A rust implementation of python more-itertools
Documentation
use crate::error::{self, Error};

struct Map<T, J> {
    iter: Box<dyn Iterator<Item = Result<T,Error>>>,
    pred: fn(T) -> Result<J, Error>,
    iter_finished: bool,
    iter_error: Option<Error>
}

impl<T,J> Iterator for Map<T, J>
{
    type Item = Result<J, Error>;

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

        if self.iter_error.is_some() {
            return Some(Err(self.iter_error.as_ref().unwrap().clone()));
        }

        let _next = self.iter.next();
        if let Some(v) = _next {
            if let Ok(v2) = v {
                let j = (self.pred)(v2);
                if j.is_err() {
                    self.iter_error = Some(j.as_ref().err().unwrap().clone());
                    self.iter_finished = true;
                }
                return Some(j);
            } else {
                self.iter_finished = true;
                return Some(Err(v.err().unwrap()));
            }
        } else {
            self.iter_finished = true;
            return None;
        }
    }
}

pub fn map<T: 'static, J: 'static>(iter: Box<dyn Iterator<Item=Result<T,Error>>>, pred: fn(T)->Result<J, Error>) -> Box<dyn Iterator<Item=Result<J, Error>>> 
{
    return Box::new(Map {
        iter,
        pred: pred,
        iter_finished: false,
        iter_error: None
    });
}


struct Map2<T0, T1, J> {
    iter0: Box<dyn Iterator<Item=Result<T0,Error>>>,
    iter1: Box<dyn Iterator<Item=Result<T1,Error>>>,
    pred: fn(&T0, &T1)->Result<J, Error>,
    iter_finished: bool,
    iter_error: Option<Error>
}

impl<T0, T1, J> Iterator for Map2<T0, T1, J>
{
    type Item = Result<J, Error>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.iter_finished {
            return None;
        }
        
        if self.iter_error.is_some() {
            return Some(Err(self.iter_error.as_ref().unwrap().clone()));
        }

        let _next0 = self.iter0.next();
        let _next1 = self.iter1.next();
        match (&_next0, &_next1) {
            (Some(v0), Some(v1)) => {
                match (v0, v1) {
                    (Ok(v0_t), Ok(v1_t)) => {
                        let j = (self.pred)(v0_t, v1_t);
                        if j.is_err() {
                            self.iter_error = Some(j.as_ref().err().unwrap().clone());
                            self.iter_finished = true;
                        }
                        return Some(j);
                    }, 
                    _ => {
                        if v0.is_err() {
                            self.iter_error = Some(error::any_error(v0.as_ref().err().unwrap().kind(), 
                            "[map.v0] ".to_string()+v0.as_ref().err().unwrap().message().unwrap()));

                            self.iter_finished = true;
                            return Some(Err(self.iter_error.as_ref().unwrap().clone()));
                        } else {
                            self.iter_error = Some(error::any_error(v1.as_ref().err().unwrap().kind(), 
                            "[map.v1] ".to_string()+v1.as_ref().err().unwrap().message().unwrap()));

                            self.iter_finished = true;
                            return Some(Err(self.iter_error.as_ref().unwrap().clone()));
                        }
                    }
                }
            },
            _ => {
                self.iter_finished = true;
                return None;
            },
        }
    }
}

pub fn map2<T0: 'static, T1: 'static, J: 'static>(
    iter0: Box<dyn Iterator<Item = Result<T0,Error>>>, 
    iter1: Box<dyn Iterator<Item = Result<T1,Error>>>,
    pred: fn(&T0,&T1)->Result<J,Error>) -> Box<dyn Iterator<Item = Result<J,Error>>> 
{
    return Box::new(Map2 {
        iter0,
        iter1,
        pred: pred,
        iter_finished: false,
        iter_error: None
    });
}


#[cfg(test)]
mod tests {
    use crate::{error, utils::{extract_value_from_result_vec, generate_okok_iterator, generate_okokerr_iterator}};

    use super::*;

    #[test]
    fn test1() {
        let v = generate_okok_iterator(vec![1,2,3]);
        let ret = map(v, |x| {Ok(x==3)});
        let ret = extract_value_from_result_vec(ret.collect::<Vec<_>>());
        assert!(ret.1.is_none());
        assert_eq!(vec![false,false,true], ret.0);
    }

    #[test]
    fn test1_error() {
        let v = generate_okokerr_iterator(vec![1,2,3], error::overflow_error("for test".to_string()));
        let ret = map(v, |x| {Ok(x==3)});
        let ret = extract_value_from_result_vec(ret.collect::<Vec<_>>());
        assert!(ret.1.is_some());
        assert_eq!(vec![false,false,true], ret.0);
    }

    #[test]
    fn test2() {
        let v0 = generate_okok_iterator(vec![1,2,3]);
        let v1 = generate_okok_iterator(vec![2,3,4]);
        let ret = map2(v0, v1, |x,y| {Ok(x*y)});
        let ret = extract_value_from_result_vec(ret.collect::<Vec<_>>());
        assert!(ret.1.is_none());
        assert_eq!(vec![2,6,12], ret.0);
    }

    #[test]
    fn test2_result() {
        let v0 = generate_okok_iterator(vec![1,2,i32::MAX]);
        let v1 = generate_okok_iterator(vec![2,3,4]);
        let mut ret = map2(
            v0, 
            v1, 
            |x,y| {
                let ret = x.overflowing_mul(*y);
                if ret.1 {
                    return Err(error::any_error(error::Kind::OverflowError, "multiple overflow.".to_string()));
                } else {
                    return Ok(ret.0);
                }
            }
        );
        assert_eq!(Ok(2), ret.next().unwrap());
        assert_eq!(Ok(6), ret.next().unwrap());
        assert_eq!(error::Kind::OverflowError, ret.next().unwrap().err().unwrap().kind());
        assert_eq!(None, ret.next());
    }
}