resiter/
unwrap.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<T, E>>` to unwrap everything.
8///
9/// Errors can be unwraped as well. If the closure `F` returns `Some(O)`, that `O` will be inserted
10/// instead of the `E` into the resulting iterator.
11/// If the closure returns `None`, the error will be dropped (equally to
12/// `iter.filter_map(Result::ok)`.
13///
14#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
15pub struct UnwrapWith<I, O, E, F>(I, F)
16where
17    I: Iterator<Item = Result<O, E>>,
18    F: FnMut(E) -> Option<O>;
19
20impl<I, O, E, F> Iterator for UnwrapWith<I, O, E, F>
21where
22    I: Iterator<Item = Result<O, E>>,
23    F: FnMut(E) -> Option<O>,
24{
25    type Item = O;
26
27    fn next(&mut self) -> Option<Self::Item> {
28        while let Some(o) = self.0.by_ref().next() {
29            match o {
30                Ok(t) => return Some(t),
31                Err(e) => {
32                    if let Some(t) = (self.1)(e) {
33                        return Some(t);
34                    }
35                }
36            }
37        }
38
39        None
40    }
41}
42
43pub trait UnwrapWithExt<I, O, E, F>
44where
45    I: Iterator<Item = Result<O, E>>,
46    F: FnMut(E) -> Option<O>,
47{
48    /// Unwraps all results
49    ///
50    /// Errors can be ignored:
51    /// ```
52    /// use resiter::unwrap::UnwrapWithExt;
53    /// use std::str::FromStr;
54    ///
55    /// let unwrapped: Vec<usize> = ["1", "2", "a", "b", "5"]
56    ///     .iter()
57    ///     .map(|e| usize::from_str(e))
58    ///     .unwrap_with(|_| None) // ignore errors
59    ///     .collect();
60    ///
61    /// assert_eq!(unwrapped, vec![1, 2, 5],);
62    /// ```
63    ///
64    /// Or simply converted:
65    /// ```
66    /// use resiter::unwrap::UnwrapWithExt;
67    /// use std::str::FromStr;
68    ///
69    /// let unwrapped: Vec<usize> = ["1", "2", "a", "b", "5"]
70    ///     .iter()
71    ///     .map(|e| usize::from_str(e))
72    ///     .unwrap_with(|_| Some(8)) // convert errors
73    ///     .collect();
74    ///
75    /// assert_eq!(unwrapped, vec![1, 2, 8, 8, 5],);
76    /// ```
77    fn unwrap_with(self, _: F) -> UnwrapWith<I, O, E, F>;
78}
79
80impl<I, O, E, F> UnwrapWithExt<I, O, E, F> for I
81where
82    I: Iterator<Item = Result<O, E>>,
83    F: FnMut(E) -> Option<O>,
84{
85    #[inline]
86    fn unwrap_with(self, f: F) -> UnwrapWith<I, O, E, F> {
87        UnwrapWith(self, f)
88    }
89}