1use std::{fmt, path::PathBuf};
2
3#[derive(Debug)]
4pub enum SourceError {
5 Io {
6 path: PathBuf,
7 source: std::io::Error,
8 },
9 Parse {
10 path: PathBuf,
11 message: String,
12 },
13 Serialize(String),
14 Env(String),
15 Crypto(CryptoError),
16 Backend(String),
17 #[cfg(feature = "redb-backend")]
18 Redb(redb::Error),
19}
20
21impl fmt::Display for SourceError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::Io { path, source } => {
25 write!(f, "I/O error reading {}: {source}", path.display())
26 }
27 Self::Parse { path, message } => {
28 write!(f, "parse error in {}: {message}", path.display())
29 }
30 Self::Serialize(msg) => write!(f, "serialization error: {msg}"),
31 Self::Env(msg) => write!(f, "environment variable error: {msg}"),
32 Self::Crypto(e) => write!(f, "crypto error: {e}"),
33 Self::Backend(msg) => write!(f, "backend error: {msg}"),
34 #[cfg(feature = "redb-backend")]
35 Self::Redb(e) => write!(f, "redb error: {e}"),
36 }
37 }
38}
39
40impl std::error::Error for SourceError {
41 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
42 match self {
43 Self::Io { source, .. } => Some(source),
44 Self::Crypto(e) => Some(e),
45 #[cfg(feature = "redb-backend")]
46 Self::Redb(e) => Some(e),
47 _ => None,
48 }
49 }
50}
51
52impl From<CryptoError> for SourceError {
53 fn from(e: CryptoError) -> Self {
54 Self::Crypto(e)
55 }
56}
57
58#[cfg(feature = "redb-backend")]
59mod redb_err {
60 use super::SourceError;
61
62 impl From<redb::Error> for SourceError {
63 fn from(e: redb::Error) -> Self {
64 Self::Redb(e)
65 }
66 }
67 impl From<redb::DatabaseError> for SourceError {
68 fn from(e: redb::DatabaseError) -> Self {
69 Self::Redb(e.into())
70 }
71 }
72 impl From<redb::TransactionError> for SourceError {
73 fn from(e: redb::TransactionError) -> Self {
74 Self::Redb(e.into())
75 }
76 }
77 impl From<redb::TableError> for SourceError {
78 fn from(e: redb::TableError) -> Self {
79 Self::Redb(e.into())
80 }
81 }
82 impl From<redb::StorageError> for SourceError {
83 fn from(e: redb::StorageError) -> Self {
84 Self::Redb(e.into())
85 }
86 }
87 impl From<redb::CommitError> for SourceError {
88 fn from(e: redb::CommitError) -> Self {
89 Self::Redb(e.into())
90 }
91 }
92}
93
94#[derive(Debug)]
95pub enum LoadError {
96 Source(SourceError),
97 Migration(MigrationError),
98 Crypto(CryptoError),
99 Deserialize(crate::deserialize::DeserializeError),
100}
101
102impl fmt::Display for LoadError {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 match self {
105 Self::Source(e) => fmt::Display::fmt(e, f),
106 Self::Migration(e) => fmt::Display::fmt(e, f),
107 Self::Crypto(e) => fmt::Display::fmt(e, f),
108 Self::Deserialize(e) => write!(f, "deserialization failed: {e}"),
109 }
110 }
111}
112
113impl std::error::Error for LoadError {
114 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
115 match self {
116 Self::Source(e) => Some(e),
117 Self::Migration(e) => Some(e),
118 Self::Crypto(e) => Some(e),
119 Self::Deserialize(e) => Some(e),
120 }
121 }
122}
123
124impl From<SourceError> for LoadError {
125 fn from(e: SourceError) -> Self {
126 Self::Source(e)
127 }
128}
129
130impl From<MigrationError> for LoadError {
131 fn from(e: MigrationError) -> Self {
132 Self::Migration(e)
133 }
134}
135
136impl From<CryptoError> for LoadError {
137 fn from(e: CryptoError) -> Self {
138 Self::Crypto(e)
139 }
140}
141
142impl From<crate::deserialize::DeserializeError> for LoadError {
143 fn from(e: crate::deserialize::DeserializeError) -> Self {
144 Self::Deserialize(e)
145 }
146}
147
148#[derive(Debug)]
149pub enum MigrationError {
150 NoPath { from: u32, to: u32 },
151 Step(String),
152}
153
154impl fmt::Display for MigrationError {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 match self {
157 Self::NoPath { from, to } => {
158 write!(f, "no migration path from version {from} to {to}")
159 }
160 Self::Step(msg) => write!(f, "migration step failed: {msg}"),
161 }
162 }
163}
164
165impl std::error::Error for MigrationError {}
166
167#[derive(Debug)]
168pub enum KeyError {
169 Io(std::io::Error),
170 InvalidLength(usize),
171 #[cfg(all(target_os = "linux", feature = "native-keyring"))]
173 NoDaemon,
174 #[cfg(all(target_os = "linux", feature = "native-keyring"))]
175 SecretService(String),
176 #[cfg(all(target_os = "macos", feature = "native-keyring"))]
177 Keychain(security_framework::base::Error),
178 #[cfg(all(windows, feature = "native-keyring"))]
179 CredentialManager(String),
180 #[cfg(feature = "sealed-key")]
181 Kdf(argon2::Error),
182 InvalidBlob,
183 Passphrase,
184}
185
186impl fmt::Display for KeyError {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 match self {
189 Self::Io(e) => write!(f, "I/O error: {e}"),
190 Self::InvalidLength(n) => {
191 write!(f, "invalid key length: expected 32 bytes, got {n}")
192 }
193 #[cfg(all(target_os = "linux", feature = "native-keyring"))]
194 Self::NoDaemon => write!(f, "Secret Service daemon not available"),
195 #[cfg(all(target_os = "linux", feature = "native-keyring"))]
196 Self::SecretService(e) => write!(f, "Secret Service error: {e}"),
197 #[cfg(all(target_os = "macos", feature = "native-keyring"))]
198 Self::Keychain(e) => write!(f, "keychain error: {e}"),
199 #[cfg(all(windows, feature = "native-keyring"))]
200 Self::CredentialManager(msg) => write!(f, "Credential Manager error: {msg}"),
201 #[cfg(feature = "sealed-key")]
202 Self::Kdf(e) => write!(f, "KDF error: {e}"),
203 Self::InvalidBlob => write!(f, "sealed key blob is invalid"),
204 Self::Passphrase => write!(f, "passphrase not available"),
205 }
206 }
207}
208
209impl std::error::Error for KeyError {
210 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
211 match self {
212 Self::Io(e) => Some(e),
213 #[cfg(all(target_os = "linux", feature = "native-keyring"))]
214 Self::NoDaemon | Self::SecretService(_) => None,
215 #[cfg(all(target_os = "macos", feature = "native-keyring"))]
216 Self::Keychain(e) => Some(e),
217 _ => None,
218 }
219 }
220}
221
222impl From<std::io::Error> for KeyError {
223 fn from(e: std::io::Error) -> Self {
224 Self::Io(e)
225 }
226}
227
228#[cfg(all(target_os = "macos", feature = "native-keyring"))]
229impl From<security_framework::base::Error> for KeyError {
230 fn from(e: security_framework::base::Error) -> Self {
231 Self::Keychain(e)
232 }
233}
234
235#[cfg(feature = "sealed-key")]
236impl From<argon2::Error> for KeyError {
237 fn from(e: argon2::Error) -> Self {
238 Self::Kdf(e)
239 }
240}
241
242#[derive(Debug)]
243pub enum CryptoError {
244 Encrypt,
245 Decrypt,
246 InvalidFormat,
247 NotAString(String),
248}
249
250impl fmt::Display for CryptoError {
251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252 match self {
253 Self::Encrypt => write!(f, "encryption failed"),
254 Self::Decrypt => write!(f, "decryption failed"),
255 Self::InvalidFormat => write!(f, "invalid ciphertext format"),
256 Self::NotAString(field) => write!(f, "value at field '{field}' is not a string"),
257 }
258 }
259}
260
261impl std::error::Error for CryptoError {}