use std::{fmt, result};
use std::error::Error;
use crate::storage::{StorageError, StorageErrorKind};
use crate::serializer::{SerializerError, SerializerErrorKind};
#[derive(Debug)]
pub struct CollectionError(Box<RawCollectionError>);
#[derive(Debug)]
struct RawCollectionError {
kind: CollectionErrorKind,
source: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl CollectionError {
pub(crate) fn not_found() -> Self {
Self(Box::new(RawCollectionError {
kind: CollectionErrorKind::NotFound,
source: None,
}))
}
pub(crate) fn unidentified() -> Self {
Self(Box::new(RawCollectionError {
kind: CollectionErrorKind::Unidentified,
source: None,
}))
}
pub(crate) fn syntax<E>(error: E) -> Self
where E: Into<Box<dyn std::error::Error + Send + Sync>> {
Self(Box::new(RawCollectionError {
kind: CollectionErrorKind::Syntax,
source: Some(error.into()),
}))
}
pub(crate) fn storage_corrupted<E>(error: E) -> Self
where E: Into<Box<dyn std::error::Error + Send + Sync>> {
Self(Box::new(RawCollectionError {
kind: CollectionErrorKind::StorageCorrupted,
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(RawCollectionError {
kind: CollectionErrorKind::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(RawCollectionError {
kind: CollectionErrorKind::Other,
source: Some(error.into()),
}))
}
pub fn kind(&self) -> CollectionErrorKind {
self.0.kind
}
pub fn is_not_found(&self) -> bool {
CollectionErrorKind::NotFound == self.0.kind
}
pub fn is_unidentified(&self) -> bool {
CollectionErrorKind::Unidentified == self.0.kind
}
pub fn is_syntax(&self) -> bool {
CollectionErrorKind::Syntax == self.0.kind
}
pub fn is_storage_corrupted(&self) -> bool {
CollectionErrorKind::StorageCorrupted == self.0.kind
}
pub fn is_io(&self) -> bool {
CollectionErrorKind::Io == self.0.kind
}
pub fn is_other(&self) -> bool {
CollectionErrorKind::Other == self.0.kind
}
}
impl Error for CollectionError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self.0.source {
Some(ref source) => Some(&**source),
None => None
}
}
}
impl fmt::Display for CollectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.kind.fmt(f)
}
}
impl From<StorageError> for CollectionError {
fn from(error: StorageError) -> Self {
use StorageErrorKind::*;
match error.kind() {
NotFound => Self::not_found(),
InvalidUuid => Self::storage_corrupted(error),
Io => Self::io(error),
Other => Self::other(error)
}
}
}
impl From<SerializerError> for CollectionError {
fn from(error: SerializerError) -> Self {
use SerializerErrorKind::*;
match error.kind() {
Syntax => Self::syntax(error),
Io => Self::io(error),
Other => Self::other(error)
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum CollectionErrorKind {
NotFound,
Unidentified,
Syntax,
StorageCorrupted,
Io,
Other,
}
impl fmt::Display for CollectionErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CollectionErrorKind::*;
match self {
NotFound => write!(f, "entity not found"),
Unidentified => write!(f, "entity doesn't have an id"),
Syntax => write!(f, "serialization/deserialization error"),
StorageCorrupted => write!(f, "storage is corrupted"),
Io => write!(f, "io error"),
Other => write!(f, "other error"),
}
}
}
pub type Result<T> = result::Result<T, CollectionError>;