resiter_dpc_tmp/
filter_map.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 selectively transform and map Oks and Errors.
8pub trait FilterMap<O, E>: Sized {
9    fn filter_map_ok<F, O2>(self, F) -> FilterMapOk<Self, F>
10    where
11        F: FnMut(O) -> Option<O2>;
12    fn filter_map_err<F, E2>(self, F) -> FilterMapErr<Self, F>
13    where
14        F: FnMut(E) -> Option<E2>;
15}
16
17impl<I, O, E> FilterMap<O, E> for I
18where
19    I: Iterator<Item = Result<O, E>> + Sized,
20{
21    fn filter_map_ok<F, O2>(self, f: F) -> FilterMapOk<Self, F>
22    where
23        F: FnMut(O) -> Option<O2>,
24    {
25        FilterMapOk { iter: self, f }
26    }
27    fn filter_map_err<F, E2>(self, f: F) -> FilterMapErr<Self, F>
28    where
29        F: FnMut(E) -> Option<E2>,
30    {
31        FilterMapErr { iter: self, f }
32    }
33}
34
35#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
36pub struct FilterMapOk<I, F> {
37    iter: I,
38    f: F,
39}
40
41impl<I, O, E, F, O2> Iterator for FilterMapOk<I, F>
42where
43    I: Iterator<Item = Result<O, E>>,
44    F: FnMut(O) -> Option<O2>,
45{
46    type Item = Result<O2, E>;
47
48    fn next(&mut self) -> Option<Self::Item> {
49        loop {
50            match self.iter.next() {
51                Some(Ok(x)) => {
52                    if let Some(x) = (self.f)(x) {
53                        return Some(Ok(x));
54                    }
55                }
56                Some(Err(e)) => return Some(Err(e)),
57                None => return None,
58            }
59        }
60    }
61
62    #[inline]
63    fn size_hint(&self) -> (usize, Option<usize>) {
64        self.iter.size_hint()
65    }
66}
67
68#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
69pub struct FilterMapErr<I, F> {
70    iter: I,
71    f: F,
72}
73
74impl<I, O, E, F, E2> Iterator for FilterMapErr<I, F>
75where
76    I: Iterator<Item = Result<O, E>>,
77    F: FnMut(E) -> Option<E2>,
78{
79    type Item = Result<O, E2>;
80
81    fn next(&mut self) -> Option<Self::Item> {
82        loop {
83            match self.iter.next() {
84                Some(Ok(x)) => return Some(Ok(x)),
85                Some(Err(e)) => {
86                    if let Some(e) = (self.f)(e) {
87                        return Some(Err(e));
88                    }
89                }
90                None => return None,
91            }
92        }
93    }
94    #[inline]
95    fn size_hint(&self) -> (usize, Option<usize>) {
96        self.iter.size_hint()
97    }
98}
99
100#[test]
101fn test_filter_map_ok() {
102    use std::str::FromStr;
103
104    let filter_mapped: Vec<_> = vec![
105        Ok("1"),
106        Err("2"),
107        Ok("a"),
108        Err("4"),
109        Ok("5"),
110        Err("b"),
111        Err("8"),
112    ].into_iter()
113    .filter_map_ok(|txt| usize::from_str(txt).ok())
114    .filter_map_err(|txt| usize::from_str(txt).ok().map(|i| i * 3))
115    .collect();
116
117    assert_eq!(filter_mapped[0], Ok(1));
118    assert_eq!(filter_mapped[1], Err(2 * 3));
119    assert_eq!(filter_mapped[2], Err(4 * 3));
120    assert_eq!(filter_mapped[3], Ok(5));
121    assert_eq!(filter_mapped[4], Err(8 * 3));
122}
123
124#[test]
125fn test_filter_map_ok_hint() {
126    use std::str::FromStr;
127
128    let hint = ["1", "2", "a", "4", "5"]
129        .into_iter()
130        .map(|txt| usize::from_str(txt))
131        .filter_map_ok(|i| Some(2 * i))
132        .size_hint();
133
134    assert_eq!(hint, (5, Some(5)));
135}
136
137#[test]
138fn test_filter_map_err_hint() {
139    use std::str::FromStr;
140
141    let hint = ["1", "2", "a", "4", "5"]
142        .into_iter()
143        .map(|txt| usize::from_str(txt))
144        .filter_map_err(|e| Some(format!("{:?}", e)))
145        .size_hint();
146
147    assert_eq!(hint, (5, Some(5)));
148}