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}