use core::fmt::{self, Display, Debug};
use {Causes, Fail};
use backtrace::Backtrace;
use context::Context;
use compat::Compat;
#[cfg(feature = "std")]
use box_std::BoxStd;
#[cfg_attr(feature = "small-error", path = "./error_impl_small.rs")]
mod error_impl;
use self::error_impl::ErrorImpl;
#[cfg(feature = "std")]
use std::error::Error as StdError;
pub struct Error {
imp: ErrorImpl,
}
impl<F: Fail> From<F> for Error {
fn from(failure: F) -> Error {
Error {
imp: ErrorImpl::from(failure)
}
}
}
impl Error {
#[cfg(feature = "std")]
pub fn from_boxed_compat(err: Box<dyn StdError + Sync + Send + 'static>) -> Error {
Error::from(BoxStd(err))
}
pub fn as_fail(&self) -> &dyn Fail {
self.imp.failure()
}
pub fn name(&self) -> Option<&str> {
self.as_fail().name()
}
#[deprecated(since = "0.1.2", note = "please use 'as_fail()' method instead")]
pub fn cause(&self) -> &dyn Fail {
self.as_fail()
}
pub fn backtrace(&self) -> &Backtrace {
self.imp.failure().backtrace().unwrap_or(&self.imp.backtrace())
}
pub fn context<D: Display + Send + Sync + 'static>(self, context: D) -> Context<D> {
Context::with_err(context, self)
}
pub fn compat(self) -> Compat<Error> {
Compat { error: self }
}
pub fn downcast<T: Fail>(self) -> Result<T, Error> {
self.imp.downcast().map_err(|imp| Error { imp })
}
pub fn find_root_cause(&self) -> &dyn Fail {
self.as_fail().find_root_cause()
}
pub fn iter_causes(&self) -> Causes {
self.as_fail().iter_causes()
}
pub fn iter_chain(&self) -> Causes {
self.as_fail().iter_chain()
}
pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
self.imp.failure().downcast_ref()
}
pub fn downcast_mut<T: Fail>(&mut self) -> Option<&mut T> {
self.imp.failure_mut().downcast_mut()
}
#[deprecated(since = "0.1.2", note = "please use the 'find_root_cause()' method instead")]
pub fn root_cause(&self) -> &dyn Fail {
::find_root_cause(self.as_fail())
}
#[deprecated(since = "0.1.2", note = "please use the 'iter_chain()' method instead")]
pub fn causes(&self) -> Causes {
Causes { fail: Some(self.as_fail()) }
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.imp.failure(), f)
}
}
impl Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let backtrace = self.imp.backtrace();
if backtrace.is_none() {
Debug::fmt(&self.imp.failure(), f)
} else {
write!(f, "{:?}\n\n{:?}", &self.imp.failure(), backtrace)
}
}
}
impl AsRef<dyn Fail> for Error {
fn as_ref(&self) -> &dyn Fail {
self.as_fail()
}
}
#[cfg(test)]
mod test {
use std::io;
use super::Error;
fn assert_just_data<T: Send + Sync + 'static>() { }
#[test]
fn assert_error_is_just_data() {
assert_just_data::<Error>();
}
#[test]
fn methods_seem_to_work() {
let io_error: io::Error = io::Error::new(io::ErrorKind::NotFound, "test");
let error: Error = io::Error::new(io::ErrorKind::NotFound, "test").into();
assert!(error.downcast_ref::<io::Error>().is_some());
let _: ::Backtrace = *error.backtrace();
assert_eq!(format!("{:?}", io_error), format!("{:?}", error));
assert_eq!(format!("{}", io_error), format!("{}", error));
drop(error);
assert!(true);
}
#[test]
fn downcast_can_be_used() {
let mut error: Error = io::Error::new(io::ErrorKind::NotFound, "test").into();
{
let real_io_error_ref = error.downcast_ref::<io::Error>().unwrap();
assert_eq!(real_io_error_ref.to_string(), "test");
}
{
let real_io_error_mut = error.downcast_mut::<io::Error>().unwrap();
assert_eq!(real_io_error_mut.to_string(), "test");
}
let real_io_error = error.downcast::<io::Error>().unwrap();
assert_eq!(real_io_error.to_string(), "test");
}
}