1use std::ops::Try;
2
3use rustc_errors::ErrorGuaranteed;
4
5use crate::result::ErrorCollector;
6
7pub trait IterExt: Iterator {
8 fn try_collect_vec<T, E>(self) -> Result<Vec<T>, E>
9 where
10 Self: Sized + Iterator<Item = Result<T, E>>,
11 {
12 self.collect()
13 }
14
15 fn collect_errors<T, E, C>(self, collector: &mut C) -> CollectErrors<Self, C>
16 where
17 Self: Iterator<Item = Result<T, E>> + Sized,
18 C: ErrorCollector<E>,
19 {
20 CollectErrors { iter: self, collector }
21 }
22
23 fn try_collect_exhaust<T, V>(self) -> Result<V, ErrorGuaranteed>
24 where
25 V: FromIterator<T>,
26 Self: Iterator<Item = Result<T, ErrorGuaranteed>> + Sized,
27 {
28 let mut acc: Option<ErrorGuaranteed> = None;
29 let v = self.collect_errors(&mut acc).collect();
30 match acc {
31 Some(e) => Err(e),
32 None => Ok(v),
33 }
34 }
35
36 fn try_for_each_exhaust<T, F>(self, mut f: F) -> Result<(), ErrorGuaranteed>
37 where
38 Self: Iterator<Item = T> + Sized,
39 F: FnMut(T) -> Result<(), ErrorGuaranteed>,
40 {
41 let mut acc: Option<ErrorGuaranteed> = None;
42 for v in self {
43 if let Err(e) = f(v) {
44 acc = Some(e).or(acc);
45 }
46 }
47 match acc {
48 Some(e) => Err(e),
49 None => Ok(()),
50 }
51 }
52
53 fn map_take_while<F, R>(&mut self, f: F) -> MapTakeWhile<Self, F>
54 where
55 Self: Clone,
56 F: FnMut(&Self::Item) -> Option<R>,
57 {
58 MapTakeWhile { iter: self, f }
59 }
60}
61
62impl<I: ?Sized> IterExt for I where I: Iterator {}
63
64pub struct CollectErrors<'a, I, C> {
65 iter: I,
66 collector: &'a mut C,
67}
68
69impl<I, T, E, F> Iterator for CollectErrors<'_, I, F>
70where
71 I: Iterator<Item = Result<T, E>>,
72 F: ErrorCollector<E>,
73{
74 type Item = T;
75
76 fn next(&mut self) -> Option<Self::Item> {
77 self.find(|_| true)
78 }
79
80 fn try_fold<B, F2, R2>(&mut self, init: B, mut f: F2) -> R2
81 where
82 F2: FnMut(B, Self::Item) -> R2,
83 R2: Try<Output = B>,
84 {
85 self.iter.try_fold(init, |acc, x| {
86 match x {
87 Ok(x) => f(acc, x),
88 Err(e) => {
89 self.collector.collect(e);
90 try { acc }
91 }
92 }
93 })
94 }
95
96 fn fold<B, F2>(mut self, init: B, fold: F2) -> B
97 where
98 Self: Sized,
99 F2: FnMut(B, Self::Item) -> B,
100 {
101 #[inline]
102 fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
103 move |acc, x| Ok(f(acc, x))
104 }
105
106 self.try_fold(init, ok(fold)).unwrap()
107 }
108}
109
110pub struct MapTakeWhile<'a, I: 'a, F> {
111 iter: &'a mut I,
112 f: F,
113}
114
115impl<'a, I, F, R> Iterator for MapTakeWhile<'a, I, F>
116where
117 I: 'a + Iterator + Clone,
118 F: FnMut(&I::Item) -> Option<R>,
119{
120 type Item = R;
121
122 fn next(&mut self) -> Option<Self::Item> {
123 let old = self.iter.clone();
124 match self.iter.next() {
125 None => None,
126 Some(elt) => {
127 if let Some(elt) = (self.f)(&elt) {
128 Some(elt)
129 } else {
130 *self.iter = old;
131 None
132 }
133 }
134 }
135 }
136}