1
use std::{convert::Infallible, str::Utf8Error, string::FromUtf8Error, sync::Arc};
2

            
3
use bonsaidb_core::{
4
    permissions::PermissionDenied,
5
    schema::{view, InvalidNameError},
6
    AnyError,
7
};
8
use nebari::AbortError;
9

            
10
/// Errors that can occur from interacting with storage.
11
3
#[derive(thiserror::Error, Debug)]
12
pub enum Error {
13
    /// An error occurred interacting with the storage layer, `nebari`.
14
    #[error("error from storage: {0}")]
15
    Nebari(#[from] nebari::Error),
16

            
17
    /// An error occurred serializing the underlying database structures.
18
    #[error("error while serializing internal structures: {0}")]
19
    InternalSerialization(#[from] bincode::Error),
20

            
21
    /// An error occurred serializing the contents of a `Document` or results of a `View`.
22
    #[error("error while serializing: {0}")]
23
    Serialization(#[from] pot::Error),
24

            
25
    /// An internal error occurred while waiting for or sending a message.
26
    #[error("error while communicating internally")]
27
    InternalCommunication,
28

            
29
    /// An error occurred while executing a view
30
    #[error("error from view: {0}")]
31
    View(#[from] view::Error),
32

            
33
    /// An error occurred in the secrets storage layer.
34
    #[error("a vault error occurred: {0}")]
35
    #[cfg(feature = "encryption")]
36
    Vault(#[from] crate::vault::Error),
37

            
38
    /// An error occurred decompressing a stored value.
39
    #[error("a vault error occurred: {0}")]
40
    #[cfg(feature = "compression")]
41
    Compression(#[from] lz4_flex::block::DecompressError),
42

            
43
    /// A collection requested to be encrypted, but encryption is disabled.
44
    #[error("encryption is disabled, but a collection is requesting encryption")]
45
    #[cfg(not(feature = "encryption"))]
46
    EncryptionDisabled,
47

            
48
    /// An core error occurred.
49
    #[error("a core error occurred: {0}")]
50
    Core(#[from] bonsaidb_core::Error),
51

            
52
    /// A tokio task failed to execute.
53
    #[error("a concurrency error ocurred: {0}")]
54
    TaskJoin(#[from] tokio::task::JoinError),
55

            
56
    /// A tokio task failed to execute.
57
    #[error("an IO error occurred: {0}")]
58
    Io(#[from] tokio::io::Error),
59

            
60
    /// An error occurred from a job and couldn't be unwrapped due to clones.
61
    #[error("an error from a job occurred: {0}")]
62
    Job(Arc<Error>),
63

            
64
    /// An error occurred from backing up or restoring.
65
    #[error("a backup error: {0}")]
66
    Backup(Box<dyn AnyError>),
67

            
68
    /// An error occurred with a password hash.
69
    #[cfg(feature = "password-hashing")]
70
    #[error("password hash error: {0}")]
71
    PasswordHash(String),
72
}
73

            
74
impl From<flume::RecvError> for Error {
75
    fn from(_: flume::RecvError) -> Self {
76
        Self::InternalCommunication
77
    }
78
}
79

            
80
#[cfg(feature = "password-hashing")]
81
impl From<argon2::Error> for Error {
82
    fn from(err: argon2::Error) -> Self {
83
        Self::PasswordHash(err.to_string())
84
    }
85
}
86

            
87
#[cfg(feature = "password-hashing")]
88
impl From<argon2::password_hash::Error> for Error {
89
    fn from(err: argon2::password_hash::Error) -> Self {
90
        Self::PasswordHash(err.to_string())
91
    }
92
}
93

            
94
impl From<tokio::sync::oneshot::error::RecvError> for Error {
95
    fn from(_: tokio::sync::oneshot::error::RecvError) -> Self {
96
        Self::InternalCommunication
97
    }
98
}
99

            
100
impl From<tokio::sync::oneshot::error::TryRecvError> for Error {
101
    fn from(_: tokio::sync::oneshot::error::TryRecvError) -> Self {
102
        Self::InternalCommunication
103
    }
104
}
105

            
106
impl From<Error> for bonsaidb_core::Error {
107
    fn from(err: Error) -> Self {
108
77
        match err {
109
15584
            Error::View(view::Error::Core(core)) | Error::Core(core) => core,
110
2
            other => Self::Database(other.to_string()),
111
        }
112
15586
    }
113
}
114

            
115
impl From<Arc<Error>> for Error {
116
    fn from(err: Arc<Error>) -> Self {
117
        match Arc::try_unwrap(err) {
118
            Ok(err) => err,
119
            Err(still_wrapped) => Error::Job(still_wrapped),
120
        }
121
    }
122
}
123

            
124
impl From<FromUtf8Error> for Error {
125
    fn from(err: FromUtf8Error) -> Self {
126
        Self::Core(bonsaidb_core::Error::InvalidUnicode(err.to_string()))
127
    }
128
}
129

            
130
impl From<Utf8Error> for Error {
131
    fn from(err: Utf8Error) -> Self {
132
        Self::Core(bonsaidb_core::Error::InvalidUnicode(err.to_string()))
133
    }
134
}
135

            
136
impl From<InvalidNameError> for Error {
137
    fn from(err: InvalidNameError) -> Self {
138
        Self::Core(bonsaidb_core::Error::from(err))
139
    }
140
}
141

            
142
impl From<AbortError<Infallible>> for Error {
143
    fn from(err: AbortError<Infallible>) -> Self {
144
        match err {
145
            AbortError::Nebari(error) => Self::Nebari(error),
146
            AbortError::Other(_) => unreachable!(),
147
        }
148
    }
149
}
150

            
151
impl From<AbortError<Error>> for Error {
152
    fn from(err: AbortError<Error>) -> Self {
153
        match err {
154
            AbortError::Nebari(error) => Self::Nebari(error),
155
            AbortError::Other(error) => error,
156
        }
157
    }
158
}
159

            
160
impl From<PermissionDenied> for Error {
161
2
    fn from(err: PermissionDenied) -> Self {
162
2
        Self::Core(bonsaidb_core::Error::from(err))
163
2
    }
164
}
165

            
166
1
#[test]
167
1
fn test_converting_error() {
168
1
    use serde::ser::Error as _;
169
1
    let err: bonsaidb_core::Error = Error::Serialization(pot::Error::custom("mymessage")).into();
170
1
    match err {
171
1
        bonsaidb_core::Error::Database(storage_error) => {
172
1
            assert!(storage_error.contains("mymessage"));
173
        }
174
        _ => unreachable!(),
175
    }
176
1
}