1pub trait Filter<O, E>: Sized {
9 fn filter_ok<F>(self, _: F) -> FilterOk<Self, F>
26 where
27 F: FnMut(&O) -> bool;
28
29 fn filter_err<F>(self, _: F) -> FilterErr<Self, F>
44 where
45 F: FnMut(&E) -> bool;
46}
47
48impl<I, O, E> Filter<O, E> for I
49where
50 I: Iterator<Item = Result<O, E>> + Sized,
51{
52 #[inline]
53 fn filter_ok<F>(self, f: F) -> FilterOk<Self, F>
54 where
55 F: FnMut(&O) -> bool,
56 {
57 FilterOk { iter: self, f }
58 }
59
60 #[inline]
61 fn filter_err<F>(self, f: F) -> FilterErr<Self, F>
62 where
63 F: FnMut(&E) -> bool,
64 {
65 FilterErr { iter: self, f }
66 }
67}
68
69#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
70pub struct FilterOk<I, F> {
71 iter: I,
72 f: F,
73}
74
75impl<I, O, E, F> Iterator for FilterOk<I, F>
76where
77 I: Iterator<Item = Result<O, E>>,
78 F: FnMut(&O) -> bool,
79{
80 type Item = Result<O, E>;
81
82 fn next(&mut self) -> Option<Self::Item> {
83 loop {
84 match self.iter.next() {
85 Some(Ok(x)) => {
86 if (self.f)(&x) {
87 return Some(Ok(x));
88 }
89 }
90 other => {
91 return other;
92 }
93 }
94 }
95 }
96
97 #[inline]
98 fn size_hint(&self) -> (usize, Option<usize>) {
99 let hint_sup = self.iter.size_hint().1;
100 (0, hint_sup)
101 }
102}
103
104#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
105pub struct FilterErr<I, F> {
106 iter: I,
107 f: F,
108}
109
110impl<I, O, E, F> Iterator for FilterErr<I, F>
111where
112 I: Iterator<Item = Result<O, E>>,
113 F: FnMut(&E) -> bool,
114{
115 type Item = Result<O, E>;
116
117 fn next(&mut self) -> Option<Self::Item> {
118 loop {
119 match self.iter.next() {
120 Some(Err(x)) => {
121 if (self.f)(&x) {
122 return Some(Err(x));
123 }
124 }
125 other => {
126 return other;
127 }
128 }
129 }
130 }
131
132 #[inline]
133 fn size_hint(&self) -> (usize, Option<usize>) {
134 let hint_sup = self.iter.size_hint().1;
135 (0, hint_sup)
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_filter_ok_hint() {
145 use std::str::FromStr;
146
147 let hint = ["1", "2", "a", "4", "5"]
148 .iter()
149 .map(|txt| usize::from_str(txt))
150 .filter_ok(|i| i % 2 == 0)
151 .size_hint();
152
153 assert_eq!(hint, (0, Some(5)));
154 }
155
156 #[test]
157 fn test_filter_err_hint() {
158 use std::str::FromStr;
159
160 let hint = ["1", "2", "a", "4", "5"]
161 .iter()
162 .map(|txt| usize::from_str(txt))
163 .filter_err(|_| false)
164 .size_hint();
165
166 assert_eq!(hint, (0, Some(5)));
167 }
168}