insideout/
lib.rs

1/// Wrap composed types inside-out
2///
3/// ```
4/// use insideout::InsideOut;
5///
6/// fn main() {
7///     let maybe_result: Option<Result<_, ()>> = Some(Ok(1));
8///     assert_eq!(maybe_result.inside_out(), Ok(Some(1)));
9///     let result_maybe: Result<Option<i16>, &'static str> = Err("foo");
10///     assert_eq!(result_maybe.inside_out(), Some(Err("foo")));
11///     let result_maybe: Result<Option<_>, &'static str> = Ok(Some(3i16));
12///     assert_eq!(result_maybe.inside_out(), Some(Ok(3)));
13/// }
14/// ```
15pub trait InsideOut {
16    type Output;
17    fn inside_out(self) -> Self::Output;
18}
19
20impl<T, E> InsideOut for Option<Result<T, E>> {
21    type Output = Result<Option<T>, E>;
22    fn inside_out(self) -> Self::Output {
23        match self {
24            Some(Ok(x)) => Ok(Some(x)),
25            Some(Err(e)) => Err(e),
26            None => Ok(None),
27        }
28    }
29}
30
31impl<T, E> InsideOut for Result<Option<T>, E> {
32    type Output = Option<Result<T, E>>;
33    fn inside_out(self) -> Self::Output {
34        match self {
35            Ok(o) => o.map(|o| Ok(o)),
36            Err(e) => Some(Err(e)),
37        }
38    }
39}
40
41/// Wrap items of an iterator inside-out
42///
43/// Ideally, this would be a same trait as `InsideOut`,
44/// but because of potential trait impl conflicts, it's
45/// different.
46pub trait InsideOutIter {
47    type Output;
48    fn inside_out_iter(self) -> Self::Output;
49}
50
51impl<I, T> InsideOutIter for I
52where
53    I: Iterator<Item = T>,
54    T: InsideOut,
55{
56    type Output = InsideOutIterImpl<I>;
57
58    fn inside_out_iter(self) -> Self::Output {
59        InsideOutIterImpl(self)
60    }
61}
62
63/// An iterator that performs `InsideOut` on elements of enclosed iterator
64///
65/// Use `inside_out_iter()` to create.
66///
67/// ```
68/// use insideout::InsideOutIter;
69///
70/// let i = vec![Ok(Some(1)), Err(2), Ok(None), Err(3)].into_iter();
71///
72/// let inside_outed :Vec<_> = i.inside_out_iter().collect();
73///
74/// assert_eq!(inside_outed,[Some(Ok(1)), Some(Err(2)), None, Some(Err(3))]);
75///
76/// ```
77///
78pub struct InsideOutIterImpl<I>(I);
79
80impl<I, T> Iterator for InsideOutIterImpl<I>
81where
82    I: Iterator<Item = T>,
83    T: InsideOut,
84{
85    type Item = <T as InsideOut>::Output;
86
87    fn next(&mut self) -> Option<Self::Item> {
88        self.0.next().map(InsideOut::inside_out)
89    }
90}