1
use std::fmt::Display;
2
use std::sync::Arc;
3

            
4
use bonsaidb_core::permissions::PermissionDenied;
5
use bonsaidb_core::schema::InsertError;
6
use bonsaidb_core::{schema, AnyError};
7
use schema::InvalidNameError;
8

            
9
/// An error occurred while interacting with a [`Server`](crate::Server).
10
14
#[derive(Debug, thiserror::Error)]
11
pub enum Error {
12
    #[cfg(feature = "websockets")]
13
    /// An error occurred from the Websocket transport layer.
14
    #[error("a websocket error occurred: '{0}'")]
15
    WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
16

            
17
    /// An error occurred from IO
18
    #[error("a networking error occurred: '{0}'")]
19
    Io(#[from] tokio::io::Error),
20

            
21
    /// An error occurred while processing a request
22
    #[error("an error occurred processing a request: '{0}'")]
23
    Request(Arc<dyn AnyError>),
24

            
25
    /// An error occurred from within the schema.
26
    #[error("error from core {0}")]
27
    Core(#[from] bonsaidb_core::Error),
28

            
29
    /// An internal error occurred while waiting for a message.
30
    #[error("error while waiting for a message")]
31
    InternalCommunication,
32

            
33
    /// An error occurred while interacting with a local database.
34
    #[error("an error occurred interacting with a database: {0}")]
35
    Database(#[from] bonsaidb_local::Error),
36

            
37
    /// An error occurred with a certificate.
38
    #[error("a certificate error: {0}")]
39
    Certificate(#[from] fabruic::error::Certificate),
40

            
41
    /// An error occurred parsing a PEM file.
42
    #[error("an invalid PEM file: {0}")]
43
    #[cfg(feature = "pem")]
44
    Pem(#[from] pem::PemError),
45

            
46
    /// An error occurred requesting an ACME certificate.
47
    #[error("an error requesting an ACME certificate: {0}")]
48
    #[cfg(feature = "acme")]
49
    Acme(#[from] async_acme::acme::AcmeError),
50

            
51
    /// An error occurred while processing an ACME order.
52
    #[error("an error occurred while processing an ACME order: {0}")]
53
    #[cfg(feature = "acme")]
54
    AcmeOrder(#[from] async_acme::rustls_helper::OrderError),
55

            
56
    /// An error occurred during tls signing.
57
    #[error("an error occurred during tls signing")]
58
    TlsSigningError,
59
}
60

            
61
impl Error {
62
    pub(crate) fn other(origin: impl Display, error: impl Display) -> Self {
63
        Self::Core(bonsaidb_core::Error::other(origin, error))
64
    }
65
}
66

            
67
impl From<Error> for bonsaidb_core::Error {
68
    fn from(other: Error) -> Self {
69
        // without it, there's no way to get this to_string() easily.
70
        match other {
71
7882
            Error::Core(core) | Error::Database(bonsaidb_local::Error::Core(core)) => core,
72
            Error::Database(storage) => Self::from(storage),
73
            Error::Io(io) => Self::other("io", io),
74
            #[cfg(feature = "websockets")]
75
            Error::WebSocket(err) => Self::other("bonsaidb-server websockets", err),
76
            err => Self::other("bonsaidb-server", err),
77
        }
78
7882
    }
79
}
80

            
81
impl From<flume::RecvError> for Error {
82
    fn from(_: flume::RecvError) -> Self {
83
        Self::InternalCommunication
84
    }
85
}
86

            
87
impl<T> From<flume::SendError<T>> for Error {
88
    fn from(_: flume::SendError<T>) -> Self {
89
        Self::InternalCommunication
90
    }
91
}
92

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

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

            
105
impl From<PermissionDenied> for Error {
106
    fn from(err: PermissionDenied) -> Self {
107
        Self::Core(bonsaidb_core::Error::PermissionDenied(err))
108
    }
109
}
110

            
111
impl From<InvalidNameError> for Error {
112
    fn from(err: InvalidNameError) -> Self {
113
        Self::Core(bonsaidb_core::Error::InvalidName(err))
114
    }
115
}
116

            
117
impl From<rustls::sign::SignError> for Error {
118
    fn from(_: rustls::sign::SignError) -> Self {
119
        Self::TlsSigningError
120
    }
121
}
122

            
123
impl<T> From<InsertError<T>> for Error {
124
    fn from(error: InsertError<T>) -> Self {
125
        Self::from(error.error)
126
    }
127
}
128

            
129
pub trait ResultExt<R> {
130
    fn map_err_to_core(self) -> Result<R, bonsaidb_core::Error>
131
    where
132
        Self: Sized;
133
}
134

            
135
impl<R> ResultExt<R> for Result<R, Error> {
136
    fn map_err_to_core(self) -> Result<R, bonsaidb_core::Error>
137
    where
138
        Self: Sized,
139
    {
140
        self.map_err(bonsaidb_core::Error::from)
141
    }
142
}
143
impl From<pot::Error> for Error {
144
    fn from(other: pot::Error) -> Self {
145
        Self::Core(bonsaidb_core::Error::from(other))
146
    }
147
}
148

            
149
#[cfg(feature = "websockets")]
150
impl From<bincode::Error> for Error {
151
    fn from(other: bincode::Error) -> Self {
152
        Self::Core(bonsaidb_core::Error::other("bincode", other))
153
    }
154
}
155

            
156
macro_rules! impl_from_fabruic {
157
    ($error:ty) => {
158
        impl From<$error> for Error {
159
            fn from(other: $error) -> Self {
160
                Self::Core(bonsaidb_core::Error::other("bonsaidb-server quic", other))
161
            }
162
        }
163
    };
164
}
165

            
166
impl_from_fabruic!(fabruic::error::CertificateChain);
167
impl_from_fabruic!(fabruic::error::Receiver);
168
impl_from_fabruic!(fabruic::error::Connecting);
169
impl_from_fabruic!(fabruic::error::PrivateKey);
170
impl_from_fabruic!(fabruic::error::KeyPair);
171
impl_from_fabruic!(fabruic::error::Connection);
172
impl_from_fabruic!(fabruic::error::Incoming);
173
impl_from_fabruic!(fabruic::error::AlreadyClosed);
174
impl_from_fabruic!(fabruic::error::Config);
175
impl_from_fabruic!(fabruic::error::Builder);