result-either 0.1.3

Result err variant methods, e.g cloned_err
Documentation
#![doc = include_str!("../README.md")]
#![no_std]
use core::{
    ops::{Deref, DerefMut},
    option::IntoIter,
};

#[doc(hidden)]
pub trait ResultLike: Sized {
    type T;
    type E;

    fn by(self) -> Result<Self::T, Self::E>;

    fn by_ref(&self) -> Result<&Self::T, &Self::E>;

    fn by_mut(&mut self) -> Result<&mut Self::T, &mut Self::E>;
}

#[doc(hidden)]
pub trait ThisRef<'a>: 'a {
    type Out: ?Sized;

    /// Consume self into reference
    fn this_ref(self) -> &'a Self::Out;
}

impl<'a, T: ?Sized> ThisRef<'a> for &'a T {
    type Out = T;

    fn this_ref(self) -> &'a Self::Out {
        self
    }
}
impl<'a, T: ?Sized> ThisRef<'a> for &'a mut T {
    type Out = T;

    fn this_ref(self) -> &'a Self::Out {
        self
    }
}

impl<T, E> ResultLike for Result<T, E> {
    type T = T;
    type E = E;

    #[inline]
    fn by(self) -> Result<Self::T, Self::E> {
        self
    }

    #[inline]
    fn by_ref(&self) -> Result<&Self::T, &Self::E> {
        self.as_ref()
    }

    #[inline]
    fn by_mut(&mut self) -> Result<&mut Self::T, &mut Self::E> {
        self.as_mut()
    }
}

/// [`Result`] extension methods for [`Err`]
#[allow(private_bounds, private_interfaces)]
pub trait ResultExt: ResultLike {
    /// Like [`Result::as_deref`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let x: Result<(), String> = Err("foo".to_owned());
    /// let y: Result<&(), &str> = x.err_as_deref();
    /// ```
    fn err_as_deref(&self) -> Result<&Self::T, &<Self::E as Deref>::Target>
    where Self::E: Deref,
    {
        self.by_ref().map_err(Deref::deref)
    }

    /// Like [`Result::as_deref_mut`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let mut x: Result<(), String> = Err("foo".to_owned());
    /// let y: Result<&mut (), &mut str> = x.err_as_deref_mut();
    /// ```
    fn err_as_deref_mut(&mut self) -> Result<&mut Self::T, &mut <Self::E as Deref>::Target>
    where Self::E: DerefMut,
    {
        self.by_mut().map_err(DerefMut::deref_mut)
    }

    /// Like [`Result::copied`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let x: Result<(), &i32> = Err(&2);
    /// let _: Result<(), i32> = x.copied_err();
    /// ```
    fn copied_err<'a>(self) -> Result<Self::T, <Self::E as ThisRef<'a>>::Out>
    where Self::E: ThisRef<'a>,
          <Self::E as ThisRef<'a>>::Out: Copy,
    {
        self.by().map_err(|e| *e.this_ref())
    }

    /// Like [`Result::cloned`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let msg = "foo".to_owned();
    /// let x: Result<(), &String> = Err(&msg);
    /// let _: Result<(), String> = x.cloned_err();
    /// ```
    fn cloned_err<'a>(self) -> Result<Self::T, <Self::E as ThisRef<'a>>::Out>
    where Self::E: ThisRef<'a>,
          <Self::E as ThisRef<'a>>::Out: Clone,
    {
        self.by().map_err(|e| e.this_ref().clone())
    }

    /// Like [`Result::iter`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<i32, i32> = Ok(1);
    /// let err: Result<i32, i32> = Err(1);
    ///
    /// assert_eq!(ok.iter_err().next(),  None);
    /// assert_eq!(err.iter_err().next(), Some(&1));
    /// ```
    fn iter_err(&self) -> IntoIter<&Self::E> {
        self.by_ref().err().into_iter()
    }

    /// Like [`Result::iter_mut`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let mut ok: Result<i32, i32> = Ok(1);
    /// let mut err: Result<i32, i32> = Err(1);
    ///
    /// assert_eq!(ok.iter_err_mut().next(),  None);
    /// assert_eq!(err.iter_err_mut().next(), Some(&mut 1));
    /// ```
    fn iter_err_mut(&mut self) -> IntoIter<&mut Self::E> {
        self.by_mut().err().into_iter()
    }

    /// Like [`Result::into_iter`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<i32, i32> = Ok(1);
    /// let err: Result<i32, i32> = Err(1);
    ///
    /// assert_eq!(ok.into_iter_err().next(),  None);
    /// assert_eq!(err.into_iter_err().next(), Some(1));
    /// ```
    fn into_iter_err(self) -> IntoIter<Self::E> {
        self.by().err().into_iter()
    }

    /// Like [`Result::map_or`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<i32, &str> = Ok(1);
    /// let err: Result<i32, &str> = Err("err");
    ///
    /// assert_eq!(ok.map_err_or(0, str::len),  0);
    /// assert_eq!(err.map_err_or(0, str::len), 3);
    /// ```
    fn map_err_or<E, F>(self, default: E, f: F) -> E
    where F: FnOnce(Self::E) -> E,
    {
        match self.by() {
            Ok(_) => default,
            Err(e) => f(e),
        }
    }

    /// Like [`Result::map_or_else`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<usize, &str> = Ok(1);
    /// let err: Result<usize, &str> = Err("err");
    ///
    /// assert_eq!(ok.map_err_or_else(|n| n*2, str::len),  2);
    /// assert_eq!(err.map_err_or_else(|n| n*2, str::len), 3);
    /// ```
    fn map_err_or_else<E, D, F>(self, default: D, f: F) -> E
    where F: FnOnce(Self::E) -> E,
          D: FnOnce(Self::T) -> E,
    {
        match self.by() {
            Ok(ok) => default(ok),
            Err(e) => f(e),
        }
    }

    /// Like [`Result::unwrap_or`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<usize, &str> = Ok(1);
    /// let err: Result<usize, &str> = Err("err");
    ///
    /// assert_eq!(ok.unwrap_err_or("ok"),  "ok");
    /// assert_eq!(err.unwrap_err_or("ok"), "err");
    /// ```
    fn unwrap_err_or(self, default: Self::E) -> Self::E {
        match self.by() {
            Ok(_) => default,
            Err(e) => e,
        }
    }

    /// Like [`Result::unwrap_or_else`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<usize, &str> = Ok(1);
    /// let err: Result<usize, &str> = Err("err");
    ///
    /// assert_eq!(ok.unwrap_err_or_else(|_| "ok"),  "ok");
    /// assert_eq!(err.unwrap_err_or_else(|_| "ok"), "err");
    /// ```
    fn unwrap_err_or_else<F>(self, op: F) -> Self::E
    where F: FnOnce(Self::T) -> Self::E,
    {
        match self.by() {
            Ok(ok) => op(ok),
            Err(e) => e,
        }
    }

    /// Like [`Result::unwrap_or_default`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<usize, &str> = Ok(1);
    /// let err: Result<usize, &str> = Err("err");
    ///
    /// assert_eq!(ok.unwrap_err_or_default(),  "");
    /// assert_eq!(err.unwrap_err_or_default(), "err");
    /// ```
    fn unwrap_err_or_default(self) -> Self::E
    where Self::E: Default,
    {
        match self.by() {
            Ok(_) => Default::default(),
            Err(e) => e,
        }
    }

    /// Like [`Result::transpose`], but on [`Err`]
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let ok: Result<i32, Option<i32>> = Ok(1);
    /// let none: Result<i32, Option<i32>> = Err(None);
    /// let some: Result<i32, Option<i32>> = Err(Some(3));
    ///
    /// assert_eq!(ok.transpose_err(),   Some(Ok(1)));
    /// assert_eq!(none.transpose_err(), None);
    /// assert_eq!(some.transpose_err(), Some(Err(3)));
    /// ```
    fn transpose_err<E>(self) -> Option<Result<Self::T, E>>
    where Self: ResultLike<E = Option<E>>,
    {
        match self.by() {
            Ok(x) => Some(Ok(x)),
            Err(Some(e)) => Some(Err(e)),
            Err(None) => None,
        }
    }

    /// Like `self.map_err(Into::into)`
    ///
    /// # Examples
    /// ```
    /// # use result_either::ResultExt;
    /// let e: Result<(), &str> = Err("foo");
    /// let e1: Result<(), String> = e.err_into();
    /// assert_eq!(e1, Err("foo".to_owned()));
    /// ```
    fn err_into<E>(self) -> Result<Self::T, E>
    where Self::E: Into<E>,
    {
        self.by().map_err(Into::into)
    }

    /// Map `Ok(x) => Err(x)`, `Err(x) => Ok(x)`
    ///
    /// # Examples
    ///
    /// ```
    /// # use result_either::ResultExt;
    /// let ok:  Result<i32, i32> = Ok(3);
    /// let err: Result<i32, i32> = Err(4);
    /// assert_eq!(ok.flip(), Err(3));
    /// assert_eq!(err.flip(), Ok(4));
    /// ```
    fn flip(self) -> Result<Self::E, Self::T> {
        match self.by() {
            Ok(x) => Err(x),
            Err(x) => Ok(x),
        }
    }

    /// Unpack `Result<T, T>`
    ///
    /// # Examples
    ///
    /// ```
    /// # use result_either::ResultExt;
    /// let ok:  Result<i32, i32> = Ok(3);
    /// let err: Result<i32, i32> = Err(4);
    /// assert_eq!(ok.into_inner(), 3);
    /// assert_eq!(err.into_inner(), 4);
    /// ```
    fn into_inner<O>(self) -> O
    where Self: ResultExt<T = O, E = O>,
    {
        match self.by() {
            Ok(x) | Err(x) => x,
        }
    }
}
impl<T: ResultLike> ResultExt for T { }