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