1use alloc::{
2 boxed::Box,
3 format,
4 string::{String, ToString},
5 vec::Vec,
6};
7use core::{
8 fmt::{Debug, Display},
9 str::FromStr,
10};
11
12#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
14pub enum DatabaseError {
15 #[error("failed to open the database: {_0}")]
17 Open(DatabaseErrorInfo),
18 #[error("failed to create a table: {_0}")]
20 CreateTable(DatabaseErrorInfo),
21 #[error(transparent)]
23 Write(Box<DatabaseWriteError>),
24 #[error("failed to read a value from a database table: {_0}")]
26 Read(DatabaseErrorInfo),
27 #[error("database delete error code: {_0}")]
29 Delete(DatabaseErrorInfo),
30 #[error("failed to commit transaction changes: {_0}")]
32 Commit(DatabaseErrorInfo),
33 #[error("failed to initialize a transaction: {_0}")]
35 InitTx(DatabaseErrorInfo),
36 #[error("failed to initialize a cursor: {_0}")]
38 InitCursor(DatabaseErrorInfo),
39 #[error("failed to decode a key from a table")]
41 Decode,
42 #[error("failed to get stats: {_0}")]
44 Stats(DatabaseErrorInfo),
45 #[error("log level {_0:?} is not available")]
47 LogLevelUnavailable(LogLevel),
48 #[error("{_0}")]
50 Other(String),
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
55#[display("{message} ({code})")]
56pub struct DatabaseErrorInfo {
57 pub message: Box<str>,
59 pub code: i32,
61}
62
63impl<E> From<E> for DatabaseErrorInfo
64where
65 E: Display + Into<i32>,
66{
67 #[inline]
68 fn from(error: E) -> Self {
69 Self { message: error.to_string().into(), code: error.into() }
70 }
71}
72
73impl From<DatabaseWriteError> for DatabaseError {
74 #[inline]
75 fn from(error: DatabaseWriteError) -> Self {
76 Self::Write(Box::new(error))
77 }
78}
79
80#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
82#[error("write operation {:?} failed for key \"{}\" in table {}: {}",
83 self.operation,
84 alloy_primitives::hex::encode(&self.key),
85 self.table_name,
86 self.info)]
87pub struct DatabaseWriteError {
88 pub info: DatabaseErrorInfo,
90 pub operation: DatabaseWriteOperation,
92 pub table_name: &'static str,
94 pub key: Vec<u8>,
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
100pub enum DatabaseWriteOperation {
101 CursorAppend,
103 CursorUpsert,
105 CursorInsert,
107 CursorAppendDup,
109 Put,
111}
112
113#[derive(Debug, PartialEq, Eq, Clone, Copy)]
115pub enum LogLevel {
116 Fatal,
118 Error,
120 Warn,
122 Notice,
124 Verbose,
126 Debug,
128 Trace,
130 Extra,
132}
133
134impl LogLevel {
135 pub const fn value_variants() -> &'static [Self] {
137 &[
138 Self::Fatal,
139 Self::Error,
140 Self::Warn,
141 Self::Notice,
142 Self::Verbose,
143 Self::Debug,
144 Self::Trace,
145 Self::Extra,
146 ]
147 }
148
149 pub const fn variant_name(&self) -> &'static str {
151 match self {
152 Self::Fatal => "fatal",
153 Self::Error => "error",
154 Self::Warn => "warn",
155 Self::Notice => "notice",
156 Self::Verbose => "verbose",
157 Self::Debug => "debug",
158 Self::Trace => "trace",
159 Self::Extra => "extra",
160 }
161 }
162
163 pub const fn help_message(&self) -> &'static str {
165 match self {
166 Self::Fatal => "Enables logging for critical conditions, i.e. assertion failures",
167 Self::Error => "Enables logging for error conditions",
168 Self::Warn => "Enables logging for warning conditions",
169 Self::Notice => "Enables logging for normal but significant condition",
170 Self::Verbose => "Enables logging for verbose informational",
171 Self::Debug => "Enables logging for debug-level messages",
172 Self::Trace => "Enables logging for trace debug-level messages",
173 Self::Extra => "Enables logging for extra debug-level messages",
174 }
175 }
176}
177
178impl FromStr for LogLevel {
179 type Err = String;
180
181 fn from_str(s: &str) -> Result<Self, Self::Err> {
182 match s.to_lowercase().as_str() {
183 "fatal" => Ok(Self::Fatal),
184 "error" => Ok(Self::Error),
185 "warn" => Ok(Self::Warn),
186 "notice" => Ok(Self::Notice),
187 "verbose" => Ok(Self::Verbose),
188 "debug" => Ok(Self::Debug),
189 "trace" => Ok(Self::Trace),
190 "extra" => Ok(Self::Extra),
191 _ => Err(format!("Invalid log level: {s}")),
192 }
193 }
194}