resiter_dpc_tmp/
filter.rs

1//
2// This Source Code Form is subject to the terms of the Mozilla Public
3// License, v. 2.0. If a copy of the MPL was not distributed with this
4// file, You can obtain one at http://mozilla.org/MPL/2.0/.
5//
6
7/// Extension trait for `Iterator<Item = Result<O, E>>` to filter one kind of result (and leaving the other as is)
8pub trait Filter<O, E>: Sized {
9    fn filter_ok<F>(self, F) -> FilterOk<Self, F>
10    where
11        F: FnMut(&O) -> bool;
12    fn filter_err<F>(self, F) -> FilterErr<Self, F>
13    where
14        F: FnMut(&E) -> bool;
15}
16
17impl<I, O, E> Filter<O, E> for I
18where
19    I: Iterator<Item = Result<O, E>> + Sized,
20{
21    fn filter_ok<F>(self, f: F) -> FilterOk<Self, F>
22    where
23        F: FnMut(&O) -> bool,
24    {
25        FilterOk { iter: self, f }
26    }
27    fn filter_err<F>(self, f: F) -> FilterErr<Self, F>
28    where
29        F: FnMut(&E) -> bool,
30    {
31        FilterErr { iter: self, f }
32    }
33}
34
35#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
36pub struct FilterOk<I, F> {
37    iter: I,
38    f: F,
39}
40
41impl<I, O, E, F> Iterator for FilterOk<I, F>
42where
43    I: Iterator<Item = Result<O, E>>,
44    F: FnMut(&O) -> bool,
45{
46    type Item = Result<O, E>;
47
48    fn next(&mut self) -> Option<Self::Item> {
49        loop {
50            match self.iter.next() {
51                Some(Ok(x)) => {
52                    if (self.f)(&x) {
53                        return Some(Ok(x));
54                    }
55                }
56                other => {
57                    return other;
58                }
59            }
60        }
61    }
62
63    #[inline]
64    fn size_hint(&self) -> (usize, Option<usize>) {
65        let hint_sup = self.iter.size_hint().1;
66        (0, hint_sup)
67    }
68}
69
70#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
71pub struct FilterErr<I, F> {
72    iter: I,
73    f: F,
74}
75
76impl<I, O, E, F> Iterator for FilterErr<I, F>
77where
78    I: Iterator<Item = Result<O, E>>,
79    F: FnMut(&E) -> bool,
80{
81    type Item = Result<O, E>;
82
83    fn next(&mut self) -> Option<Self::Item> {
84        loop {
85            match self.iter.next() {
86                Some(Err(x)) => {
87                    if (self.f)(&x) {
88                        return Some(Err(x));
89                    }
90                }
91                other => {
92                    return other;
93                }
94            }
95        }
96    }
97
98    #[inline]
99    fn size_hint(&self) -> (usize, Option<usize>) {
100        let hint_sup = self.iter.size_hint().1;
101        (0, hint_sup)
102    }
103}
104
105#[test]
106fn test_filter_ok() {
107    use std::str::FromStr;
108
109    let mapped: Vec<_> = ["1", "2", "a", "4", "5"]
110        .into_iter()
111        .map(|txt| usize::from_str(txt))
112        .filter_ok(|i| i % 2 == 0)
113        .collect();
114
115    assert_eq!(mapped.len(), 3);
116    assert_eq!(mapped[0], Ok(2));
117    assert_eq!(mapped[2], Ok(4));
118}
119
120#[test]
121fn test_filter_ok_hint() {
122    use std::str::FromStr;
123
124    let hint = ["1", "2", "a", "4", "5"]
125        .into_iter()
126        .map(|txt| usize::from_str(txt))
127        .filter_ok(|i| i % 2 == 0)
128        .size_hint();
129
130    assert_eq!(hint, (0, Some(5)));
131}
132
133#[test]
134fn test_filter_err() {
135    use std::str::FromStr;
136
137    let mapped: Vec<_> = ["1", "2", "a", "4", "5"]
138        .into_iter()
139        .map(|txt| usize::from_str(txt))
140        .filter_err(|_| false)
141        .collect();
142
143    assert_eq!(mapped, vec![Ok(1), Ok(2), Ok(4), Ok(5)]);
144}
145
146#[test]
147fn test_filter_err_hint() {
148    use std::str::FromStr;
149
150    let hint = ["1", "2", "a", "4", "5"]
151        .into_iter()
152        .map(|txt| usize::from_str(txt))
153        .filter_err(|_| false)
154        .size_hint();
155
156    assert_eq!(hint, (0, Some(5)));
157}