#![forbid(unsafe_code)]
#[doc(inline)]
pub use crate::syscalls::{Error as SyscallError, FrozenFd};
use std::{
error::Error as StdError,
io::Error as IOError,
sync::atomic::{AtomicBool, Ordering},
};
use snafu::{GenerateBacktrace, ResultExt};
#[derive(Debug)]
pub struct Backtrace(pub Option<backtrace::Backtrace>);
pub static BACKTRACES_ENABLED: AtomicBool = AtomicBool::new(cfg!(debug_assertions));
impl GenerateBacktrace for Backtrace {
fn generate() -> Self {
if BACKTRACES_ENABLED.load(Ordering::SeqCst) {
Backtrace(Some(backtrace::Backtrace::new()))
} else {
Backtrace(None)
}
}
fn as_backtrace(&self) -> Option<&snafu::Backtrace> {
self.0.as_ref()
}
}
#[derive(Snafu, Debug)]
#[snafu(visibility = "pub(crate)")]
pub enum Error {
#[snafu(display("feature '{}' not implemented", feature))]
NotImplemented {
feature: String,
backtrace: Backtrace,
},
#[snafu(display("feature '{}' not supported on this kernel", feature))]
NotSupported {
feature: String,
backtrace: Backtrace,
},
#[snafu(display("invalid {} argument: {}", name, description))]
InvalidArgument {
name: String,
description: String,
backtrace: Backtrace,
},
#[snafu(display("violation of safety requirement: {}", description))]
SafetyViolation {
description: String,
backtrace: Backtrace,
},
#[snafu(display("{} failed", operation))]
OsError {
operation: String,
source: IOError,
backtrace: Backtrace,
},
#[snafu(display("{} failed", operation))]
RawOsError {
operation: String,
#[snafu(backtrace)]
source: SyscallError,
},
#[snafu(display("{}", context))]
Wrapped {
context: String,
#[snafu(backtrace)]
#[snafu(source(from(Error, Box::new)))]
source: Box<Error>,
},
}
pub(crate) trait ErrorExt {
fn wrap<S: Into<String>>(self, context: S) -> Self;
}
impl<T> ErrorExt for Result<T, Error> {
fn wrap<S: Into<String>>(self, context: S) -> Self {
self.context(Wrapped {
context: context.into(),
})
}
}
pub(crate) struct Chain<'a> {
current: Option<&'a (dyn StdError + 'static)>,
}
impl<'a> Iterator for Chain<'a> {
type Item = &'a (dyn StdError + 'static);
fn next(&mut self) -> Option<Self::Item> {
let current = self.current;
self.current = self.current.and_then(StdError::source);
current
}
}
impl Error {
pub(crate) fn iter_chain_hotfix(&self) -> Chain {
Chain {
current: Some(self),
}
}
pub(crate) fn root_cause(&self) -> &(dyn StdError + 'static) {
self.iter_chain_hotfix()
.last()
.expect("Error::iter_chain_hotfix() should have at least one result")
}
}