blob: f4125cdd68983daf37c279a163e4dcee3f97da16 [file] [log] [blame]
use core::fmt::Display;
use {Compat, Context, Fail};
/// Extension methods for `Result`.
pub trait ResultExt<T, E> {
/// Wraps the error in `Compat` to make it compatible with older error
/// handling APIs that expect `std::error::Error`.
///
/// # Examples
///
/// ```
/// # fn main() {
/// # tests::run_test();
/// # }
/// #
/// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
/// #
/// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
/// use std::error::Error;
/// # use std::fmt;
/// #
/// # extern crate failure;
/// #
/// # use tests::failure::ResultExt;
/// #
/// # #[derive(Debug)]
/// struct CustomError;
///
/// impl Error for CustomError {
/// fn description(&self) -> &str {
/// "My custom error message"
/// }
///
/// fn cause(&self) -> Option<&Error> {
/// None
/// }
/// }
/// #
/// # impl fmt::Display for CustomError {
/// # fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// # write!(f, "{}", self.description())
/// # }
/// # }
/// #
/// # pub fn run_test() {
///
/// let x = (|| -> Result<(), failure::Error> {
/// Err(CustomError).compat()?
/// })().with_context(|e| {
/// format!("An error occured: {}", e)
/// }).unwrap_err();
///
/// let x = format!("{}", x);
///
/// assert_eq!(x, "An error occured: My custom error message");
/// # }
///
/// # }
/// ```
fn compat(self) -> Result<T, Compat<E>>;
/// Wraps the error type in a context type.
///
/// # Examples
///
/// ```
/// # #[cfg(all(feature = "std", feature = "derive"))]
/// # #[macro_use] extern crate failure;
/// #
/// # #[cfg(all(feature = "std", feature = "derive"))]
/// # #[macro_use] extern crate failure_derive;
/// #
/// # fn main() {
/// # tests::run_test();
/// # }
/// #
/// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
/// #
/// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
/// #
/// # use failure::{self, ResultExt};
/// #
/// #[derive(Fail, Debug)]
/// #[fail(display = "")]
/// struct CustomError;
/// #
/// # pub fn run_test() {
///
/// let x = (|| -> Result<(), failure::Error> {
/// Err(CustomError)?
/// })().context(format!("An error occured")).unwrap_err();
///
/// let x = format!("{}", x);
///
/// assert_eq!(x, "An error occured");
/// # }
///
/// # }
/// ```
fn context<D>(self, context: D) -> Result<T, Context<D>>
where
D: Display + Send + Sync + 'static;
/// Wraps the error type in a context type generated by looking at the
/// error value.
///
/// # Examples
///
/// ```
/// # #[cfg(all(feature = "std", feature = "derive"))]
/// # #[macro_use] extern crate failure;
/// #
/// # #[cfg(all(feature = "std", feature = "derive"))]
/// # #[macro_use] extern crate failure_derive;
/// #
/// # fn main() {
/// # tests::run_test();
/// # }
/// #
/// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
/// #
/// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
/// #
/// # use failure::{self, ResultExt};
/// #
/// #[derive(Fail, Debug)]
/// #[fail(display = "My custom error message")]
/// struct CustomError;
/// #
/// # pub fn run_test() {
///
/// let x = (|| -> Result<(), failure::Error> {
/// Err(CustomError)?
/// })().with_context(|e| {
/// format!("An error occured: {}", e)
/// }).unwrap_err();
///
/// let x = format!("{}", x);
///
/// assert_eq!(x, "An error occured: My custom error message");
/// # }
///
/// # }
/// ```
fn with_context<F, D>(self, f: F) -> Result<T, Context<D>>
where
F: FnOnce(&E) -> D,
D: Display + Send + Sync + 'static;
}
impl<T, E> ResultExt<T, E> for Result<T, E>
where
E: Fail,
{
fn compat(self) -> Result<T, Compat<E>> {
self.map_err(|err| err.compat())
}
fn context<D>(self, context: D) -> Result<T, Context<D>>
where
D: Display + Send + Sync + 'static,
{
self.map_err(|failure| failure.context(context))
}
fn with_context<F, D>(self, f: F) -> Result<T, Context<D>>
where
F: FnOnce(&E) -> D,
D: Display + Send + Sync + 'static,
{
self.map_err(|failure| {
let context = f(&failure);
failure.context(context)
})
}
}
with_std! {
use Error;
impl<T> ResultExt<T, Error> for Result<T, Error> {
fn compat(self) -> Result<T, Compat<Error>> {
self.map_err(|err| err.compat())
}
fn context<D>(self, context: D) -> Result<T, Context<D>> where
D: Display + Send + Sync + 'static
{
self.map_err(|failure| failure.context(context))
}
fn with_context<F, D>(self, f: F) -> Result<T, Context<D>> where
F: FnOnce(&Error) -> D,
D: Display + Send + Sync + 'static
{
self.map_err(|failure| {
let context = f(&failure);
failure.context(context)
})
}
}
}