1use alloc::{
2 boxed::Box,
3 format,
4 string::{String, ToString},
5 sync::Arc,
6 vec::Vec,
7};
8use core::{
9 error::Error,
10 fmt::{Debug, Display},
11 str::FromStr,
12};
13
14#[derive(Clone, Debug, thiserror::Error)]
16pub enum DatabaseError {
17 #[error("failed to open the database: {_0}")]
19 Open(DatabaseErrorInfo),
20 #[error("failed to create a table: {_0}")]
22 CreateTable(DatabaseErrorInfo),
23 #[error(transparent)]
25 Write(Box<DatabaseWriteError>),
26 #[error("failed to read a value from a database table: {_0}")]
28 Read(DatabaseErrorInfo),
29 #[error("database delete error code: {_0}")]
31 Delete(DatabaseErrorInfo),
32 #[error("failed to commit transaction changes: {_0}")]
34 Commit(DatabaseErrorInfo),
35 #[error("failed to initialize a transaction: {_0}")]
37 InitTx(DatabaseErrorInfo),
38 #[error("failed to initialize a cursor: {_0}")]
40 InitCursor(DatabaseErrorInfo),
41 #[error("failed to decode a key from a table")]
43 Decode,
44 #[error("failed to get stats: {_0}")]
46 Stats(DatabaseErrorInfo),
47 #[error("log level {_0:?} is not available")]
49 LogLevelUnavailable(LogLevel),
50 #[error("{_0}")]
52 Other(String),
53 #[error(transparent)]
55 Custom(#[from] Arc<dyn Error + Send + Sync>),
56}
57
58#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
60#[display("{message} ({code})")]
61pub struct DatabaseErrorInfo {
62 pub message: Box<str>,
64 pub code: i32,
66}
67
68impl<E> From<E> for DatabaseErrorInfo
69where
70 E: Display + Into<i32>,
71{
72 #[inline]
73 fn from(error: E) -> Self {
74 Self { message: error.to_string().into(), code: error.into() }
75 }
76}
77
78impl From<DatabaseWriteError> for DatabaseError {
79 #[inline]
80 fn from(error: DatabaseWriteError) -> Self {
81 Self::Write(Box::new(error))
82 }
83}
84
85#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
87#[error("write operation {:?} failed for key \"{}\" in table {}: {}",
88 self.operation,
89 alloy_primitives::hex::encode(&self.key),
90 self.table_name,
91 self.info)]
92pub struct DatabaseWriteError {
93 pub info: DatabaseErrorInfo,
95 pub operation: DatabaseWriteOperation,
97 pub table_name: &'static str,
99 pub key: Vec<u8>,
101}
102
103#[derive(Clone, Copy, Debug, PartialEq, Eq)]
105pub enum DatabaseWriteOperation {
106 CursorAppend,
108 CursorUpsert,
110 CursorInsert,
112 CursorAppendDup,
114 PutUpsert,
116 PutAppend,
118 Flush,
120}
121
122#[derive(Debug, PartialEq, Eq, Clone, Copy)]
124pub enum LogLevel {
125 Fatal,
127 Error,
129 Warn,
131 Notice,
133 Verbose,
135 Debug,
137 Trace,
139 Extra,
141}
142
143impl LogLevel {
144 pub const fn value_variants() -> &'static [Self] {
146 &[
147 Self::Fatal,
148 Self::Error,
149 Self::Warn,
150 Self::Notice,
151 Self::Verbose,
152 Self::Debug,
153 Self::Trace,
154 Self::Extra,
155 ]
156 }
157
158 pub const fn variant_name(&self) -> &'static str {
160 match self {
161 Self::Fatal => "fatal",
162 Self::Error => "error",
163 Self::Warn => "warn",
164 Self::Notice => "notice",
165 Self::Verbose => "verbose",
166 Self::Debug => "debug",
167 Self::Trace => "trace",
168 Self::Extra => "extra",
169 }
170 }
171
172 pub const fn help_message(&self) -> &'static str {
174 match self {
175 Self::Fatal => "Enables logging for critical conditions, i.e. assertion failures",
176 Self::Error => "Enables logging for error conditions",
177 Self::Warn => "Enables logging for warning conditions",
178 Self::Notice => "Enables logging for normal but significant condition",
179 Self::Verbose => "Enables logging for verbose informational",
180 Self::Debug => "Enables logging for debug-level messages",
181 Self::Trace => "Enables logging for trace debug-level messages",
182 Self::Extra => "Enables logging for extra debug-level messages",
183 }
184 }
185}
186
187impl FromStr for LogLevel {
188 type Err = String;
189
190 fn from_str(s: &str) -> Result<Self, Self::Err> {
191 match s.to_lowercase().as_str() {
192 "fatal" => Ok(Self::Fatal),
193 "error" => Ok(Self::Error),
194 "warn" => Ok(Self::Warn),
195 "notice" => Ok(Self::Notice),
196 "verbose" => Ok(Self::Verbose),
197 "debug" => Ok(Self::Debug),
198 "trace" => Ok(Self::Trace),
199 "extra" => Ok(Self::Extra),
200 _ => Err(format!("Invalid log level: {s}")),
201 }
202 }
203}