use std::fmt;
use std::ops::{Deref, DerefMut};
#[doc(hidden)]
type BoxError = Box<dyn std::error::Error + Send + Sync>;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ErrorKind {
Serialization,
InvalidRoute,
CannotDeserializeArg,
ConditionNotMet,
NotFound,
MissingArgs,
Runtime,
Internal,
InvalidInput,
}
impl ErrorKind {
pub(crate) fn as_str(&self) -> &'static str {
use ErrorKind::*;
match *self {
Serialization => "serialization failed",
InvalidRoute => "invalid route",
CannotDeserializeArg => "argument cannot be deserialized into target type",
ConditionNotMet => "condition failed",
NotFound => "job not found",
MissingArgs => "missing arguments",
Runtime => "runtime error",
Internal => "internal error",
InvalidInput => "invalid input",
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str(self.as_str())
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Self {
Error { kind, error: None }
}
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::new(ErrorKind::Serialization, e)
}
}
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
error: Option<BoxError>,
}
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(source) = self.error.as_ref() {
write!(fmt, "{source}")
} else {
write!(fmt, "{}", self.kind.as_str())
}
}
}
impl Error {
pub fn new<E: Into<BoxError>>(kind: ErrorKind, error: E) -> Self {
Self {
kind,
error: Some(error.into()),
}
}
pub fn kind(&self) -> ErrorKind {
self.kind
}
pub fn source(&self) -> Option<&BoxError> {
self.error.as_ref()
}
pub fn runtime<E: Into<BoxError>>(error: E) -> Self {
Self::new(ErrorKind::Runtime, error)
}
pub fn internal<E: Into<BoxError>>(error: E) -> Self {
Self::new(ErrorKind::Internal, error)
}
}
#[derive(Debug)]
pub struct AggregateError<E>(pub Vec<E>);
impl<E: std::error::Error> std::error::Error for AggregateError<E> {}
impl<E: std::error::Error> From<Vec<E>> for AggregateError<E> {
fn from(vec: Vec<E>) -> Self {
AggregateError(vec)
}
}
impl<E> fmt::Display for AggregateError<E>
where
E: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for e in &self.0 {
writeln!(f, "- {e}")?;
}
Ok(())
}
}
impl<E> Deref for AggregateError<E> {
type Target = Vec<E>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<E> DerefMut for AggregateError<E> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}