resiter_dpc_tmp/
and_then.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 Oks and Errors.
8pub trait AndThen<O, E>: Sized {
9    fn and_then_ok<F, O2>(self, F) -> AndThenOk<Self, F>
10    where
11        F: FnMut(O) -> Result<O2, E>;
12    fn and_then_err<F, E2>(self, F) -> AndThenErr<Self, F>
13    where
14        F: FnMut(E) -> Result<O, E2>;
15}
16
17impl<I, O, E> AndThen<O, E> for I
18where
19    I: Iterator<Item = Result<O, E>> + Sized,
20{
21    fn and_then_ok<F, O2>(self, f: F) -> AndThenOk<Self, F>
22    where
23        F: FnMut(O) -> Result<O2, E>,
24    {
25        AndThenOk { iter: self, f }
26    }
27    fn and_then_err<F, E2>(self, f: F) -> AndThenErr<Self, F>
28    where
29        F: FnMut(E) -> Result<O, E2>,
30    {
31        AndThenErr { iter: self, f }
32    }
33}
34
35#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
36pub struct AndThenOk<I, F> {
37    iter: I,
38    f: F,
39}
40
41impl<I, O, E, O2, F> Iterator for AndThenOk<I, F>
42where
43    I: Iterator<Item = Result<O, E>>,
44    F: FnMut(O) -> Result<O2, E>,
45{
46    type Item = Result<O2, E>;
47
48    fn next(&mut self) -> Option<Self::Item> {
49        match self.iter.next() {
50            Some(Ok(o)) => Some((self.f)(o)),
51            Some(Err(e)) => Some(Err(e)),
52            None => None,
53        }
54    }
55
56    #[inline]
57    fn size_hint(&self) -> (usize, Option<usize>) {
58        self.iter.size_hint()
59    }
60}
61
62#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
63pub struct AndThenErr<I, F> {
64    iter: I,
65    f: F,
66}
67
68impl<I, O, E, E2, F> Iterator for AndThenErr<I, F>
69where
70    I: Iterator<Item = Result<O, E>>,
71    F: FnMut(E) -> Result<O, E2>,
72{
73    type Item = Result<O, E2>;
74
75    fn next(&mut self) -> Option<Self::Item> {
76        match self.iter.next() {
77            Some(Err(e)) => Some((self.f)(e)),
78            Some(Ok(o)) => Some(Ok(o)),
79            None => None,
80        }
81    }
82
83    #[inline]
84    fn size_hint(&self) -> (usize, Option<usize>) {
85        self.iter.size_hint()
86    }
87}
88
89#[test]
90fn test_and_then_ok() {
91    use std::str::FromStr;
92
93    let mapped: Vec<_> = ["1", "2", "a", "b", "4", "5"]
94        .into_iter()
95        .map(|txt| usize::from_str(txt).map_err(|e| (txt, e)))
96        .and_then_ok(|i| Ok(2 * i))
97        .and_then_err(|(txt, e)| if txt == &"a" { Ok(15) } else { Err(e) })
98        .collect();
99
100    assert_eq!(mapped[0], Ok(2));
101    assert_eq!(mapped[1], Ok(4));
102    assert_eq!(mapped[2], Ok(15));
103    assert!(mapped[3].is_err());
104    assert_eq!(mapped[4], Ok(8));
105    assert_eq!(mapped[5], Ok(10));
106}