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