//! Errors for the op log.

use ontoref_types::OpId;

/// Errors surfaced by `OpLog`.
#[derive(Debug, thiserror::Error)]
pub enum Error {
    /// Underlying redb database failure.
    #[error("redb: {0}")]
    Db(String),
    /// Canonical encoding/decoding failure.
    #[error("canonical: {0}")]
    Canonical(#[from] ontoref_types::Error),
    /// Signature verification failed on append.
    #[error("bad signature on operation {0:?}")]
    BadSignature(OpId),
    /// An operation references a parent that is not in the log.
    #[error("unknown parent {0:?}")]
    UnknownParent(OpId),
    /// An operation declares a timestamp not strictly greater than every
    /// parent's.
    #[error("non-monotonic timestamp on operation {0:?}")]
    NonMonotonicTimestamp(OpId),
}

impl From<redb::Error> for Error {
    fn from(err: redb::Error) -> Self {
        Error::Db(err.to_string())
    }
}

impl From<redb::DatabaseError> for Error {
    fn from(err: redb::DatabaseError) -> Self {
        Error::Db(err.to_string())
    }
}

impl From<redb::TransactionError> for Error {
    fn from(err: redb::TransactionError) -> Self {
        Error::Db(err.to_string())
    }
}

impl From<redb::TableError> for Error {
    fn from(err: redb::TableError) -> Self {
        Error::Db(err.to_string())
    }
}

impl From<redb::StorageError> for Error {
    fn from(err: redb::StorageError) -> Self {
        Error::Db(err.to_string())
    }
}

impl From<redb::CommitError> for Error {
    fn from(err: redb::CommitError) -> Self {
        Error::Db(err.to_string())
    }
}

/// Convenience alias.
pub type Result<T> = std::result::Result<T, Error>;
