1use bonsaidb_core::arc_bytes::serde::Bytes;
2use bonsaidb_core::networking;
3use bonsaidb_core::schema::Name;
4
5#[derive(thiserror::Error, Debug)]
7pub enum Error {
8 #[cfg(feature = "websockets")]
9 #[error("a transport error occurred: '{0}'")]
11 WebSocket(crate::client::WebSocketError),
12
13 #[error("a networking error occurred: '{0}'")]
15 Network(#[from] bonsaidb_core::networking::Error),
16
17 #[error("invalid url: '{0}'")]
19 InvalidUrl(String),
20
21 #[error("unexpected disconnection")]
23 Core(#[from] bonsaidb_core::Error),
24
25 #[error("api {name} error")]
28 Api {
29 name: Name,
31 error: Bytes,
33 },
34
35 #[error("server incompatible with client protocol version")]
37 ProtocolVersionMismatch,
38}
39
40impl Error {
41 pub(crate) fn disconnected() -> Self {
42 Self::Core(bonsaidb_core::Error::Networking(
43 networking::Error::Disconnected,
44 ))
45 }
46
47 pub(crate) fn request_timeout() -> Self {
48 Self::Core(bonsaidb_core::Error::Networking(
49 networking::Error::RequestTimeout,
50 ))
51 }
52
53 pub(crate) fn connect_timeout() -> Self {
54 Self::Core(bonsaidb_core::Error::Networking(
55 networking::Error::ConnectTimeout,
56 ))
57 }
58}
59
60impl<T> From<flume::SendError<T>> for Error {
61 fn from(_: flume::SendError<T>) -> Self {
62 Self::disconnected()
63 }
64}
65
66impl From<flume::RecvTimeoutError> for Error {
67 fn from(err: flume::RecvTimeoutError) -> Self {
68 match err {
69 flume::RecvTimeoutError::Timeout => Self::request_timeout(),
70 flume::RecvTimeoutError::Disconnected => Self::disconnected(),
71 }
72 }
73}
74
75impl From<flume::RecvError> for Error {
76 fn from(_: flume::RecvError) -> Self {
77 Self::disconnected()
78 }
79}
80
81impl From<Error> for bonsaidb_core::Error {
82 fn from(other: Error) -> Self {
83 match other {
84 Error::Core(err) => err,
85 other => Self::other("bonsaidb-client", other),
86 }
87 }
88}
89
90#[cfg(feature = "websockets")]
91impl From<bincode::Error> for Error {
92 fn from(other: bincode::Error) -> Self {
93 Self::Core(bonsaidb_core::Error::other("bincode", other))
94 }
95}
96
97#[cfg(not(target_arch = "wasm32"))]
98mod fabruic_impls {
99 macro_rules! impl_from_fabruic {
100 ($error:ty) => {
101 impl From<$error> for $crate::Error {
102 fn from(other: $error) -> Self {
103 Self::Core(bonsaidb_core::Error::other("quic", other))
104 }
105 }
106 };
107 }
108
109 impl_from_fabruic!(fabruic::error::Sender);
110 impl_from_fabruic!(fabruic::error::Receiver);
111 impl_from_fabruic!(fabruic::error::Stream);
112 impl_from_fabruic!(fabruic::error::Connecting);
113 impl_from_fabruic!(fabruic::error::Connect);
114}
115
116#[cfg(feature = "websockets")]
117impl From<crate::client::WebSocketError> for Error {
118 #[cfg(not(target_arch = "wasm32"))]
119 fn from(err: crate::client::WebSocketError) -> Self {
120 if let crate::client::WebSocketError::Http(response) = &err {
121 if response.status() == 406 {
122 return Self::ProtocolVersionMismatch;
123 }
124 }
125
126 Self::WebSocket(err)
127 }
128
129 #[cfg(target_arch = "wasm32")]
130 fn from(err: crate::client::WebSocketError) -> Self {
131 Self::WebSocket(err)
132 }
133}
134
135impl From<pot::Error> for Error {
136 fn from(err: pot::Error) -> Self {
137 Self::from(bonsaidb_core::Error::from(err))
138 }
139}
140
141#[derive(thiserror::Error, Debug)]
143pub enum ApiError<T> {
144 #[error("api error: {0}")]
146 Api(T),
147 #[error("client error: {0}")]
149 Client(#[from] Error),
150}
151
152impl From<ApiError<Self>> for bonsaidb_core::Error {
153 fn from(error: ApiError<Self>) -> Self {
154 match error {
155 ApiError::Api(err) => err,
156 ApiError::Client(err) => Self::from(err),
157 }
158 }
159}