#![deny(missing_docs)]
#![cfg_attr(not(any(feature = "std", test)), no_std)]
#![cfg_attr(feature = "unstable-backtraces-impl-std", feature(backtrace))]
#[cfg(all(
not(feature = "backtraces"),
not(feature = "backtraces-impl-backtrace-crate"),
not(feature = "unstable-backtraces-impl-std"),
))]
mod backtrace_inert;
#[cfg(all(
not(feature = "backtraces"),
not(feature = "backtraces-impl-backtrace-crate"),
not(feature = "unstable-backtraces-impl-std"),
))]
pub use crate::backtrace_inert::*;
#[cfg(all(
feature = "backtraces",
not(feature = "backtraces-impl-backtrace-crate"),
not(feature = "unstable-backtraces-impl-std"),
))]
mod backtrace_shim;
#[cfg(all(
feature = "backtraces",
not(feature = "backtraces-impl-backtrace-crate"),
not(feature = "unstable-backtraces-impl-std"),
))]
pub use crate::backtrace_shim::*;
#[cfg(feature = "backtraces-impl-backtrace-crate")]
pub use backtrace::Backtrace;
#[cfg(feature = "unstable-backtraces-impl-std")]
pub use std::backtrace::Backtrace;
#[cfg(feature = "futures-01")]
pub mod futures01;
#[cfg(feature = "futures")]
pub mod futures;
pub use snafu_derive::Snafu;
macro_rules! generate_guide {
(pub mod $name:ident; $($rest:tt)*) => {
generate_guide!(@gen ".", pub mod $name { } $($rest)*);
};
(pub mod $name:ident { $($children:tt)* } $($rest:tt)*) => {
generate_guide!(@gen ".", pub mod $name { $($children)* } $($rest)*);
};
(@gen $prefix:expr, ) => {};
(@gen $prefix:expr, pub mod $name:ident; $($rest:tt)*) => {
generate_guide!(@gen $prefix, pub mod $name { } $($rest)*);
};
(@gen $prefix:expr, pub mod $name:ident { $($children:tt)* } $($rest:tt)*) => {
doc_comment::doc_comment! {
include_str!(concat!($prefix, "/", stringify!($name), ".md")),
pub mod $name {
generate_guide!(@gen concat!($prefix, "/", stringify!($name)), $($children)*);
}
}
generate_guide!(@gen $prefix, $($rest)*);
};
}
generate_guide! {
pub mod guide {
pub mod attributes;
pub mod comparison {
pub mod failure;
}
pub mod compatibility;
pub mod feature_flags;
pub mod generics;
pub mod opaque;
pub mod philosophy;
pub mod the_macro;
pub mod upgrading;
}
}
doc_comment::doctest!("../README.md", readme_tests);
#[cfg(any(feature = "std", test))]
#[doc(hidden)]
pub use std::error::Error;
#[cfg(not(any(feature = "std", test)))]
mod no_std_error;
#[cfg(not(any(feature = "std", test)))]
#[doc(hidden)]
pub use no_std_error::Error;
#[macro_export]
macro_rules! ensure {
($predicate:expr, $context_selector:expr) => {
if !$predicate {
return $context_selector.fail().map_err(core::convert::Into::into);
}
};
}
pub trait ResultExt<T, E>: Sized {
fn context<C, E2>(self, context: C) -> Result<T, E2>
where
C: IntoError<E2, Source = E>,
E2: Error + ErrorCompat;
fn with_context<F, C, E2>(self, context: F) -> Result<T, E2>
where
F: FnOnce() -> C,
C: IntoError<E2, Source = E>,
E2: Error + ErrorCompat;
#[doc(hidden)]
#[deprecated(since = "0.4.0", note = "use ResultExt::context instead")]
fn eager_context<C, E2>(self, context: C) -> Result<T, E2>
where
C: IntoError<E2, Source = E>,
E2: Error + ErrorCompat,
{
self.context(context)
}
#[doc(hidden)]
#[deprecated(since = "0.4.0", note = "use ResultExt::with_context instead")]
fn with_eager_context<F, C, E2>(self, context: F) -> Result<T, E2>
where
F: FnOnce() -> C,
C: IntoError<E2, Source = E>,
E2: Error + ErrorCompat,
{
self.with_context(context)
}
}
impl<T, E> ResultExt<T, E> for Result<T, E> {
fn context<C, E2>(self, context: C) -> Result<T, E2>
where
C: IntoError<E2, Source = E>,
E2: Error + ErrorCompat,
{
self.map_err(|error| context.into_error(error))
}
fn with_context<F, C, E2>(self, context: F) -> Result<T, E2>
where
F: FnOnce() -> C,
C: IntoError<E2, Source = E>,
E2: Error + ErrorCompat,
{
self.map_err(|error| {
let context = context();
context.into_error(error)
})
}
}
pub struct NoneError;
pub trait OptionExt<T>: Sized {
fn context<C, E>(self, context: C) -> Result<T, E>
where
C: IntoError<E, Source = NoneError>,
E: Error + ErrorCompat;
fn with_context<F, C, E>(self, context: F) -> Result<T, E>
where
F: FnOnce() -> C,
C: IntoError<E, Source = NoneError>,
E: Error + ErrorCompat;
#[doc(hidden)]
#[deprecated(since = "0.4.0", note = "use OptionExt::context instead")]
fn eager_context<C, E>(self, context: C) -> Result<T, E>
where
C: IntoError<E, Source = NoneError>,
E: Error + ErrorCompat,
{
self.context(context).map_err(Into::into)
}
#[doc(hidden)]
#[deprecated(since = "0.4.0", note = "use OptionExt::with_context instead")]
fn with_eager_context<F, C, E>(self, context: F) -> Result<T, E>
where
F: FnOnce() -> C,
C: IntoError<E, Source = NoneError>,
E: Error + ErrorCompat,
{
self.with_context(context).map_err(Into::into)
}
}
impl<T> OptionExt<T> for Option<T> {
fn context<C, E>(self, context: C) -> Result<T, E>
where
C: IntoError<E, Source = NoneError>,
E: Error + ErrorCompat,
{
self.ok_or_else(|| context.into_error(NoneError))
}
fn with_context<F, C, E>(self, context: F) -> Result<T, E>
where
F: FnOnce() -> C,
C: IntoError<E, Source = NoneError>,
E: Error + ErrorCompat,
{
self.ok_or_else(|| context().into_error(NoneError))
}
}
pub trait ErrorCompat {
fn backtrace(&self) -> Option<&Backtrace> {
None
}
}
impl<'a, E> ErrorCompat for &'a E
where
E: ErrorCompat,
{
fn backtrace(&self) -> Option<&Backtrace> {
(**self).backtrace()
}
}
#[cfg(any(feature = "std", test))]
impl<E> ErrorCompat for Box<E>
where
E: ErrorCompat,
{
fn backtrace(&self) -> Option<&Backtrace> {
(**self).backtrace()
}
}
pub trait AsErrorSource {
fn as_error_source(&self) -> &(dyn Error + 'static);
}
impl AsErrorSource for dyn Error + 'static {
fn as_error_source(&self) -> &(dyn Error + 'static) {
self
}
}
impl AsErrorSource for dyn Error + Send + 'static {
fn as_error_source(&self) -> &(dyn Error + 'static) {
self
}
}
impl AsErrorSource for dyn Error + Sync + 'static {
fn as_error_source(&self) -> &(dyn Error + 'static) {
self
}
}
impl AsErrorSource for dyn Error + Send + Sync + 'static {
fn as_error_source(&self) -> &(dyn Error + 'static) {
self
}
}
impl<T: Error + 'static> AsErrorSource for T {
fn as_error_source(&self) -> &(dyn Error + 'static) {
self
}
}
pub trait IntoError<E>
where
E: Error + ErrorCompat,
{
type Source;
fn into_error(self, source: Self::Source) -> E;
}
pub trait GenerateBacktrace {
fn generate() -> Self;
fn as_backtrace(&self) -> Option<&Backtrace>;
}
#[cfg(any(feature = "std", test))]
impl GenerateBacktrace for Option<Backtrace> {
fn generate() -> Self {
use std::env;
use std::sync::{
atomic::{AtomicBool, Ordering},
Once,
};
static START: Once = Once::new();
static ENABLED: AtomicBool = AtomicBool::new(false);
START.call_once(|| {
let enabled = env::var_os("RUST_LIB_BACKTRACE")
.or_else(|| env::var_os("RUST_BACKTRACE"))
.map_or(false, |v| v == "1");
ENABLED.store(enabled, Ordering::SeqCst);
});
if ENABLED.load(Ordering::SeqCst) {
Some(Backtrace::generate())
} else {
None
}
}
fn as_backtrace(&self) -> Option<&Backtrace> {
self.as_ref()
}
}
#[cfg(feature = "backtraces-impl-backtrace-crate")]
impl GenerateBacktrace for Backtrace {
fn generate() -> Self {
Backtrace::new()
}
fn as_backtrace(&self) -> Option<&Backtrace> {
Some(self)
}
}
#[cfg(feature = "unstable-backtraces-impl-std")]
impl GenerateBacktrace for Backtrace {
fn generate() -> Self {
Backtrace::force_capture()
}
fn as_backtrace(&self) -> Option<&Backtrace> {
Some(self)
}
}