use std::fmt;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum StorageError {
#[error("not found: {path}")]
NotFound {
path: String,
},
#[error("already exists: {path}")]
AlreadyExists {
path: String,
},
#[error("compare-and-swap conflict")]
CasConflict,
#[error("storage I/O error: {0}")]
Io(String),
#[error("internal storage error: {0}")]
Internal(Box<dyn std::error::Error + Send + Sync>),
}
impl auths_crypto::AuthsErrorInfo for StorageError {
fn error_code(&self) -> &'static str {
match self {
Self::NotFound { .. } => "AUTHS-E3501",
Self::AlreadyExists { .. } => "AUTHS-E3502",
Self::CasConflict => "AUTHS-E3503",
Self::Io(_) => "AUTHS-E3504",
Self::Internal(_) => "AUTHS-E3505",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::CasConflict => {
Some("Retry the operation — another process made a concurrent change")
}
Self::Io(_) => Some("Check file permissions and disk space"),
_ => None,
}
}
}
impl From<auths_keri::kel_io::KelStorageError> for StorageError {
fn from(err: auths_keri::kel_io::KelStorageError) -> Self {
match err {
auths_keri::kel_io::KelStorageError::NotFound { path } => {
StorageError::NotFound { path }
}
auths_keri::kel_io::KelStorageError::AlreadyExists { path } => {
StorageError::AlreadyExists { path }
}
auths_keri::kel_io::KelStorageError::CasConflict => StorageError::CasConflict,
auths_keri::kel_io::KelStorageError::Io(s) => StorageError::Io(s),
auths_keri::kel_io::KelStorageError::Internal(e) => StorageError::Internal(e),
other => StorageError::Internal(Box::new(other)),
}
}
}
impl StorageError {
pub fn not_found(path: impl fmt::Display) -> Self {
StorageError::NotFound {
path: path.to_string(),
}
}
pub fn already_exists(path: impl fmt::Display) -> Self {
StorageError::AlreadyExists {
path: path.to_string(),
}
}
pub fn internal(err: impl std::error::Error + Send + Sync + 'static) -> Self {
StorageError::Internal(Box::new(err))
}
}