dodo 0.3.1

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

/// Storage 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()),
        }))
    }

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

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

    /// Returns true if this error a InvalidUuid.
    pub fn is_invalid_uuid(&self) -> bool {
        StorageErrorKind::InvalidUuid == self.0.kind
    }

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

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

/// Storage error kind.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum StorageErrorKind {
    /// Entry not found, so the requested operation could not be performed on it.
    NotFound,
    /// Invalid Uuid encountered.
    InvalidUuid,
    /// Io error (unexpected EOF, interrupted, ...).
    Io,
    /// Other error.
    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"),
        }
    }
}

/// Storage result.
pub type Result<T> = result::Result<T, StorageError>;