use std::fmt;
use datumesh_core::ErrorCode;
#[non_exhaustive]
#[derive(Debug)]
pub enum Error {
Invalid(datumesh_core::Error),
NotLater {
what: &'static str,
key: String,
given: String,
latest: String,
},
NotFound {
what: &'static str,
key: String,
},
Mismatch {
what: &'static str,
expected: String,
found: String,
},
Conflict {
hash: String,
},
Database(postgres::Error),
PoolTimeout,
Migration(String),
}
impl Error {
pub fn code(&self) -> Option<ErrorCode> {
match self {
Error::Invalid(e) => Some(e.code()),
_ => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Invalid(e) => write!(f, "invalid input: {e}"),
Error::NotLater { what, key, given, latest } => {
write!(f, "{what} {key}: {given} is not later than the latest, {latest}")
}
Error::NotFound { what, key } => write!(f, "no {what} {key} in the store"),
Error::Mismatch { what, expected, found } => {
write!(f, "the receipt's {what} is {found}, not {expected}")
}
Error::Conflict { hash } => {
write!(f, "receipt {hash} is stored with another valid signature; kept the stored one")
}
Error::Database(e) => match e.as_db_error() {
Some(d) => write!(f, "database: {} ({})", d.message(), d.code().code()),
None => write!(f, "database: {e}"),
},
Error::PoolTimeout => f.write_str("no database connection became free in time"),
Error::Migration(m) => write!(f, "migration: {m}"),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Invalid(e) => Some(e),
Error::Database(e) => Some(e),
_ => None,
}
}
}
impl From<postgres::Error> for Error {
fn from(e: postgres::Error) -> Error {
Error::Database(e)
}
}
impl From<datumesh_core::Error> for Error {
fn from(e: datumesh_core::Error) -> Error {
Error::Invalid(e)
}
}
pub type Result<T> = core::result::Result<T, Error>;