reth_storage_errors/
db.rs

1use alloc::{
2    boxed::Box,
3    format,
4    string::{String, ToString},
5    vec::Vec,
6};
7use core::{
8    fmt,
9    fmt::{Debug, Display},
10    str::FromStr,
11};
12
13/// Database error type.
14#[derive(Clone, Debug, PartialEq, Eq, derive_more::Display)]
15pub enum DatabaseError {
16    /// Failed to open the database.
17    #[display("failed to open the database: {_0}")]
18    Open(DatabaseErrorInfo),
19    /// Failed to create a table in the database.
20    #[display("failed to create a table: {_0}")]
21    CreateTable(DatabaseErrorInfo),
22    /// Failed to write a value into a table.
23    Write(Box<DatabaseWriteError>),
24    /// Failed to read a value from a table.
25    #[display("failed to read a value from a database table: {_0}")]
26    Read(DatabaseErrorInfo),
27    /// Failed to delete a `(key, value)` pair from a table.
28    #[display("database delete error code: {_0}")]
29    Delete(DatabaseErrorInfo),
30    /// Failed to commit transaction changes into the database.
31    #[display("failed to commit transaction changes: {_0}")]
32    Commit(DatabaseErrorInfo),
33    /// Failed to initiate a transaction.
34    #[display("failed to initialize a transaction: {_0}")]
35    InitTx(DatabaseErrorInfo),
36    /// Failed to initialize a cursor.
37    #[display("failed to initialize a cursor: {_0}")]
38    InitCursor(DatabaseErrorInfo),
39    /// Failed to decode a key from a table.
40    #[display("failed to decode a key from a table")]
41    Decode,
42    /// Failed to get database stats.
43    #[display("failed to get stats: {_0}")]
44    Stats(DatabaseErrorInfo),
45    /// Failed to use the specified log level, as it's not available.
46    #[display("log level {_0:?} is not available")]
47    LogLevelUnavailable(LogLevel),
48    /// Other unspecified error.
49    #[display("{_0}")]
50    Other(String),
51}
52
53impl core::error::Error for DatabaseError {
54    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
55        match self {
56            Self::Write(err) => core::error::Error::source(err),
57            _ => Option::None,
58        }
59    }
60}
61
62/// Common error struct to propagate implementation-specific error information.
63#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
64#[display("{message} ({code})")]
65pub struct DatabaseErrorInfo {
66    /// Human-readable error message.
67    pub message: Box<str>,
68    /// Error code.
69    pub code: i32,
70}
71
72impl<E> From<E> for DatabaseErrorInfo
73where
74    E: Display + Into<i32>,
75{
76    #[inline]
77    fn from(error: E) -> Self {
78        Self { message: error.to_string().into(), code: error.into() }
79    }
80}
81
82impl From<DatabaseWriteError> for DatabaseError {
83    #[inline]
84    fn from(error: DatabaseWriteError) -> Self {
85        Self::Write(Box::new(error))
86    }
87}
88
89/// Database write error.
90#[derive(Clone, Debug, PartialEq, Eq)]
91pub struct DatabaseWriteError {
92    /// The error code and message.
93    pub info: DatabaseErrorInfo,
94    /// The write operation type.
95    pub operation: DatabaseWriteOperation,
96    /// The table name.
97    pub table_name: &'static str,
98    /// The write key.
99    pub key: Vec<u8>,
100}
101
102impl fmt::Display for DatabaseWriteError {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        write!(
105            f,
106            "write operation {:?} failed for key \"{}\" in table {}: {}",
107            self.operation,
108            alloy_primitives::hex::encode(&self.key),
109            self.table_name,
110            self.info
111        )
112    }
113}
114
115impl core::error::Error for DatabaseWriteError {}
116
117/// Database write operation type.
118#[derive(Clone, Copy, Debug, PartialEq, Eq)]
119pub enum DatabaseWriteOperation {
120    /// Append cursor.
121    CursorAppend,
122    /// Upsert cursor.
123    CursorUpsert,
124    /// Insert cursor.
125    CursorInsert,
126    /// Append duplicate cursor.
127    CursorAppendDup,
128    /// Put.
129    Put,
130}
131
132/// Database log level.
133#[derive(Debug, PartialEq, Eq, Clone, Copy)]
134pub enum LogLevel {
135    /// Enables logging for critical conditions, i.e. assertion failures.
136    Fatal,
137    /// Enables logging for error conditions.
138    Error,
139    /// Enables logging for warning conditions.
140    Warn,
141    /// Enables logging for normal but significant condition.
142    Notice,
143    /// Enables logging for verbose informational.
144    Verbose,
145    /// Enables logging for debug-level messages.
146    Debug,
147    /// Enables logging for trace debug-level messages.
148    Trace,
149    /// Enables logging for extra debug-level messages.
150    Extra,
151}
152
153impl LogLevel {
154    /// All possible variants of the `LogLevel` enum
155    pub const fn value_variants() -> &'static [Self] {
156        &[
157            Self::Fatal,
158            Self::Error,
159            Self::Warn,
160            Self::Notice,
161            Self::Verbose,
162            Self::Debug,
163            Self::Trace,
164            Self::Extra,
165        ]
166    }
167
168    /// Static str reference to `LogLevel` enum, required for `Clap::Builder::PossibleValue::new()`
169    pub const fn variant_name(&self) -> &'static str {
170        match self {
171            Self::Fatal => "fatal",
172            Self::Error => "error",
173            Self::Warn => "warn",
174            Self::Notice => "notice",
175            Self::Verbose => "verbose",
176            Self::Debug => "debug",
177            Self::Trace => "trace",
178            Self::Extra => "extra",
179        }
180    }
181
182    /// Returns all variants descriptions
183    pub const fn help_message(&self) -> &'static str {
184        match self {
185            Self::Fatal => "Enables logging for critical conditions, i.e. assertion failures",
186            Self::Error => "Enables logging for error conditions",
187            Self::Warn => "Enables logging for warning conditions",
188            Self::Notice => "Enables logging for normal but significant condition",
189            Self::Verbose => "Enables logging for verbose informational",
190            Self::Debug => "Enables logging for debug-level messages",
191            Self::Trace => "Enables logging for trace debug-level messages",
192            Self::Extra => "Enables logging for extra debug-level messages",
193        }
194    }
195}
196
197impl FromStr for LogLevel {
198    type Err = String;
199
200    fn from_str(s: &str) -> Result<Self, Self::Err> {
201        match s.to_lowercase().as_str() {
202            "fatal" => Ok(Self::Fatal),
203            "error" => Ok(Self::Error),
204            "warn" => Ok(Self::Warn),
205            "notice" => Ok(Self::Notice),
206            "verbose" => Ok(Self::Verbose),
207            "debug" => Ok(Self::Debug),
208            "trace" => Ok(Self::Trace),
209            "extra" => Ok(Self::Extra),
210            _ => Err(format!("Invalid log level: {s}")),
211        }
212    }
213}