1 #[cfg(doc)]
2 use crate::Itertools;
3
4 /// An iterator that produces only the `T` values as long as the
5 /// inner iterator produces `Ok(T)`.
6 ///
7 /// Used by [`process_results`](crate::process_results), see its docs
8 /// for more information.
9 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
10 #[derive(Debug)]
11 pub struct ProcessResults<'a, I, E: 'a> {
12 error: &'a mut Result<(), E>,
13 iter: I,
14 }
15
16 impl<'a, I, E> ProcessResults<'a, I, E> {
17 #[inline(always)]
next_body<T>(&mut self, item: Option<Result<T, E>>) -> Option<T>18 fn next_body<T>(&mut self, item: Option<Result<T, E>>) -> Option<T> {
19 match item {
20 Some(Ok(x)) => Some(x),
21 Some(Err(e)) => {
22 *self.error = Err(e);
23 None
24 }
25 None => None,
26 }
27 }
28 }
29
30 impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E>
31 where
32 I: Iterator<Item = Result<T, E>>,
33 {
34 type Item = T;
35
next(&mut self) -> Option<Self::Item>36 fn next(&mut self) -> Option<Self::Item> {
37 let item = self.iter.next();
38 self.next_body(item)
39 }
40
size_hint(&self) -> (usize, Option<usize>)41 fn size_hint(&self) -> (usize, Option<usize>) {
42 (0, self.iter.size_hint().1)
43 }
44
fold<B, F>(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B,45 fn fold<B, F>(mut self, init: B, mut f: F) -> B
46 where
47 Self: Sized,
48 F: FnMut(B, Self::Item) -> B,
49 {
50 let error = self.error;
51 self.iter
52 .try_fold(init, |acc, opt| match opt {
53 Ok(x) => Ok(f(acc, x)),
54 Err(e) => {
55 *error = Err(e);
56 Err(acc)
57 }
58 })
59 .unwrap_or_else(|e| e)
60 }
61 }
62
63 impl<'a, I, T, E> DoubleEndedIterator for ProcessResults<'a, I, E>
64 where
65 I: Iterator<Item = Result<T, E>>,
66 I: DoubleEndedIterator,
67 {
next_back(&mut self) -> Option<Self::Item>68 fn next_back(&mut self) -> Option<Self::Item> {
69 let item = self.iter.next_back();
70 self.next_body(item)
71 }
72
rfold<B, F>(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B,73 fn rfold<B, F>(mut self, init: B, mut f: F) -> B
74 where
75 F: FnMut(B, Self::Item) -> B,
76 {
77 let error = self.error;
78 self.iter
79 .try_rfold(init, |acc, opt| match opt {
80 Ok(x) => Ok(f(acc, x)),
81 Err(e) => {
82 *error = Err(e);
83 Err(acc)
84 }
85 })
86 .unwrap_or_else(|e| e)
87 }
88 }
89
90 /// “Lift” a function of the values of an iterator so that it can process
91 /// an iterator of `Result` values instead.
92 ///
93 /// [`IntoIterator`] enabled version of [`Itertools::process_results`].
process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E> where I: IntoIterator<Item = Result<T, E>>, F: FnOnce(ProcessResults<I::IntoIter, E>) -> R,94 pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E>
95 where
96 I: IntoIterator<Item = Result<T, E>>,
97 F: FnOnce(ProcessResults<I::IntoIter, E>) -> R,
98 {
99 let iter = iterable.into_iter();
100 let mut error = Ok(());
101
102 let result = processor(ProcessResults {
103 error: &mut error,
104 iter,
105 });
106
107 error.map(|_| result)
108 }
109