chore(reth-storage-errors): no_std support (#10011)

This commit is contained in:
frostburn
2024-08-13 15:56:54 -07:00
committed by GitHub
parent f8db95f45f
commit b52a65bf4f
6 changed files with 177 additions and 98 deletions

2
Cargo.lock generated
View File

@ -8679,9 +8679,9 @@ name = "reth-storage-errors"
version = "1.0.5" version = "1.0.5"
dependencies = [ dependencies = [
"alloy-rlp", "alloy-rlp",
"derive_more",
"reth-fs-util", "reth-fs-util",
"reth-primitives", "reth-primitives",
"thiserror-no-std",
] ]
[[package]] [[package]]

View File

@ -15,8 +15,9 @@ alloy-rlp.workspace = true
reth-primitives.workspace = true reth-primitives.workspace = true
reth-fs-util.workspace = true reth-fs-util.workspace = true
thiserror-no-std = { workspace = true, default-features = false } # misc
derive_more.workspace = true
[features] [features]
default = ["std"] default = ["std"]
std = ["thiserror-no-std/std"] std = []

View File

@ -1,5 +1,5 @@
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::{fmt::Display, str::FromStr, string::String}; use std::{fmt, fmt::Display, str::FromStr, string::String};
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use alloc::{ use alloc::{
@ -8,54 +8,66 @@ use alloc::{
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use core::{fmt::Display, str::FromStr}; use core::{
fmt,
fmt::{Debug, Display},
str::FromStr,
};
/// Database error type. /// Database error type.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::Error)] #[derive(Clone, Debug, PartialEq, Eq, derive_more::Display)]
pub enum DatabaseError { pub enum DatabaseError {
/// Failed to open the database. /// Failed to open the database.
#[error("failed to open the database: {0}")] #[display(fmt = "failed to open the database: {_0}")]
Open(DatabaseErrorInfo), Open(DatabaseErrorInfo),
/// Failed to create a table in the database. /// 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), CreateTable(DatabaseErrorInfo),
/// Failed to write a value into a table. /// Failed to write a value into a table.
#[error(transparent)] Write(Box<DatabaseWriteError>),
Write(#[from] Box<DatabaseWriteError>),
/// Failed to read a value from a table. /// 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), Read(DatabaseErrorInfo),
/// Failed to delete a `(key, value)` pair from a table. /// 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), Delete(DatabaseErrorInfo),
/// Failed to commit transaction changes into the database. /// 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), Commit(DatabaseErrorInfo),
/// Failed to initiate a transaction. /// Failed to initiate a transaction.
#[error("failed to initialize a transaction: {0}")] #[display(fmt = "failed to initialize a transaction: {_0}")]
InitTx(DatabaseErrorInfo), InitTx(DatabaseErrorInfo),
/// Failed to initialize a cursor. /// Failed to initialize a cursor.
#[error("failed to initialize a cursor: {0}")] #[display(fmt = "failed to initialize a cursor: {_0}")]
InitCursor(DatabaseErrorInfo), InitCursor(DatabaseErrorInfo),
/// Failed to decode a key from a table. /// 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, Decode,
/// Failed to get database stats. /// Failed to get database stats.
#[error("failed to get stats: {0}")] #[display(fmt = "failed to get stats: {_0}")]
Stats(DatabaseErrorInfo), Stats(DatabaseErrorInfo),
/// Failed to use the specified log level, as it's not available. /// 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), LogLevelUnavailable(LogLevel),
/// Other unspecified error. /// Other unspecified error.
#[error("{0}")] #[display(fmt = "{_0}")]
Other(String), 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. /// Common error struct to propagate implementation-specific error information.
#[derive(Debug, Clone, PartialEq, Eq, thiserror_no_std::Error)] #[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
#[error("{message} ({code})")] #[display(fmt = "{message} ({code})")]
pub struct DatabaseErrorInfo { pub struct DatabaseErrorInfo {
/// Human-readable error message. /// Human-readable error message.
pub message: String, pub message: String,
@ -68,24 +80,20 @@ where
E: Display + Into<i32>, E: Display + Into<i32>,
{ {
#[inline] #[inline]
fn from(value: E) -> Self { fn from(error: E) -> Self {
Self { message: value.to_string(), code: value.into() } Self { message: error.to_string(), code: error.into() }
} }
} }
impl From<DatabaseWriteError> for DatabaseError { impl From<DatabaseWriteError> for DatabaseError {
#[inline] #[inline]
fn from(value: DatabaseWriteError) -> Self { fn from(error: DatabaseWriteError) -> Self {
Self::Write(Box::new(value)) Self::Write(Box::new(error))
} }
} }
/// Database write error. /// Database write error.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::Error)] #[derive(Clone, Debug, PartialEq, Eq)]
#[error(
"write operation {operation:?} failed for key \"{key}\" in table {table_name:?}: {info}",
key = reth_primitives::hex::encode(key),
)]
pub struct DatabaseWriteError { pub struct DatabaseWriteError {
/// The error code and message. /// The error code and message.
pub info: DatabaseErrorInfo, pub info: DatabaseErrorInfo,
@ -97,6 +105,22 @@ pub struct DatabaseWriteError {
pub key: Vec<u8>, 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. /// Database write operation type.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DatabaseWriteOperation { pub enum DatabaseWriteOperation {

View File

@ -4,19 +4,24 @@ use reth_fs_util::FsPathError;
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
/// Storage lock error. /// Storage lock error.
#[derive(Debug, Clone, PartialEq, Eq, thiserror_no_std::Error)] #[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
pub enum StorageLockError { pub enum StorageLockError {
/// Write lock taken /// 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), Taken(usize),
/// Indicates other unspecified errors. /// Indicates other unspecified errors.
#[error("{0}")] #[display(fmt = "{_0}")]
Other(String), Other(String),
} }
#[cfg(feature = "std")]
impl std::error::Error for StorageLockError {}
/// TODO: turn into variant once `ProviderError` /// TODO: turn into variant once `ProviderError`
impl From<FsPathError> for StorageLockError { impl From<FsPathError> for StorageLockError {
fn from(source: FsPathError) -> Self { fn from(error: FsPathError) -> Self {
Self::Other(source.to_string()) Self::Other(error.to_string())
} }
} }

View File

@ -1,3 +1,5 @@
use crate::{db::DatabaseError, lockfile::StorageLockError, writer::UnifiedStorageWriterError};
use derive_more::Display;
use reth_primitives::{ use reth_primitives::{
Address, BlockHash, BlockHashOrNumber, BlockNumber, GotExpected, StaticFileSegment, Address, BlockHash, BlockHashOrNumber, BlockNumber, GotExpected, StaticFileSegment,
TxHashOrNumber, TxNumber, B256, U256, TxHashOrNumber, TxNumber, B256, U256,
@ -7,44 +9,41 @@ use reth_primitives::{
use std::path::PathBuf; use std::path::PathBuf;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use alloc::{ use alloc::{boxed::Box, string::String};
boxed::Box,
string::{String, ToString},
};
/// Provider result type. /// Provider result type.
pub type ProviderResult<Ok> = Result<Ok, ProviderError>; pub type ProviderResult<Ok> = Result<Ok, ProviderError>;
/// Bundled errors variants thrown by various providers. /// Bundled errors variants thrown by various providers.
#[derive(Clone, Debug, thiserror_no_std::Error, PartialEq, Eq)] #[derive(Clone, Debug, Display, PartialEq, Eq)]
pub enum ProviderError { pub enum ProviderError {
/// Database error. /// Database error.
#[error(transparent)] Database(DatabaseError),
Database(#[from] crate::db::DatabaseError),
/// RLP error. /// RLP error.
#[error(transparent)] Rlp(alloy_rlp::Error),
Rlp(#[from] alloy_rlp::Error),
/// Filesystem path error. /// Filesystem path error.
#[error("{0}")] #[display(fmt = "{_0}")]
FsPathError(String), FsPathError(String),
/// Nippy jar error. /// Nippy jar error.
#[error("nippy jar error: {0}")] #[display(fmt = "nippy jar error: {_0}")]
NippyJar(String), NippyJar(String),
/// Trie witness error. /// Trie witness error.
#[error("trie witness error: {0}")] #[display(fmt = "trie witness error: {_0}")]
TrieWitnessError(String), TrieWitnessError(String),
/// Error when recovering the sender for a transaction /// Error when recovering the sender for a transaction
#[error("failed to recover sender for transaction")] #[display(fmt = "failed to recover sender for transaction")]
SenderRecoveryError, SenderRecoveryError,
/// The header number was not found for the given block hash. /// The header number was not found for the given block hash.
#[error("block hash {0} does not exist in Headers table")] #[display(fmt = "block hash {_0} does not exist in Headers table")]
BlockHashNotFound(BlockHash), BlockHashNotFound(BlockHash),
/// A block body is missing. /// A block body is missing.
#[error("block meta not found for block #{0}")] #[display(fmt = "block meta not found for block #{_0}")]
BlockBodyIndicesNotFound(BlockNumber), BlockBodyIndicesNotFound(BlockNumber),
/// The transition ID was found for the given address and storage key, but the changeset was /// The transition ID was found for the given address and storage key, but the changeset was
/// not found. /// not found.
#[error("storage change set for address {address} and key {storage_key} at block #{block_number} does not exist")] #[display(
fmt = "storage change set for address {address} and key {storage_key} at block #{block_number} does not exist"
)]
StorageChangesetNotFound { StorageChangesetNotFound {
/// The block number found for the address and storage key. /// The block number found for the address and storage key.
block_number: BlockNumber, block_number: BlockNumber,
@ -56,7 +55,9 @@ pub enum ProviderError {
storage_key: Box<B256>, storage_key: Box<B256>,
}, },
/// The block number was found for the given address, but the changeset was not found. /// The block number was found for the given address, but the changeset was not found.
#[error("account change set for address {address} at block #{block_number} does not exist")] #[display(
fmt = "account change set for address {address} at block #{block_number} does not exist"
)]
AccountChangesetNotFound { AccountChangesetNotFound {
/// Block number found for the address. /// Block number found for the address.
block_number: BlockNumber, block_number: BlockNumber,
@ -64,104 +65,133 @@ pub enum ProviderError {
address: Address, address: Address,
}, },
/// The total difficulty for a block is missing. /// The total difficulty for a block is missing.
#[error("total difficulty not found for block #{0}")] #[display(fmt = "total difficulty not found for block #{_0}")]
TotalDifficultyNotFound(BlockNumber), TotalDifficultyNotFound(BlockNumber),
/// when required header related data was not found but was required. /// when required header related data was not found but was required.
#[error("no header found for {0:?}")] #[display(fmt = "no header found for {_0:?}")]
HeaderNotFound(BlockHashOrNumber), HeaderNotFound(BlockHashOrNumber),
/// The specific transaction is missing. /// The specific transaction is missing.
#[error("no transaction found for {0:?}")] #[display(fmt = "no transaction found for {_0:?}")]
TransactionNotFound(TxHashOrNumber), TransactionNotFound(TxHashOrNumber),
/// The specific receipt is missing /// The specific receipt is missing
#[error("no receipt found for {0:?}")] #[display(fmt = "no receipt found for {_0:?}")]
ReceiptNotFound(TxHashOrNumber), ReceiptNotFound(TxHashOrNumber),
/// Unable to find the best block. /// Unable to find the best block.
#[error("best block does not exist")] #[display(fmt = "best block does not exist")]
BestBlockNotFound, BestBlockNotFound,
/// Unable to find the finalized block. /// Unable to find the finalized block.
#[error("finalized block does not exist")] #[display(fmt = "finalized block does not exist")]
FinalizedBlockNotFound, FinalizedBlockNotFound,
/// Unable to find the safe block. /// Unable to find the safe block.
#[error("safe block does not exist")] #[display(fmt = "safe block does not exist")]
SafeBlockNotFound, SafeBlockNotFound,
/// Mismatch of sender and transaction. /// Mismatch of sender and transaction.
#[error("mismatch of sender and transaction id {tx_id}")] #[display(fmt = "mismatch of sender and transaction id {tx_id}")]
MismatchOfTransactionAndSenderId { MismatchOfTransactionAndSenderId {
/// The transaction ID. /// The transaction ID.
tx_id: TxNumber, tx_id: TxNumber,
}, },
/// Block body wrong transaction count. /// Block body wrong transaction count.
#[error("stored block indices does not match transaction count")] #[display(fmt = "stored block indices does not match transaction count")]
BlockBodyTransactionCount, BlockBodyTransactionCount,
/// Thrown when the cache service task dropped. /// Thrown when the cache service task dropped.
#[error("cache service task stopped")] #[display(fmt = "cache service task stopped")]
CacheServiceUnavailable, CacheServiceUnavailable,
/// Thrown when we failed to lookup a block for the pending state. /// Thrown when we failed to lookup a block for the pending state.
#[error("unknown block {0}")] #[display(fmt = "unknown block {_0}")]
UnknownBlockHash(B256), UnknownBlockHash(B256),
/// Thrown when we were unable to find a state for a block hash. /// Thrown when we were unable to find a state for a block hash.
#[error("no state found for block hash {0}")] #[display(fmt = "no state found for block {_0}")]
StateForHashNotFound(B256), StateForHashNotFound(B256),
/// Thrown when we were unable to find a state for a block number. /// Thrown when we were unable to find a state for a block number.
#[error("no state found for block number {0}")] #[display(fmt = "no state found for block number {_0}")]
StateForNumberNotFound(u64), StateForNumberNotFound(u64),
/// Unable to find the block number for a given transaction index. /// Unable to find the block number for a given transaction index.
#[error("unable to find the block number for a given transaction index")] #[display(fmt = "unable to find the block number for a given transaction index")]
BlockNumberForTransactionIndexNotFound, BlockNumberForTransactionIndexNotFound,
/// Root mismatch. /// Root mismatch.
#[error("merkle trie {0}")] #[display(fmt = "merkle trie {_0}")]
StateRootMismatch(Box<RootMismatch>), StateRootMismatch(Box<RootMismatch>),
/// Root mismatch during unwind /// Root mismatch during unwind
#[error("unwind merkle trie {0}")] #[display(fmt = "unwind merkle trie {_0}")]
UnwindStateRootMismatch(Box<RootMismatch>), UnwindStateRootMismatch(Box<RootMismatch>),
/// State is not available for the given block number because it is pruned. /// State is not available for the given block number because it is pruned.
#[error("state at block #{0} is pruned")] #[display(fmt = "state at block #{_0} is pruned")]
StateAtBlockPruned(BlockNumber), StateAtBlockPruned(BlockNumber),
/// Provider does not support this particular request. /// Provider does not support this particular request.
#[error("this provider does not support this request")] #[display(fmt = "this provider does not support this request")]
UnsupportedProvider, UnsupportedProvider,
/// Static File is not found at specified path. /// Static File is not found at specified path.
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[error("not able to find {0} static file at {1}")] #[display(fmt = "not able to find {_0} static file at {_1:?}")]
MissingStaticFilePath(StaticFileSegment, PathBuf), MissingStaticFilePath(StaticFileSegment, PathBuf),
/// Static File is not found for requested block. /// Static File is not found for requested block.
#[error("not able to find {0} static file for block number {1}")] #[display(fmt = "not able to find {_0} static file for block number {_1}")]
MissingStaticFileBlock(StaticFileSegment, BlockNumber), MissingStaticFileBlock(StaticFileSegment, BlockNumber),
/// Static File is not found for requested transaction. /// Static File is not found for requested transaction.
#[error("unable to find {0} static file for transaction id {1}")] #[display(fmt = "unable to find {_0} static file for transaction id {_1}")]
MissingStaticFileTx(StaticFileSegment, TxNumber), MissingStaticFileTx(StaticFileSegment, TxNumber),
/// Static File is finalized and cannot be written to. /// Static File is finalized and cannot be written to.
#[error("unable to write block #{1} to finalized static file {0}")] #[display(fmt = "unable to write block #{_1} to finalized static file {_0}")]
FinalizedStaticFile(StaticFileSegment, BlockNumber), FinalizedStaticFile(StaticFileSegment, BlockNumber),
/// Trying to insert data from an unexpected block number. /// Trying to insert data from an unexpected block number.
#[error("trying to append data to {0} as block #{1} but expected block #{2}")] #[display(fmt = "trying to append data to {_0} as block #{_1} but expected block #{_2}")]
UnexpectedStaticFileBlockNumber(StaticFileSegment, BlockNumber, BlockNumber), UnexpectedStaticFileBlockNumber(StaticFileSegment, BlockNumber, BlockNumber),
/// Static File Provider was initialized as read-only. /// Static File Provider was initialized as read-only.
#[error("cannot get a writer on a read-only environment.")] #[display(fmt = "cannot get a writer on a read-only environment.")]
ReadOnlyStaticFileAccess, ReadOnlyStaticFileAccess,
/// Error encountered when the block number conversion from U256 to u64 causes an overflow. /// Error encountered when the block number conversion from U256 to u64 causes an overflow.
#[error("failed to convert block number U256 to u64: {0}")] #[display(fmt = "failed to convert block number U256 to u64: {_0}")]
BlockNumberOverflow(U256), BlockNumberOverflow(U256),
/// Consistent view error. /// Consistent view error.
#[error("failed to initialize consistent view: {0}")] #[display(fmt = "failed to initialize consistent view: {_0}")]
ConsistentView(Box<ConsistentViewError>), ConsistentView(Box<ConsistentViewError>),
/// Storage lock error. /// Storage lock error.
#[error(transparent)] StorageLockError(StorageLockError),
StorageLockError(#[from] crate::lockfile::StorageLockError),
/// Storage writer error. /// Storage writer error.
#[error(transparent)] UnifiedStorageWriterError(UnifiedStorageWriterError),
UnifiedStorageWriterError(#[from] crate::writer::UnifiedStorageWriterError),
} }
impl From<reth_fs_util::FsPathError> for ProviderError { impl From<DatabaseError> for ProviderError {
fn from(err: reth_fs_util::FsPathError) -> Self { fn from(error: DatabaseError) -> Self {
Self::FsPathError(err.to_string()) Self::Database(error)
}
}
impl From<alloy_rlp::Error> for ProviderError {
fn from(error: alloy_rlp::Error) -> Self {
Self::Rlp(error)
}
}
impl From<StorageLockError> for ProviderError {
fn from(error: StorageLockError) -> Self {
Self::StorageLockError(error)
}
}
impl From<UnifiedStorageWriterError> for ProviderError {
fn from(error: UnifiedStorageWriterError) -> Self {
Self::UnifiedStorageWriterError(error)
}
}
#[cfg(feature = "std")]
impl std::error::Error for ProviderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Database(source) => std::error::Error::source(source),
Self::Rlp(source) => std::error::Error::source(source),
Self::StorageLockError(source) => std::error::Error::source(source),
Self::UnifiedStorageWriterError(source) => std::error::Error::source(source),
_ => Option::None,
}
} }
} }
/// A root mismatch error at a given block height. /// A root mismatch error at a given block height.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::Error)] #[derive(Clone, Debug, PartialEq, Eq, Display)]
#[error("root mismatch at #{block_number} ({block_hash}): {root}")] #[display(fmt = "root mismatch at #{block_number} ({block_hash}): {root}")]
pub struct RootMismatch { pub struct RootMismatch {
/// The target block root diff. /// The target block root diff.
pub root: GotExpected<B256>, pub root: GotExpected<B256>,
@ -172,16 +202,16 @@ pub struct RootMismatch {
} }
/// Consistent database view error. /// Consistent database view error.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::Error)] #[derive(Clone, Debug, PartialEq, Eq, Display)]
pub enum ConsistentViewError { pub enum ConsistentViewError {
/// Error thrown on attempt to initialize provider while node is still syncing. /// Error thrown on attempt to initialize provider while node is still syncing.
#[error("node is syncing. best block: {best_block:?}")] #[display(fmt = "node is syncing. best block: {best_block:?}")]
Syncing { Syncing {
/// Best block diff. /// Best block diff.
best_block: GotExpected<BlockNumber>, best_block: GotExpected<BlockNumber>,
}, },
/// Error thrown on inconsistent database view. /// Error thrown on inconsistent database view.
#[error("inconsistent database state: {tip:?}")] #[display(fmt = "inconsistent database state: {tip:?}")]
Inconsistent { Inconsistent {
/// The tip diff. /// The tip diff.
tip: GotExpected<Option<B256>>, tip: GotExpected<Option<B256>>,
@ -189,7 +219,7 @@ pub enum ConsistentViewError {
} }
impl From<ConsistentViewError> for ProviderError { impl From<ConsistentViewError> for ProviderError {
fn from(value: ConsistentViewError) -> Self { fn from(error: ConsistentViewError) -> Self {
Self::ConsistentView(Box::new(value)) Self::ConsistentView(Box::new(error))
} }
} }

View File

@ -2,15 +2,34 @@ use crate::db::DatabaseError;
use reth_primitives::StaticFileSegment; use reth_primitives::StaticFileSegment;
/// `UnifiedStorageWriter` related errors /// `UnifiedStorageWriter` related errors
#[derive(Clone, Debug, thiserror_no_std::Error, PartialEq, Eq)] /// `StorageWriter` related errors
#[derive(Clone, Debug, derive_more::Display, PartialEq, Eq)]
pub enum UnifiedStorageWriterError { pub enum UnifiedStorageWriterError {
/// Database writer is missing
#[display(fmt = "Database writer is missing")]
MissingDatabaseWriter,
/// Static file writer is missing /// Static file writer is missing
#[error("Static file writer is missing")] #[display(fmt = "Static file writer is missing")]
MissingStaticFileWriter, MissingStaticFileWriter,
/// Static file writer is of wrong segment /// Static file writer is of wrong segment
#[error("Static file writer is of wrong segment: got {0}, expected {1}")] #[display(fmt = "Static file writer is of wrong segment: got {_0}, expected {_1}")]
IncorrectStaticFileWriter(StaticFileSegment, StaticFileSegment), IncorrectStaticFileWriter(StaticFileSegment, StaticFileSegment),
/// Database-related errors. /// Database-related errors.
#[error(transparent)] Database(DatabaseError),
Database(#[from] DatabaseError), }
#[cfg(feature = "std")]
impl std::error::Error for UnifiedStorageWriterError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Database(source) => std::error::Error::source(source),
_ => Option::None,
}
}
}
impl From<DatabaseError> for UnifiedStorageWriterError {
fn from(error: DatabaseError) -> Self {
Self::Database(error)
}
} }