iterator_ext/
lib.rs

1//! An extension to Iterator trait.
2//!
3//! The [`IteratorExt`](IteratorExt) trait extends the capability of those types
4//! that implements [`Iterator`](Iterator). It provides `try_filter()`, `try_flatten()`
5//! and more fallible adaptors that are analogous to those of [`Iterator`](Iterator).
6//!
7//! The example demonstrates the usage of the adaptors. It accumulates the values from
8//! 0 to 9, and keeps only even outcomes. It raises error when the accumulation exceeds 10.
9//!
10//! ```rust
11//! use iterator_ext::IteratorExt;
12//!
13//! let results: Vec<_> = (0..10)
14//!     .map(Ok)
15//!     .try_scan(0, |acc, val| {
16//!         *acc += val;
17//!         if *acc <= 10 {
18//!             Ok(Some(*acc))
19//!         } else {
20//!             Err("exceed limit")
21//!         }
22//!     })
23//!     .try_filter(|val| Ok(val % 2 == 0))
24//!     .collect();
25//!
26//! assert_eq!(results, vec![Ok(0), Ok(6), Ok(10), Err("exceed limit")]);
27//! ```
28
29mod and_then;
30mod common;
31mod map_err;
32mod trait_;
33mod try_filter;
34mod try_filter_map;
35mod try_flat_map;
36mod try_flat_map_results;
37mod try_flatten;
38mod try_flatten_results;
39mod try_scan;
40mod try_unfold;
41
42pub use and_then::*;
43pub use map_err::*;
44pub use trait_::*;
45pub use try_filter::*;
46pub use try_filter_map::*;
47pub use try_flat_map::*;
48pub use try_flat_map_results::*;
49pub use try_flatten::*;
50pub use try_flatten_results::*;
51pub use try_scan::*;
52pub use try_unfold::*;
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn try_scan_test_1() {
60        let input = vec![Ok(1usize), Ok(2), Err("err"), Ok(3)];
61        let output: Vec<_> = input
62            .into_iter()
63            .try_scan(0, |acc, val| {
64                *acc += val;
65                Ok(Some(*acc))
66            })
67            .collect();
68        assert_eq!(output, vec![Ok(1), Ok(3), Err("err")]);
69    }
70
71    #[test]
72    fn try_scan_test_2() {
73        let input = vec![Ok(1usize), Ok(2), Err("err"), Ok(3)];
74        let output: Vec<_> = input
75            .into_iter()
76            .try_scan(0, |acc, val| {
77                if val % 2 != 0 {
78                    *acc += val;
79                    Ok(Some(*acc))
80                } else {
81                    Ok(None)
82                }
83            })
84            .collect();
85        assert_eq!(output, vec![Ok(1)]);
86    }
87
88    #[test]
89    fn try_scan_test_3() {
90        let input = vec![Ok(1usize), Ok(3), Ok(2)];
91        let output: Vec<_> = input
92            .into_iter()
93            .try_scan(0, |acc, val| {
94                if val % 2 != 0 {
95                    *acc += val;
96                    Ok(Some(*acc))
97                } else {
98                    Err("found even")
99                }
100            })
101            .collect();
102        assert_eq!(output, vec![Ok(1), Ok(4), Err("found even")]);
103    }
104
105    #[test]
106    fn try_flatten_test() {
107        let input = vec![Ok(vec![1usize, 2]), Err("err"), Ok(vec![3])];
108        let output: Vec<_> = input.into_iter().try_flatten().collect();
109        assert_eq!(output, vec![Ok(1), Ok(2), Err("err")]);
110    }
111
112    #[test]
113    fn try_flat_map_test() {
114        let input = vec![Ok(vec![1, 2]), Err("err"), Ok(vec![3])];
115        let output: Vec<_> = input.into_iter().try_flat_map(Ok).collect();
116        assert_eq!(output, vec![Ok(1usize), Ok(2), Err("err")]);
117    }
118
119    #[test]
120    fn try_flatten_results_test_1() {
121        let input = vec![
122            Ok(vec![Ok(1usize), Ok(2)]),
123            Ok(vec![Err("err"), Ok(3)]),
124            Ok(vec![Ok(4)]),
125        ];
126        let output: Vec<_> = input.into_iter().try_flatten_results().collect();
127        assert_eq!(output, vec![Ok(1usize), Ok(2), Err("err")]);
128    }
129
130    #[test]
131    fn try_flatten_results_test_2() {
132        let input = vec![Ok(vec![Ok(1usize), Ok(2)]), Err("err"), Ok(vec![Ok(3)])];
133        let output: Vec<_> = input.into_iter().try_flatten_results().collect();
134        assert_eq!(output, vec![Ok(1usize), Ok(2), Err("err")]);
135    }
136
137    #[test]
138    fn try_flat_map_results_test_1() {
139        let input = vec![
140            Ok(vec![Ok(1usize), Ok(2)]),
141            Ok(vec![Err("err"), Ok(3)]),
142            Ok(vec![Ok(4)]),
143        ];
144        let output: Vec<_> = input.into_iter().try_flat_map_results(Ok).collect();
145        assert_eq!(output, vec![Ok(1usize), Ok(2), Err("err")]);
146    }
147
148    #[test]
149    fn try_flat_map_results_test_2() {
150        let input = vec![Ok(vec![Ok(1usize), Ok(2)]), Err("err"), Ok(vec![Ok(3)])];
151        let output: Vec<_> = input.into_iter().try_flat_map_results(Ok).collect();
152        assert_eq!(output, vec![Ok(1usize), Ok(2), Err("err")]);
153    }
154
155    #[test]
156    fn try_filter_test() {
157        let input = vec![Ok(1usize), Ok(2), Ok(3), Err("err"), Ok(4)];
158        let output: Vec<_> = input
159            .into_iter()
160            .try_filter(|val| Ok(val % 2 == 1))
161            .collect();
162        assert_eq!(output, vec![Ok(1usize), Ok(3), Err("err")]);
163    }
164
165    #[test]
166    fn try_filter_map_test() {
167        let input = vec![
168            Ok(Some(1usize)),
169            Ok(None),
170            Ok(Some(3usize)),
171            Err("err"),
172            Ok(Some(4usize)),
173        ];
174        let output: Vec<_> = input.into_iter().try_filter_map(Ok).collect();
175        assert_eq!(output, vec![Ok(1usize), Ok(3), Err("err")]);
176    }
177
178    #[test]
179    fn and_then_test() {
180        let input = vec![Ok(1isize), Ok(2), Err("err"), Ok(3)];
181        let output: Vec<_> = input.into_iter().and_then(|val| Ok(-val)).collect();
182        assert_eq!(output, vec![Ok(-1), Ok(-2), Err("err")]);
183    }
184
185    #[test]
186    fn try_unfold_test() {
187        {
188            let vec: Vec<_> = try_unfold(0, |count| {
189                let idx = *count;
190                *count += 1;
191
192                if idx >= 3 {
193                    Err(idx)
194                } else {
195                    Ok(Some(idx))
196                }
197            })
198            .collect();
199
200            assert_eq!(vec, [Ok(0), Ok(1), Ok(2), Err(3)]);
201        }
202
203        {
204            let vec: Vec<_> = try_unfold(0, |count| {
205                let idx = *count;
206                *count += 1;
207
208                if idx >= 4 {
209                    Err(idx)
210                } else if idx >= 3 {
211                    Ok(None)
212                } else {
213                    Ok(Some(idx))
214                }
215            })
216            .collect();
217
218            assert_eq!(vec, [Ok(0), Ok(1), Ok(2)]);
219        }
220    }
221}