process_results/
raw_iter.rs1use crate::errors::{ControlFlow, ErrorCollector};
2use crate::IterResult;
3
4#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
8#[derive(Debug)]
9pub struct RawIter<'c, I, C> {
10 pub(crate) iter: I,
11 pub(crate) errors: &'c mut C,
12}
13
14impl<I, C> Iterator for RawIter<'_, I, C>
15where
16 I: IterResult,
17 C: ErrorCollector<I::Error>,
18{
19 type Item = I::Ok;
20
21 #[inline]
22 fn next(&mut self) -> Option<Self::Item> {
23 loop {
24 match self.iter.next() {
25 Some(Ok(item)) => {
26 break item.into();
27 }
28 Some(Err(err)) => {
29 if let ControlFlow::Break = self.errors.push_err(err) {
30 break None;
31 }
32 }
33 None => {
34 break None;
35 }
36 }
37 }
38 }
39
40 #[inline]
41 fn fold<B, F>(self, init: B, f: F) -> B
42 where
43 Self: Sized,
44 F: FnMut(B, Self::Item) -> B,
45 {
46 let mut f = f; let Self { mut iter, errors } = self;
48 let res = iter.try_fold(init, |acc, item| match item {
49 Ok(ok) => Ok(f(acc, ok)),
50 Err(err) => {
51 if let ControlFlow::Break = errors.push_err(err) {
52 Err(acc)
53 } else {
54 Ok(acc)
55 }
56 }
57 });
58 match res {
59 Ok(inner) => inner,
60 Err(inner) => inner,
61 }
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use crate::raw_iter::RawIter;
68 use arrayvec::ArrayVec;
69 use std::ops::Add;
70
71 #[test]
72 fn test() {
73 let v = vec![
74 Ok(1i64),
75 Err("Error1"),
76 Ok(4),
77 Err("Error2"),
78 Ok(-3),
79 Err("Error3"),
80 Ok(10),
81 ];
82 let mut col = ArrayVec::<&str, 2>::new();
83 let iter = RawIter {
84 iter: v.into_iter(),
85 errors: &mut col,
86 };
87 assert_eq!(iter.collect::<Vec<_>>(), vec![1, 4, -3]);
88 assert_eq!(col.into_inner().unwrap(), ["Error1", "Error2"]);
89 }
90
91 #[test]
92 fn test_fold() {
93 let v = vec![
94 Ok(1i64),
95 Err("Error1"),
96 Ok(4),
97 Err("Error2"),
98 Ok(-3),
99 Err("Error3"),
100 Ok(10),
101 ];
102 let mut col = ArrayVec::<&str, 2>::new();
103 let iter = RawIter {
104 iter: v.into_iter(),
105 errors: &mut col,
106 };
107 assert_eq!(iter.fold(0, i64::add), 2);
108 assert_eq!(col.into_inner().unwrap(), ["Error1", "Error2"]);
109 }
110}