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}