1use std::mem::swap;
2
3use crate::error::Error;
4use crate::error;
5
6pub struct Chunked<T> {
7 iter: Box<dyn Iterator<Item = T>>,
8 buf: Vec<T>,
9 n: usize,
10 strict: bool
11}
12
13
14impl<T> Iterator for Chunked<T> {
15 type Item = Result<Vec<T>, Error>;
16
17 fn next(&mut self) -> Option<Self::Item> {
18 if self.n == 0 {
19 return Some(Err(error::value_error(String::from("n should not be 0"))));
20 }
21
22 let mut ret = Vec::new();
23 while self.buf.len() < self.n {
24 let ele = self.iter.next();
25 match ele {
26 Some(ele_value) => { self.buf.push(ele_value) }
27 None => {
28 if self.buf.len() == 0 {
29 return None;
30 } else {
31 swap(&mut ret, &mut self.buf);
32 self.buf = Vec::new();
33 if self.strict && ret.len() < self.n {
34 return Some(Err(error::value_error(String::from("iterable is not divisible by n."))));
35 }
36 return Some(Ok(ret));
37 }
38 }
39 }
40
41 if self.buf.len() == self.n {
42 ret = Vec::new();
43 swap(&mut ret, &mut self.buf);
44 return Some(Ok(ret));
45 }
46 }
47
48 return Some(Ok(ret));
49
50 }
51}
52
53pub fn chunked<T>(iter: Box<dyn Iterator<Item = T>>, n: usize, strict: bool) -> Box<dyn Iterator<Item = Result<Vec<T>, Error>>>
55where
56 T: 'static,
57{
58 Box::new(Chunked {
59 iter,
60 buf: Vec::new(),
61 n,
62 strict
63 })
64}
65
66
67#[cfg(test)]
68mod tests {
69 use crate::itertools::iter::iter_from_vec;
70
71 use super::*;
72
73 #[test]
74 fn test1_no_strict() {
75 let mut it = chunked(iter_from_vec(vec![1,2,3,4,5,6,7,8,9,10]), 3, false);
76
77 assert_eq!(vec![1,2,3], it.next().unwrap().ok().unwrap());
78 assert_eq!(vec![4,5,6], it.next().unwrap().ok().unwrap());
79 assert_eq!(vec![7,8,9], it.next().unwrap().ok().unwrap());
80 assert_eq!(vec![10], it.next().unwrap().ok().unwrap());
81 assert_eq!(None, it.next());
82 assert_eq!(None, it.next());
83 }
84
85 #[test]
86 fn test2_strict() {
87 let mut it = chunked(iter_from_vec(vec![1,2,3,4,5,6,7,8,9,10]), 3, true);
88
89 assert_eq!(vec![1,2,3], it.next().unwrap().ok().unwrap());
90 assert_eq!(vec![4,5,6], it.next().unwrap().ok().unwrap());
91 assert_eq!(vec![7,8,9], it.next().unwrap().ok().unwrap());
92
93 assert_eq!(error::Kind::ValueError, it.next().unwrap().err().unwrap().kind());
94 }
95
96 #[test]
97 fn test3_no_strict_chars() {
98 let mut it = chunked(iter_from_vec("abcdefghij".chars().collect()), 3, false);
99
100 assert_eq!(vec!['a', 'b', 'c'], it.next().unwrap().ok().unwrap());
101 assert_eq!(vec!['d', 'e', 'f'], it.next().unwrap().ok().unwrap());
102 assert_eq!(vec!['g', 'h', 'i'], it.next().unwrap().ok().unwrap());
103 assert_eq!(vec!['j'], it.next().unwrap().ok().unwrap());
104
105 assert_eq!(None, it.next());
106 assert_eq!(None, it.next());
107 }
108
109 #[test]
110 fn test3_no_strict_string() {
111 let v = vec![String::from("1"),
112 String::from("2"),
113 String::from("3"),
114 String::from("4")
115 ];
116
117 let mut it = chunked(iter_from_vec(v), 3, false);
118
119 assert_eq!(vec![String::from("1"), String::from("2") ,String::from("3")], it.next().unwrap().ok().unwrap());
120 assert_eq!(vec![String::from("4")], it.next().unwrap().ok().unwrap());
121
122 assert_eq!(None, it.next());
123 assert_eq!(None, it.next());
124 }
125
126 #[test]
127 fn test4_value_error_n_is_0() {
128 let mut it = chunked(iter_from_vec(vec![1,2,3,4,5,6,7,8,9,10]), 0, false);
129 assert_eq!(error::Kind::ValueError, it.next().unwrap().err().unwrap().kind());
130 }
131}
132