1pub trait Map<O, E>: Sized {
9 fn map_ok<F, O2>(self, F) -> MapOk<Self, F>
10 where
11 F: FnMut(O) -> O2;
12 fn map_err<F, E2>(self, F) -> MapErr<Self, F>
13 where
14 F: FnMut(E) -> E2;
15}
16
17impl<I, O, E> Map<O, E> for I
18where
19 I: Iterator<Item = Result<O, E>> + Sized,
20{
21 fn map_ok<F, O2>(self, f: F) -> MapOk<Self, F>
22 where
23 F: FnMut(O) -> O2,
24 {
25 MapOk { iter: self, f }
26 }
27 fn map_err<F, E2>(self, f: F) -> MapErr<Self, F>
28 where
29 F: FnMut(E) -> E2,
30 {
31 MapErr { iter: self, f }
32 }
33}
34
35#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
36pub struct MapOk<I, F> {
37 iter: I,
38 f: F,
39}
40
41impl<I, O, E, F, O2> Iterator for MapOk<I, F>
42where
43 I: Iterator<Item = Result<O, E>>,
44 F: FnMut(O) -> O2,
45{
46 type Item = Result<O2, E>;
47
48 fn next(&mut self) -> Option<Self::Item> {
49 self.iter.next().map(|r| r.map(&mut self.f))
50 }
51
52 #[inline]
53 fn size_hint(&self) -> (usize, Option<usize>) {
54 self.iter.size_hint()
55 }
56}
57
58#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
59pub struct MapErr<I, F> {
60 iter: I,
61 f: F,
62}
63
64impl<I, O, E, F, E2> Iterator for MapErr<I, F>
65where
66 I: Iterator<Item = Result<O, E>>,
67 F: FnMut(E) -> E2,
68{
69 type Item = Result<O, E2>;
70
71 fn next(&mut self) -> Option<Self::Item> {
72 self.iter.next().map(|r| r.map_err(&mut self.f))
73 }
74
75 #[inline]
76 fn size_hint(&self) -> (usize, Option<usize>) {
77 self.iter.size_hint()
78 }
79}
80
81#[test]
82fn test_map_ok() {
83 use std::str::FromStr;
84
85 let mapped: Vec<_> = ["1", "2", "a", "4", "5"]
86 .into_iter()
87 .map(|txt| usize::from_str(txt))
88 .map_ok(|i| 2 * i)
89 .collect();
90
91 assert_eq!(mapped[0], Ok(2));
92 assert_eq!(mapped[1], Ok(4));
93 assert_eq!(mapped[3], Ok(8));
94 assert_eq!(mapped[4], Ok(10));
95}
96
97#[test]
98fn test_map_ok_hint() {
99 use std::str::FromStr;
100
101 let hint = ["1", "2", "a", "4", "5"]
102 .into_iter()
103 .map(|txt| usize::from_str(txt))
104 .map_ok(|i| 2 * i)
105 .size_hint();
106
107 assert_eq!(hint, (5, Some(5)));
108}
109
110#[test]
111fn test_map_err() {
112 use std::str::FromStr;
113
114 let mapped: Vec<_> = ["1", "2", "a", "4", "5"]
115 .into_iter()
116 .map(|txt| usize::from_str(txt))
117 .map_err(|e| format!("{:?}", e))
118 .collect();
119
120 assert_eq!(
121 mapped[2],
122 Err("ParseIntError { kind: InvalidDigit }".to_string())
123 );
124}
125
126#[test]
127fn test_map_err_hint() {
128 use std::str::FromStr;
129
130 let hint = ["1", "2", "a", "4", "5"]
131 .into_iter()
132 .map(|txt| usize::from_str(txt))
133 .map_err(|e| format!("{:?}", e))
134 .size_hint();
135
136 assert_eq!(hint, (5, Some(5)));
137}