1use std::error::Error as StdError;
2use std::fmt::{self, Display, Formatter};
3
4use crate::crypto::{Error as CryptoError, ErrorKind as CryptoErrorKind};
5use crate::storage::{Error as StorageError, ErrorKind as StorageErrorKind};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum ErrorKind {
10 Backend,
12
13 Busy,
15
16 Custom,
18
19 Duplicate,
21
22 Encryption,
24
25 Input,
27
28 NotFound,
30
31 Unexpected,
33
34 Unsupported,
36}
37
38impl ErrorKind {
39 pub fn as_str(&self) -> &'static str {
41 match self {
42 Self::Backend => "Backend error",
43 Self::Busy => "Busy",
44 Self::Custom => "Custom error",
45 Self::Duplicate => "Duplicate",
46 Self::Encryption => "Encryption error",
47 Self::Input => "Input error",
48 Self::NotFound => "Not found",
49 Self::Unexpected => "Unexpected error",
50 Self::Unsupported => "Unsupported",
51 }
52 }
53}
54
55impl Display for ErrorKind {
56 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
57 f.write_str(self.as_str())
58 }
59}
60
61#[derive(Debug)]
63pub struct Error {
64 pub(crate) kind: ErrorKind,
65 pub(crate) cause: Option<Box<dyn StdError + Send + Sync + 'static>>,
66 pub(crate) message: Option<String>,
67}
68
69impl Error {
70 pub(crate) fn from_msg<T: Into<String>>(kind: ErrorKind, msg: T) -> Self {
71 Self {
72 kind,
73 cause: None,
74 message: Some(msg.into()),
75 }
76 }
77
78 pub fn kind(&self) -> ErrorKind {
80 self.kind
81 }
82
83 pub fn message(&self) -> Option<&str> {
85 self.message.as_deref()
86 }
87
88 pub(crate) fn with_cause<T: Into<Box<dyn StdError + Send + Sync + 'static>>>(
89 mut self,
90 err: T,
91 ) -> Self {
92 self.cause = Some(err.into());
93 self
94 }
95}
96
97impl Display for Error {
98 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
99 if let Some(msg) = self.message.as_ref() {
100 f.write_str(msg)?;
101 } else {
102 f.write_str(self.kind.as_str())?;
103 }
104 if let Some(cause) = self.cause.as_ref() {
105 write!(f, "\nCaused by: {}", cause)?;
106 }
107 Ok(())
108 }
109}
110
111impl StdError for Error {
112 fn source(&self) -> Option<&(dyn StdError + 'static)> {
113 self.cause
114 .as_ref()
115 .map(|err| &**err as &(dyn StdError + 'static))
116 }
117}
118
119impl PartialEq for Error {
120 fn eq(&self, other: &Self) -> bool {
121 self.kind == other.kind && self.message == other.message
122 }
123}
124
125impl From<ErrorKind> for Error {
126 fn from(kind: ErrorKind) -> Self {
127 Self {
128 kind,
129 cause: None,
130 message: None,
131 }
132 }
133}
134
135impl From<CryptoError> for Error {
136 fn from(err: CryptoError) -> Self {
137 let kind = match err.kind() {
138 CryptoErrorKind::Custom => ErrorKind::Custom,
139 CryptoErrorKind::Encryption => ErrorKind::Encryption,
140 CryptoErrorKind::ExceededBuffer | CryptoErrorKind::Unexpected => ErrorKind::Unexpected,
141 CryptoErrorKind::Invalid
142 | CryptoErrorKind::InvalidKeyData
143 | CryptoErrorKind::InvalidNonce
144 | CryptoErrorKind::MissingSecretKey
145 | CryptoErrorKind::Usage => ErrorKind::Input,
146 CryptoErrorKind::Unsupported => ErrorKind::Unsupported,
147 };
148 Error::from_msg(kind, err.message())
149 }
150}
151
152impl From<StorageError> for Error {
153 fn from(err: StorageError) -> Self {
154 let (kind, cause, message) = err.into_parts();
155 let kind = match kind {
156 StorageErrorKind::Backend => ErrorKind::Backend,
157 StorageErrorKind::Busy => ErrorKind::Busy,
158 StorageErrorKind::Custom => ErrorKind::Custom,
159 StorageErrorKind::Duplicate => ErrorKind::Duplicate,
160 StorageErrorKind::Encryption => ErrorKind::Encryption,
161 StorageErrorKind::Input => ErrorKind::Input,
162 StorageErrorKind::NotFound => ErrorKind::NotFound,
163 StorageErrorKind::Unexpected => ErrorKind::Unexpected,
164 StorageErrorKind::Unsupported => ErrorKind::Unsupported,
165 };
166 Error {
167 kind,
168 cause,
169 message,
170 }
171 }
172}
173
174macro_rules! err_msg {
175 () => {
176 $crate::error::Error::from($crate::error::ErrorKind::Input)
177 };
178 ($kind:ident) => {
179 $crate::error::Error::from($crate::error::ErrorKind::$kind)
180 };
181 ($kind:ident, $($args:tt)+) => {
182 $crate::error::Error::from_msg($crate::error::ErrorKind::$kind, format!($($args)+))
183 };
184 ($($args:tt)+) => {
185 $crate::error::Error::from_msg($crate::error::ErrorKind::Input, format!($($args)+))
186 };
187}
188
189macro_rules! err_map {
190 ($($params:tt)*) => {
191 |err| err_msg!($($params)*).with_cause(err)
192 };
193}