Skip to content

Commit

Permalink
chore(reth-storage-errors): no_std support (#10011)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinezjorge committed Aug 13, 2024
1 parent f8db95f commit b52a65b
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 98 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions crates/storage/errors/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ alloy-rlp.workspace = true
reth-primitives.workspace = true
reth-fs-util.workspace = true

thiserror-no-std = { workspace = true, default-features = false }
# misc
derive_more.workspace = true

[features]
default = ["std"]
std = ["thiserror-no-std/std"]
std = []
80 changes: 52 additions & 28 deletions crates/storage/errors/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(feature = "std")]
use std::{fmt::Display, str::FromStr, string::String};
use std::{fmt, fmt::Display, str::FromStr, string::String};

#[cfg(not(feature = "std"))]
use alloc::{
Expand All @@ -8,54 +8,66 @@ use alloc::{
string::{String, ToString},
vec::Vec,
};

#[cfg(not(feature = "std"))]
use core::{fmt::Display, str::FromStr};
use core::{
fmt,
fmt::{Debug, Display},
str::FromStr,
};

/// Database error type.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::Error)]
#[derive(Clone, Debug, PartialEq, Eq, derive_more::Display)]
pub enum DatabaseError {
/// Failed to open the database.
#[error("failed to open the database: {0}")]
#[display(fmt = "failed to open the database: {_0}")]
Open(DatabaseErrorInfo),
/// Failed to create a table in the database.
#[error("failed to create a table: {0}")]
#[display(fmt = "failed to create a table: {_0}")]
CreateTable(DatabaseErrorInfo),
/// Failed to write a value into a table.
#[error(transparent)]
Write(#[from] Box<DatabaseWriteError>),
Write(Box<DatabaseWriteError>),
/// Failed to read a value from a table.
#[error("failed to read a value from a database table: {0}")]
#[display(fmt = "failed to read a value from a database table: {_0}")]
Read(DatabaseErrorInfo),
/// Failed to delete a `(key, value)` pair from a table.
#[error("database delete error code: {0}")]
#[display(fmt = "database delete error code: {_0}")]
Delete(DatabaseErrorInfo),
/// Failed to commit transaction changes into the database.
#[error("failed to commit transaction changes: {0}")]
#[display(fmt = "failed to commit transaction changes: {_0}")]
Commit(DatabaseErrorInfo),
/// Failed to initiate a transaction.
#[error("failed to initialize a transaction: {0}")]
#[display(fmt = "failed to initialize a transaction: {_0}")]
InitTx(DatabaseErrorInfo),
/// Failed to initialize a cursor.
#[error("failed to initialize a cursor: {0}")]
#[display(fmt = "failed to initialize a cursor: {_0}")]
InitCursor(DatabaseErrorInfo),
/// Failed to decode a key from a table.
#[error("failed to decode a key from a table")]
#[display(fmt = "failed to decode a key from a table")]
Decode,
/// Failed to get database stats.
#[error("failed to get stats: {0}")]
#[display(fmt = "failed to get stats: {_0}")]
Stats(DatabaseErrorInfo),
/// Failed to use the specified log level, as it's not available.
#[error("log level {0:?} is not available")]
#[display(fmt = "log level {_0:?} is not available")]
LogLevelUnavailable(LogLevel),
/// Other unspecified error.
#[error("{0}")]
#[display(fmt = "{_0}")]
Other(String),
}

#[cfg(feature = "std")]
impl std::error::Error for DatabaseError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Write(err) => std::error::Error::source(err),
_ => Option::None,
}
}
}

/// Common error struct to propagate implementation-specific error information.
#[derive(Debug, Clone, PartialEq, Eq, thiserror_no_std::Error)]
#[error("{message} ({code})")]
#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
#[display(fmt = "{message} ({code})")]
pub struct DatabaseErrorInfo {
/// Human-readable error message.
pub message: String,
Expand All @@ -68,24 +80,20 @@ where
E: Display + Into<i32>,
{
#[inline]
fn from(value: E) -> Self {
Self { message: value.to_string(), code: value.into() }
fn from(error: E) -> Self {
Self { message: error.to_string(), code: error.into() }
}
}

impl From<DatabaseWriteError> for DatabaseError {
#[inline]
fn from(value: DatabaseWriteError) -> Self {
Self::Write(Box::new(value))
fn from(error: DatabaseWriteError) -> Self {
Self::Write(Box::new(error))
}
}

/// Database write error.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::Error)]
#[error(
"write operation {operation:?} failed for key \"{key}\" in table {table_name:?}: {info}",
key = reth_primitives::hex::encode(key),
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DatabaseWriteError {
/// The error code and message.
pub info: DatabaseErrorInfo,
Expand All @@ -97,6 +105,22 @@ pub struct DatabaseWriteError {
pub key: Vec<u8>,
}

impl fmt::Display for DatabaseWriteError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"write operation {:?} failed for key \"{}\" in table {}: {}",
self.operation,
reth_primitives::hex::encode(&self.key),
self.table_name,
self.info
)
}
}

#[cfg(feature = "std")]
impl std::error::Error for DatabaseWriteError {}

/// Database write operation type.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DatabaseWriteOperation {
Expand Down
15 changes: 10 additions & 5 deletions crates/storage/errors/src/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@ use reth_fs_util::FsPathError;
use alloc::string::{String, ToString};

/// Storage lock error.
#[derive(Debug, Clone, PartialEq, Eq, thiserror_no_std::Error)]
#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
pub enum StorageLockError {
/// Write lock taken
#[error("storage directory is currently in use as read-write by another process: PID {0}")]
#[display(
fmt = "storage directory is currently in use as read-write by another process: PID {_0}"
)]
Taken(usize),
/// Indicates other unspecified errors.
#[error("{0}")]
#[display(fmt = "{_0}")]
Other(String),
}

#[cfg(feature = "std")]
impl std::error::Error for StorageLockError {}

/// TODO: turn into variant once `ProviderError`
impl From<FsPathError> for StorageLockError {
fn from(source: FsPathError) -> Self {
Self::Other(source.to_string())
fn from(error: FsPathError) -> Self {
Self::Other(error.to_string())
}
}
Loading

0 comments on commit b52a65b

Please sign in to comment.