bonsaidb_server/
error.rs

1use std::fmt::Display;
2use std::sync::Arc;
3
4use bonsaidb_core::permissions::PermissionDenied;
5use bonsaidb_core::schema::InsertError;
6use bonsaidb_core::{schema, AnyError};
7use schema::InvalidNameError;
8
9/// An error occurred while interacting with a [`Server`](crate::Server).
10#[derive(Debug, thiserror::Error)]
11pub 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
61impl 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
67impl 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            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    }
79}
80
81impl From<flume::RecvError> for Error {
82    fn from(_: flume::RecvError) -> Self {
83        Self::InternalCommunication
84    }
85}
86
87impl<T> From<flume::SendError<T>> for Error {
88    fn from(_: flume::SendError<T>) -> Self {
89        Self::InternalCommunication
90    }
91}
92
93impl From<tokio::sync::oneshot::error::RecvError> for Error {
94    fn from(_: tokio::sync::oneshot::error::RecvError) -> Self {
95        Self::InternalCommunication
96    }
97}
98
99impl From<tokio::sync::oneshot::error::TryRecvError> for Error {
100    fn from(_: tokio::sync::oneshot::error::TryRecvError) -> Self {
101        Self::InternalCommunication
102    }
103}
104
105impl From<PermissionDenied> for Error {
106    fn from(err: PermissionDenied) -> Self {
107        Self::Core(bonsaidb_core::Error::PermissionDenied(err))
108    }
109}
110
111impl From<InvalidNameError> for Error {
112    fn from(err: InvalidNameError) -> Self {
113        Self::Core(bonsaidb_core::Error::InvalidName(err))
114    }
115}
116
117impl From<rustls::sign::SignError> for Error {
118    fn from(_: rustls::sign::SignError) -> Self {
119        Self::TlsSigningError
120    }
121}
122
123impl<T> From<InsertError<T>> for Error {
124    fn from(error: InsertError<T>) -> Self {
125        Self::from(error.error)
126    }
127}
128
129pub trait ResultExt<R> {
130    fn map_err_to_core(self) -> Result<R, bonsaidb_core::Error>
131    where
132        Self: Sized;
133}
134
135impl<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}
143impl 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")]
150impl From<bincode::Error> for Error {
151    fn from(other: bincode::Error) -> Self {
152        Self::Core(bonsaidb_core::Error::other("bincode", other))
153    }
154}
155
156macro_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
166impl_from_fabruic!(fabruic::error::CertificateChain);
167impl_from_fabruic!(fabruic::error::Receiver);
168impl_from_fabruic!(fabruic::error::Connecting);
169impl_from_fabruic!(fabruic::error::PrivateKey);
170impl_from_fabruic!(fabruic::error::KeyPair);
171impl_from_fabruic!(fabruic::error::Connection);
172impl_from_fabruic!(fabruic::error::Incoming);
173impl_from_fabruic!(fabruic::error::AlreadyClosed);
174impl_from_fabruic!(fabruic::error::Config);
175impl_from_fabruic!(fabruic::error::Builder);