more-itertools 0.1.6

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

pub struct SubstringsIndexes<T> {
    string_len: usize,
    substring_len: usize,
    cur: usize,
    vec: Vec<T>,
    reverse: bool,
    upstream_error: Option<Error>,
    iter_finished: bool,
}

impl<T> Iterator for SubstringsIndexes<T>
where
T: Clone
{
    type Item = Result<(Vec<T>, usize, usize), 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()));
        }

        if !self.reverse {
            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.as_slice()[self.cur..self.cur+self.substring_len] {
                        ret.push(ele.clone())
                    }
                    let cur = self.cur;
                    self.cur += 1;

                    return Some(Ok((ret, cur, cur+self.substring_len)));
                }
            }
        } else {
            loop {
                if self.substring_len <= 0 {
                    return None;
                }
    
                if self.cur == usize::MAX {
                    self.substring_len -= 1;
                    self.cur = self.string_len - self.substring_len;
                    continue;
                } else {
                    let mut ret = Vec::new();
                    for ele in &self.vec.as_slice()[self.cur..self.cur+self.substring_len] {
                        ret.push(ele.clone())
                    }
                    let cur = self.cur;
                    self.cur -= 1;

                    return Some(Ok((ret, cur, cur+self.substring_len)));
                }
            }
        }
    }
}


pub fn substrings_indexes<T>(mut iter: Box<dyn Iterator<Item = Result<T,Error>>>, reverse: bool) -> Box<dyn Iterator<Item = Result<(Vec<T>,usize,usize),Error>>> 
where
T: Clone + 'static
{
    let mut upstream_error: Option<Error> = None;

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

    let mut ret = SubstringsIndexes {
        string_len: vec.len(),
        substring_len: 1,
        cur: 0,
        vec,
        reverse,
        upstream_error,
        iter_finished: false,
    };

    if ret.reverse {
        ret.substring_len = ret.string_len;
        ret.cur = ret.string_len - ret.substring_len;
    }

    return Box::new(ret);
}

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

    use super::*;

    #[test]
    fn test1() {
        let v = generate_okok_iterator("more".to_string().chars().collect());
        let mut ssi = substrings_indexes(v, false);

        assert_eq!(Some((vec!['m'], 0 as usize, 1 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['o'], 1 as usize, 2 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['r'], 2 as usize, 3 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['e'], 3 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['m', 'o'], 0 as usize, 2 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['o', 'r'], 1 as usize, 3 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['r', 'e'], 2 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['m', 'o', 'r'], 0 as usize, 3 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['o', 'r', 'e'], 1 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['m', 'o', 'r', 'e'], 0 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(None, ssi.next());
    }

    #[test]
    fn test2() {
        let v = generate_okok_iterator("more".to_string().chars().collect());
        let mut ssi = substrings_indexes(v, true);

        assert_eq!(Some((vec!['m', 'o', 'r', 'e'], 0 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['o', 'r', 'e'], 1 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['m', 'o', 'r'], 0 as usize, 3 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['r', 'e'], 2 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['o', 'r'], 1 as usize, 3 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['m', 'o'], 0 as usize, 2 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['e'], 3 as usize, 4 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['r'], 2 as usize, 3 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['o'], 1 as usize, 2 as usize)), ssi.next().unwrap().ok());
        assert_eq!(Some((vec!['m'], 0 as usize, 1 as usize)), ssi.next().unwrap().ok());
        assert_eq!(None, ssi.next());
    }

    #[test]
    fn test3() {
        let v = generate_okokerr_iterator("more".to_string().chars().collect(), error::overflow_error("[test]".to_string()));
        let mut ssi = substrings_indexes(v, true);
        assert_eq!(error::Kind::OverflowError, ssi.next().unwrap().err().unwrap().kind());
    }
}