use core::fmt;
#[cfg(feature="std")]
use std::error::Error as stdError;
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub enum ErrorKind {
Unavailable,
Unexpected,
Transient,
NotReady,
#[doc(hidden)]
__Nonexhaustive,
}
impl ErrorKind {
pub fn should_retry(self) -> bool {
self != ErrorKind::Unavailable
}
pub fn should_wait(self) -> bool {
self == ErrorKind::NotReady
}
pub fn description(self) -> &'static str {
match self {
ErrorKind::Unavailable => "permanently unavailable",
ErrorKind::Unexpected => "unexpected failure",
ErrorKind::Transient => "transient failure",
ErrorKind::NotReady => "not ready yet",
ErrorKind::__Nonexhaustive => unreachable!(),
}
}
}
#[derive(Debug)]
pub struct Error {
pub kind: ErrorKind,
pub msg: &'static str,
#[cfg(feature="std")]
cause: Option<Box<stdError + Send + Sync>>,
}
impl Error {
pub fn new(kind: ErrorKind, msg: &'static str) -> Self {
#[cfg(feature="std")] {
Error { kind, msg, cause: None }
}
#[cfg(not(feature="std"))] {
Error { kind, msg }
}
}
#[cfg(feature="std")]
pub fn with_cause<E>(kind: ErrorKind, msg: &'static str, cause: E) -> Self
where E: Into<Box<stdError + Send + Sync>>
{
Error { kind, msg, cause: Some(cause.into()) }
}
#[cfg(not(feature="std"))]
pub fn with_cause<E>(kind: ErrorKind, msg: &'static str, _cause: E) -> Self {
Error { kind, msg }
}
#[cfg(feature="std")]
pub fn take_cause(&mut self) -> Option<Box<stdError + Send + Sync>> {
self.cause.take()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[cfg(feature="std")] {
if let Some(ref cause) = self.cause {
return write!(f, "{} ({}); cause: {}",
self.msg, self.kind.description(), cause);
}
}
write!(f, "{} ({})", self.msg, self.kind.description())
}
}
#[cfg(feature="std")]
impl stdError for Error {
fn description(&self) -> &str {
self.msg
}
fn cause(&self) -> Option<&stdError> {
self.cause.as_ref().map(|e| e.as_ref() as &stdError)
}
}