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}