#[cfg(feature = "chrono")]
use chrono;
use failure::{Backtrace, Context, Fail};
use std::{
fmt::{self, Display},
io,
str::Utf8Error,
};
use toml;
#[derive(Debug)]
pub struct Error {
inner: Context<ErrorKind>,
description: String,
}
impl Error {
pub fn new<S: ToString>(kind: ErrorKind, description: &S) -> Self {
Self {
inner: Context::new(kind),
description: description.to_string(),
}
}
pub fn kind(&self) -> ErrorKind {
*self.inner.get_context()
}
}
impl Fail for Error {
fn cause(&self) -> Option<&Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", &self.inner, &self.description)
}
}
#[derive(Copy, Clone, Debug, Eq, Fail, PartialEq)]
pub enum ErrorKind {
#[fail(display = "bad parameter")]
BadParam,
#[fail(display = "I/O operation failed")]
Io,
#[fail(display = "couldn't parse data")]
Parse,
}
macro_rules! err {
($kind:path, $msg:expr) => {
crate::error::Error::new(
$kind,
&$msg.to_string()
)
};
($kind:path, $fmt:expr, $($arg:tt)+) => {
err!($kind, &format!($fmt, $($arg)+))
};
}
#[allow(unused_macros)]
macro_rules! fail {
($kind:path, $msg:expr) => {
return Err(err!($kind, $msg).into());
};
($kind:path, $fmt:expr, $($arg:tt)+) => {
fail!($kind, &format!($fmt, $($arg)+));
};
}
impl From<Utf8Error> for Error {
fn from(other: Utf8Error) -> Self {
err!(ErrorKind::Parse, &other)
}
}
#[cfg(feature = "chrono")]
impl From<chrono::ParseError> for Error {
fn from(other: chrono::ParseError) -> Self {
err!(ErrorKind::Parse, &other)
}
}
impl From<fmt::Error> for Error {
fn from(other: fmt::Error) -> Self {
err!(ErrorKind::Io, &other)
}
}
impl From<io::Error> for Error {
fn from(other: io::Error) -> Self {
err!(ErrorKind::Io, &other)
}
}
impl From<toml::de::Error> for Error {
fn from(other: toml::de::Error) -> Self {
err!(ErrorKind::Parse, &other)
}
}