resiter/onerr.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#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
8pub struct OnErr<I, O, E, F>(I, F)
9where
10 I: Iterator<Item = Result<O, E>>,
11 F: FnMut(&E);
12
13/// Extension trait for `Iterator<Item = Result<T, E>>` to do something on `Err(_)`
14pub trait OnErrDo<I, O, E, F>
15where
16 I: Iterator<Item = Result<O, E>>,
17 F: FnMut(&E),
18{
19 /// Apply a sideffect on each `Err`
20 ///
21 /// ```
22 /// use resiter::onerr::OnErrDo;
23 /// use std::str::FromStr;
24 ///
25 /// let mut errs = Vec::<::std::num::ParseIntError>::new();
26 /// let _: Vec<Result<usize, ::std::num::ParseIntError>> = ["1", "2", "a", "b", "5"]
27 /// .iter()
28 /// .map(|e| usize::from_str(e))
29 /// .on_err(|e| {
30 /// errs.push(e.to_owned())
31 /// })
32 /// .collect();
33 ///
34 /// assert_eq!(errs.len(), 2);
35 /// ```
36 fn on_err(self, _: F) -> OnErr<I, O, E, F>;
37}
38
39impl<I, O, E, F> OnErrDo<I, O, E, F> for I
40where
41 I: Iterator<Item = Result<O, E>>,
42 F: FnMut(&E),
43{
44 #[inline]
45 fn on_err(self, f: F) -> OnErr<I, O, E, F> {
46 OnErr(self, f)
47 }
48}
49
50impl<I, O, E, F> Iterator for OnErr<I, O, E, F>
51where
52 I: Iterator<Item = Result<O, E>>,
53 F: FnMut(&E),
54{
55 type Item = Result<O, E>;
56
57 fn next(&mut self) -> Option<Self::Item> {
58 self.0.next().map(|r| {
59 r.map_err(|e| {
60 (self.1)(&e);
61 e
62 })
63 })
64 }
65}