outcome-46f94afc-026f-5511-9d7e-7d1fd495fb5c 0.1.1

Augmentations for error propagation
Documentation
#[cfg(feature = "std")]
extern crate std;

#[cfg(feature = "std")]
use std::{
  eprintln,
  process::{ExitCode, Termination},
};

#[cfg(not(feature = "nightly"))]
use core::convert::Infallible;
use core::fmt::Debug;

#[cfg(not(feature = "nightly"))]
use crate::outcome::Outcome;
use crate::private::panic;

/// `Aberration` is a type that can represent a [`Mistake`], or [`Failure`].
///
/// **NOTE**: This type will become a alias once `!` is stabilized.
///
/// See the [module documentation](crate) for details.
///
/// [`Mistake`]: Aberration::Mistake
/// [`Failure`]: Aberration::Failure
#[must_use = "This Aberration might be a `Mistake`, which should be handled"]
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum Aberration<M, F> {
  /// Contains the mistake value. Analogous to
  /// [`Outcome::Mistake`](crate::prelude::Outcome::Mistake)
  Mistake(M),
  /// Contains the failure value. Analogous to
  /// [`Outcome::Failure`](crate::prelude::Outcome::Failure)
  Failure(F),
}

impl<M, F> Aberration<M, F> {
  /// Converts from `&Aberration<M, F>` to `Aberration<&M, &F>`.
  ///
  /// Produces a new `Aberration`, containing a reference into the original,
  /// leaving it in place.
  /// # Examples
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// let x: Aberration<u32, &str> = Aberration::Mistake(42);
  /// assert_eq!(x.as_ref(), Aberration::Mistake(&42));
  ///
  /// let x: Aberration<&str, u32> = Aberration::Failure(47);
  /// assert_eq!(x.as_ref(), Aberration::Failure(&47));
  #[inline]
  pub fn as_ref(&self) -> Aberration<&M, &F> {
    match *self {
      Self::Mistake(ref value) => Aberration::Mistake(value),
      Self::Failure(ref value) => Aberration::Failure(value),
    }
  }

  /// Converts from `&mut Aberration<M, F>` to `Aberration<&mut M, &mut F>`
  ///
  /// # Examples
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// fn mutate(x: &mut Aberration<u32, i32>) {
  ///   match x.as_mut() {
  ///     Aberration::Mistake(m) => *m = 42,
  ///     Aberration::Failure(f) => *f = 47,
  ///   }
  /// }
  ///
  /// let mut x: Aberration<u32, i32> = Aberration::Mistake(1);
  /// mutate(&mut x);
  /// assert_eq!(x.unwrap_mistake(), 42);
  ///
  /// let mut x: Aberration<u32, i32> = Aberration::Failure(1);
  /// mutate(&mut x);
  /// assert_eq!(x.unwrap_failure(), 47);
  /// ```
  #[inline]
  pub fn as_mut(&mut self) -> Aberration<&mut M, &mut F> {
    match *self {
      Self::Mistake(ref mut value) => Aberration::Mistake(value),
      Self::Failure(ref mut value) => Aberration::Failure(value),
    }
  }

  /// Returns `true` if the aberration is a [`Mistake`]
  ///
  /// # Examples
  ///
  /// # Basic usage:
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// let x: Aberration<u32, i32> = Aberration::Mistake(42);
  /// assert!(x.is_mistake());
  ///
  /// let x: Aberration<u32, i32> = Aberration::Failure(47);
  /// assert!(!x.is_mistake());
  /// ```
  ///
  /// [`Mistake`]: Aberration::Mistake
  #[must_use = "if you intended to assert a mistake, consider `.unwrap_mistake()` instead"]
  #[inline]
  pub fn is_mistake(&self) -> bool {
    if let Self::Mistake(_) = self {
      return true;
    }
    false
  }

  /// Returns `true` if the aberration is a [`Failure`]
  ///
  /// # Examples
  ///
  /// # Basic usage:
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// let x: Aberration<u32, i32> = Aberration::Failure(1);
  /// assert!(x.is_failure());
  ///
  /// let x: Aberration<u32, i32> = Aberration::Mistake(1);
  /// assert!(!x.is_failure());
  /// ```
  /// [`Failure`]: Aberration::Failure
  #[must_use = "if you intended to assert a failure, consider `.unwrap_failure()` instead"]
  #[inline]
  pub fn is_failure(&self) -> bool {
    if let Self::Failure(_) = self {
      return true;
    }
    false
  }

  /// Converts from `Aberration<M, F>` to [`Option<M>`]
  ///
  /// Converts `self` into an [`Option<M>`], consuming `self`, and discarding
  /// the failure value if any.
  ///
  /// # Examples
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// let x: Aberration<u32, i32> = Aberration::Failure(42);
  /// assert_eq!(x.mistake(), None);
  ///
  /// let x: Aberration<u32, i32> = Aberration::Mistake(42);
  /// assert_eq!(x.mistake(), Some(42));
  /// ```
  #[inline]
  pub fn mistake(self) -> Option<M> {
    if let Self::Mistake(value) = self {
      return Some(value);
    }
    None
  }

  /// Converts from `Aberration<M, F>` to [`Option<F>`]
  ///
  /// Converts `self` into an [`Option<F>`], consuming `self`, and discarding the
  /// mistake value if any.
  ///
  /// # Examples
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// let x: Aberration<u32, i32> = Aberration::Failure(42);
  /// assert_eq!(x.failure(), Some(42));
  ///
  /// let x: Aberration<u32, i32> = Aberration::Mistake(42);
  /// assert_eq!(x.failure(), None);
  /// ```
  #[inline]
  pub fn failure(self) -> Option<F> {
    if let Self::Failure(value) = self {
      return Some(value);
    }
    None
  }

  /// Maps an `Aberration<M, F>` to `Aberration<N, F>` by applying a function
  /// to a contained [`Mistake`] value, leaving any [`Failure`] value
  /// untouched.
  ///
  /// [`Mistake`]: Aberration::Mistake
  /// [`Failure`]: Aberration::Failure
  #[inline]
  pub fn map_mistake<N, C>(self, callable: C) -> Aberration<N, F>
  where
    C: FnOnce(M) -> N,
  {
    match self {
      Self::Mistake(value) => Aberration::Mistake(callable(value)),
      Self::Failure(value) => Aberration::Failure(value),
    }
  }

  /// Maps an `Aberration<M, F>` to `Aberration<M, G>` by applying a function
  /// to a contained [`Failure`] value, leaving any [`Mistake`] value
  /// untouched.
  ///
  /// [`Mistake`]: Aberration::Mistake
  /// [`Failure`]: Aberration::Failure
  #[inline]
  pub fn map_failure<G, C>(self, callable: C) -> Aberration<M, G>
  where
    C: FnOnce(F) -> G,
  {
    match self {
      Self::Mistake(value) => Aberration::Mistake(value),
      Self::Failure(value) => Aberration::Failure(callable(value)),
    }
  }
}

#[cfg(not(feature = "nightly"))]
impl<M, F> Aberration<M, F>
where
  M: Into<F>,
{
  /// **TODO**: Write documentation
  pub fn escalate(self) -> Outcome<Infallible, Infallible, F> {
    match self {
      Self::Mistake(m) => Outcome::Failure(m.into()),
      Self::Failure(f) => Outcome::Failure(f),
    }
  }
}

impl<M, F: Debug> Aberration<M, F> {
  /// Returns the contained [`Mistake`] value, consuming the `self` value.
  ///
  /// # Panics
  ///
  /// Panics if the value is a [`Failure`], with a custom panic message
  /// provided by the failure.
  ///
  /// # Examples
  ///
  /// ```should_panic
  /// # use outcome::prelude::*;
  /// let x: Aberration<&str, i32> = Aberration::Failure(47);
  /// x.unwrap_mistake(); // panics with '47'
  /// ```
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// let x: Aberration<&str, i32> = Aberration::Mistake("try again!");
  /// assert_eq!(x.unwrap_mistake(), "try again!");
  /// ```
  ///
  /// [`Mistake`]: Aberration::Mistake
  /// [`Failure`]: Aberration::Failure
  #[track_caller]
  #[inline]
  pub fn unwrap_mistake(self) -> M {
    match self {
      Self::Mistake(m) => m,
      Self::Failure(f) => panic("Aberration::unwrap_mistake()", "Failure", &f),
    }
  }
}

impl<M: Debug, F> Aberration<M, F> {
  /// Returns the contained [`Failure`] value, consuming the `self` value.
  ///
  /// # Panics
  ///
  /// Panics if the value is a [`Mistake`], with a custom panic message
  /// provided by the mistake.
  ///
  /// # Examples
  ///
  /// ```should_panic
  /// # use outcome::prelude::*;
  /// let x: Aberration<i32, &str> = Aberration::Mistake(47);
  /// x.unwrap_failure(); // panics with '47'
  /// ```
  ///
  /// ```
  /// # use outcome::prelude::*;
  /// let x: Aberration<i32, &str> = Aberration::Failure("error!");
  /// assert_eq!(x.unwrap_failure(), "error!");
  /// ```
  ///
  /// [`Mistake`]: Aberration::Mistake
  /// [`Failure`]: Aberration::Failure
  #[track_caller]
  #[inline]
  pub fn unwrap_failure(self) -> F {
    match self {
      Self::Mistake(m) => panic("Aberration::unwrap_failure()", "Mistake", &m),
      Self::Failure(f) => f,
    }
  }
}

impl<M: Clone, F: Clone> Clone for Aberration<M, F> {
  #[inline]
  fn clone(&self) -> Self {
    match self {
      Self::Mistake(value) => Self::Mistake(value.clone()),
      Self::Failure(value) => Self::Failure(value.clone()),
    }
  }

  #[inline]
  fn clone_from(&mut self, source: &Self) {
    match (self, source) {
      (Self::Mistake(to), Self::Mistake(from)) => to.clone_from(from),
      (Self::Failure(to), Self::Failure(from)) => to.clone_from(from),
      (to, from) => *to = from.clone(),
    }
  }
}

#[cfg(feature = "std")]
impl<M: Debug, F: Debug> Termination for Aberration<M, F> {
  #[inline]
  fn report(self) -> ExitCode {
    match self {
      Aberration::Mistake(m) => eprintln!("Mistake: {:?}", m),
      Aberration::Failure(f) => eprintln!("Failure: {:?}", f),
    };
    ExitCode::FAILURE
  }
}