use thiserror::Error;
#[derive(Error, Debug)]
pub enum StoreError {
#[error("RocksDB operation failed: {0}")]
RocksDb(#[from] rocksdb::Error),
#[error("Serialization failed: {0}")]
Serialization(String),
#[error("Deserialization failed: {0}")]
Deserialization(String),
#[error("Key encoding failed: {0}")]
KeyEncoding(String),
#[error("Key decoding failed: {0}")]
KeyDecoding(String),
#[error("Invalid configuration: {0}")]
InvalidConfiguration(String),
#[error("Operation requires a transaction context")]
TransactionRequired,
#[error("Underlying IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Resource not found for key: {key:?}")]
NotFound { key: Option<Vec<u8>> },
#[error("Merge operation failed: {0}")]
MergeError(String),
#[error("Column Family '{0}' not found or not opened")] UnknownCf(String),
#[error("Operation failed: {0}")]
Other(String),
}
impl Clone for StoreError {
fn clone(&self) -> Self {
match self {
Self::Io(e) => Self::Other(format!("(Cloned) IO error: {}", e)),
Self::RocksDb(e) => Self::RocksDb(e.clone()),
Self::Serialization(s) => Self::Serialization(s.clone()),
Self::Deserialization(s) => Self::Deserialization(s.clone()),
Self::KeyEncoding(s) => Self::KeyEncoding(s.clone()),
Self::KeyDecoding(s) => Self::KeyDecoding(s.clone()),
Self::InvalidConfiguration(s) => Self::InvalidConfiguration(s.clone()),
Self::TransactionRequired => Self::TransactionRequired,
Self::NotFound { key } => Self::NotFound { key: key.clone() },
Self::MergeError(s) => Self::MergeError(s.clone()),
Self::UnknownCf(s) => Self::UnknownCf(s.clone()),
Self::Other(s) => Self::Other(s.clone()),
}
}
}
pub type StoreResult<T> = Result<T, StoreError>;
pub trait StoreResultExt<T> {
fn map_to_option<OkFunc, RVal>(self, ok_fn: OkFunc) -> StoreResult<Option<RVal>>
where
Self: Sized, OkFunc: FnOnce(T) -> Option<RVal>;
fn map_to_vec<OkFunc, RVal>(self, ok_fn: OkFunc) -> StoreResult<Vec<RVal>>
where
Self: Sized,
OkFunc: FnOnce(T) -> Vec<RVal>;
}
impl<T> StoreResultExt<T> for StoreResult<T> {
#[inline]
fn map_to_option<OkFunc, RVal>(self, ok_fn: OkFunc) -> StoreResult<Option<RVal>>
where
OkFunc: FnOnce(T) -> Option<RVal>,
{
match self {
Ok(result_value) => {
Ok(ok_fn(result_value))
}
Err(StoreError::NotFound { .. }) => {
Ok(None)
}
Err(other_err) => {
Err(other_err)
}
}
}
#[inline]
fn map_to_vec<OkFunc, RVal>(self, ok_fn: OkFunc) -> StoreResult<Vec<RVal>>
where
OkFunc: FnOnce(T) -> Vec<RVal>,
{
match self {
Ok(result_value) => {
Ok(ok_fn(result_value))
}
Err(StoreError::NotFound { .. }) => {
Ok(Vec::new())
}
Err(other_err) => {
Err(other_err)
}
}
}
}