use std::error::Error as StdError;
use std::fmt;
use redis::RedisError;
pub type InitializationResult<T> = Result<T, Error>;
#[derive(Debug)]
pub struct CheckoutError {
kind: CheckoutErrorKind,
}
impl CheckoutError {
pub(crate) fn new(kind: CheckoutErrorKind) -> Self {
Self { kind }
}
pub fn kind(&self) -> CheckoutErrorKind {
self.kind
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CheckoutErrorKind {
NoConnection,
CheckoutTimeout,
ReservationLimitReached,
NoPool,
CheckoutLimitReached,
TaskExecution,
}
impl fmt::Display for CheckoutErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match self {
CheckoutErrorKind::NoConnection => "there are no connections available",
CheckoutErrorKind::CheckoutTimeout => {
"there was no connection to checkout available in time"
}
CheckoutErrorKind::ReservationLimitReached => "the reservation limit has been reached",
CheckoutErrorKind::NoPool => "there was no pool available",
CheckoutErrorKind::CheckoutLimitReached => "checkout limit limit reached",
CheckoutErrorKind::TaskExecution => "task execution failed",
};
f.write_str(s)
}
}
impl fmt::Display for CheckoutError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.kind())?;
Ok(())
}
}
impl StdError for CheckoutError {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
None
}
}
impl From<CheckoutErrorKind> for CheckoutError {
fn from(kind: CheckoutErrorKind) -> Self {
Self { kind }
}
}
impl From<CheckoutError> for RedisError {
fn from(err: CheckoutError) -> Self {
let err = std::io::Error::new(std::io::ErrorKind::NotConnected, err);
err.into()
}
}
impl From<redis::RedisError> for Error {
fn from(err: redis::RedisError) -> Self {
Self::new("redis error", Some(err))
}
}
impl From<CheckoutError> for Error {
fn from(err: CheckoutError) -> Self {
Self::caused_by(err)
}
}
#[derive(Debug)]
pub struct Error {
message: Option<String>,
cause: Option<Box<dyn StdError + Send + Sync + 'static>>,
}
impl Error {
pub fn new<T: Into<String>, E: StdError + Send + Sync + 'static>(
msg: T,
cause: Option<E>,
) -> Self {
Self {
message: Some(msg.into()),
cause: cause.map(|cause| Box::new(cause) as Box<dyn StdError + Send + Sync + 'static>),
}
}
pub fn message<T: Into<String>>(msg: T) -> Self {
Self {
message: Some(msg.into()),
cause: None,
}
}
pub fn caused_by<E: StdError + Send + Sync + 'static>(cause: E) -> Self {
Self {
message: None,
cause: Some(Box::new(cause)),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match (self.message.as_ref(), self.cause.as_ref()) {
(Some(msg), Some(cause)) => write!(f, "{}: {}", msg, cause),
(Some(msg), None) => write!(f, "{}", msg),
(None, Some(cause)) => write!(f, "an error occurred: {}", cause),
(None, None) => write!(f, "an error occurred"),
}
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.cause.as_ref().map(|cause| &**cause as &dyn StdError)
}
}