dodo 0.3.1

Basic persistence library designed to be a quick and easy way to create a persistent storage.
Documentation
use std::{fmt, result};
use std::error::Error;

use crate::storage::{StorageError, StorageErrorKind};
use crate::serializer::{SerializerError, SerializerErrorKind};

/// Collection error.
#[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()),
        }))
    }

    /// Error kind.
    pub fn kind(&self) -> CollectionErrorKind {
        self.0.kind
    }

    /// Returns true if this error is NotFound.
    pub fn is_not_found(&self) -> bool {
        CollectionErrorKind::NotFound == self.0.kind
    }

    /// Returns true if this error is Unidentified.
    pub fn is_unidentified(&self) -> bool {
        CollectionErrorKind::Unidentified == self.0.kind
    }

    /// Returns true if this error a Syntax.
    pub fn is_syntax(&self) -> bool {
        CollectionErrorKind::Syntax == self.0.kind
    }

    /// Returns true if this error a StorageCorrupted.
    pub fn is_storage_corrupted(&self) -> bool {
        CollectionErrorKind::StorageCorrupted == self.0.kind
    }

    /// Returns true if this error Io.
    pub fn is_io(&self) -> bool {
        CollectionErrorKind::Io == self.0.kind
    }

    /// Returns true if this error is Other.
    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)
        }
    }
}

/// Collection error kind.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum CollectionErrorKind {
    /// Entity not found, so the requested operation could not be performed.
    NotFound,
    /// Entity doesn't have an id, and the requested operation could not be performed.
    Unidentified,
    /// Serialization/deserialization error.
    Syntax,
    /// Storage is in an invalid state and cannot perform the requested operation.
    StorageCorrupted,
    /// Io error (unexpected EOF, interrupted, ...).
    Io,
    /// Other error.
    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"),
        }
    }
}

/// Collection result.
pub type Result<T> = result::Result<T, CollectionError>;