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#[derive(Clone, Debug, PartialEq, Eq, derive_more::Display)]
15pub enum DatabaseError {
16 #[display("failed to open the database: {_0}")]
18 Open(DatabaseErrorInfo),
19 #[display("failed to create a table: {_0}")]
21 CreateTable(DatabaseErrorInfo),
22 Write(Box<DatabaseWriteError>),
24 #[display("failed to read a value from a database table: {_0}")]
26 Read(DatabaseErrorInfo),
27 #[display("database delete error code: {_0}")]
29 Delete(DatabaseErrorInfo),
30 #[display("failed to commit transaction changes: {_0}")]
32 Commit(DatabaseErrorInfo),
33 #[display("failed to initialize a transaction: {_0}")]
35 InitTx(DatabaseErrorInfo),
36 #[display("failed to initialize a cursor: {_0}")]
38 InitCursor(DatabaseErrorInfo),
39 #[display("failed to decode a key from a table")]
41 Decode,
42 #[display("failed to get stats: {_0}")]
44 Stats(DatabaseErrorInfo),
45 #[display("log level {_0:?} is not available")]
47 LogLevelUnavailable(LogLevel),
48 #[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#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
64#[display("{message} ({code})")]
65pub struct DatabaseErrorInfo {
66 pub message: Box<str>,
68 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#[derive(Clone, Debug, PartialEq, Eq)]
91pub struct DatabaseWriteError {
92 pub info: DatabaseErrorInfo,
94 pub operation: DatabaseWriteOperation,
96 pub table_name: &'static str,
98 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#[derive(Clone, Copy, Debug, PartialEq, Eq)]
119pub enum DatabaseWriteOperation {
120 CursorAppend,
122 CursorUpsert,
124 CursorInsert,
126 CursorAppendDup,
128 Put,
130}
131
132#[derive(Debug, PartialEq, Eq, Clone, Copy)]
134pub enum LogLevel {
135 Fatal,
137 Error,
139 Warn,
141 Notice,
143 Verbose,
145 Debug,
147 Trace,
149 Extra,
151}
152
153impl LogLevel {
154 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 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 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}