use std::{fmt, io, result};
use std::error::Error;
#[derive(Debug)]
pub struct StorageError(Box<RawStorageError>);
#[derive(Debug)]
struct RawStorageError {
kind: StorageErrorKind,
source: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl StorageError {
pub(crate) fn not_found() -> Self {
Self(Box::new(RawStorageError {
kind: StorageErrorKind::NotFound,
source: None,
}))
}
pub(crate) fn invalid_uuid<E>(error: E) -> Self
where E: Into<Box<dyn std::error::Error + Send + Sync>> {
Self(Box::new(RawStorageError {
kind: StorageErrorKind::InvalidUuid,
source: Some(error.into()),
}))
}
pub(crate) fn io<E>(error: E) -> Self
where E: Into<Box<dyn std::error::Error + Send + Sync>> {
Self(Box::new(RawStorageError {
kind: StorageErrorKind::Io,
source: Some(error.into()),
}))
}
pub(crate) fn other<E>(error: E) -> Self
where E: Into<Box<dyn std::error::Error + Send + Sync>> {
Self(Box::new(RawStorageError {
kind: StorageErrorKind::Other,
source: Some(error.into()),
}))
}
pub fn kind(&self) -> StorageErrorKind {
self.0.kind
}
pub fn is_not_found(&self) -> bool {
StorageErrorKind::NotFound == self.0.kind
}
pub fn is_invalid_uuid(&self) -> bool {
StorageErrorKind::InvalidUuid == self.0.kind
}
pub fn is_io(&self) -> bool {
StorageErrorKind::Io == self.0.kind
}
pub fn is_other(&self) -> bool {
StorageErrorKind::Other == self.0.kind
}
}
impl Error for StorageError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self.0.source {
Some(ref source) => Some(&**source),
None => None
}
}
}
impl fmt::Display for StorageError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.kind.fmt(f)
}
}
impl From<uuid::Error> for StorageError {
fn from(error: uuid::Error) -> Self {
Self::invalid_uuid(error)
}
}
impl From<io::Error> for StorageError {
fn from(error: io::Error) -> Self {
Self::io(error)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum StorageErrorKind {
NotFound,
InvalidUuid,
Io,
Other,
}
impl fmt::Display for StorageErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use StorageErrorKind::*;
match self {
NotFound => write!(f, "entry not found"),
InvalidUuid => write!(f, "invalid uuid"),
Io => write!(f, "io error"),
Other => write!(f, "other error"),
}
}
}
pub type Result<T> = result::Result<T, StorageError>;