use std::fmt::{self, Display};
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
msg: Option<String>,
}
impl Error {
pub fn new(kind: ErrorKind, msg: Option<String>) -> Self {
Self { kind, msg }
}
pub fn kind(&self) -> ErrorKind {
self.kind
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Self {
Self { kind, msg: None }
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)?;
if let Some(msg) = &self.msg {
write!(f, ": {msg}")?;
}
Ok(())
}
}
impl std::error::Error for Error {}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[non_exhaustive]
pub enum ErrorKind {
Config,
InvalidArg,
Macro,
}
impl Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::Config => write!(f, "configuration error"),
ErrorKind::InvalidArg => write!(f, "invalid argument"),
ErrorKind::Macro => write!(f, "macro expansion error"),
}
}
}
macro_rules! format_err {
($kind:path, $msg:expr) => {
$crate::error::Error::new($kind, Some($msg.to_string()))
};
($kind:path, $fmt:expr, $($arg:tt)+) => {
format_err!($kind, &format!($fmt, $($arg)+))
};
}
macro_rules! fail {
($kind:path, $msg:expr) => {
return Err(format_err!($kind, $msg))
};
($kind:path, $fmt:expr, $($arg:tt)+) => {
return Err(format_err!($kind, $fmt, $($arg)+))
};
}