1use crate::{api::Response, Value};
2use serde::Serialize;
3use std::path::PathBuf;
4use std::{convert::Infallible, io};
5use surrealdb_core::dbs::capabilities::{ParseFuncTargetError, ParseNetTargetError};
6use thiserror::Error;
7
8#[derive(Error, Debug)]
10#[non_exhaustive]
11pub enum Error {
12 #[error("{0}")]
14 Query(String),
15
16 #[error("There was an error processing a remote HTTP request: {0}")]
18 Http(String),
19
20 #[error("There was an error processing a remote WS request: {0}")]
22 Ws(String),
23
24 #[error("Unsupported protocol or storage engine, `{0}`")]
26 Scheme(String),
27
28 #[error("Connection uninitialised")]
30 ConnectionUninitialised,
31
32 #[error("Already connected")]
34 AlreadyConnected,
35
36 #[error("Invalid bindings: {0}")]
38 InvalidBindings(Value),
39
40 #[error("Tried to add a range to an record-id resource")]
42 RangeOnRecordId,
43
44 #[error("Tried to add a range to an object resource")]
46 RangeOnObject,
47
48 #[error("Tried to add a range to an array resource")]
50 RangeOnArray,
51
52 #[error("Tried to add a range to an edge resource")]
54 RangeOnEdges,
55
56 #[error("Tried to add a range to a resource which was already a range")]
58 RangeOnRange,
59
60 #[error("Tried to add a range to an unspecified resource")]
62 RangeOnUnspecified,
63
64 #[error("Table name `{table}` contained a colon (:), this is dissallowed to avoid confusion with record-id's try `Table(\"{table}\")` instead.")]
66 TableColonId {
67 table: String,
68 },
69
70 #[error("Duplicate request ID: {0}")]
72 DuplicateRequestId(i64),
73
74 #[error("Invalid request: {0}")]
76 InvalidRequest(String),
77
78 #[error("Invalid params: {0}")]
80 InvalidParams(String),
81
82 #[error("Internal error: {0}")]
84 InternalError(String),
85
86 #[error("Parse error: {0}")]
88 ParseError(String),
89
90 #[error("Invalid semantic version: {0}")]
92 InvalidSemanticVersion(String),
93
94 #[error("Invalid URL: {0}")]
96 InvalidUrl(String),
97
98 #[error("Failed to convert `{value}` to `T`: {error}")]
100 FromValue {
101 value: Value,
102 error: String,
103 },
104
105 #[error("Failed to deserialize a binary response: {error}")]
107 ResponseFromBinary {
108 binary: Vec<u8>,
109 error: bincode::Error,
110 },
111
112 #[error("Failed to serialize `{value}` to JSON string: {error}")]
114 ToJsonString {
115 value: Value,
116 error: String,
117 },
118
119 #[error("Failed to deserialize `{string}` to sql::Value: {error}")]
121 FromJsonString {
122 string: String,
123 error: String,
124 },
125
126 #[error("Invalid namespace name: {0:?}")]
128 InvalidNsName(String),
129
130 #[error("Invalid database name: {0:?}")]
132 InvalidDbName(String),
133
134 #[error("Failed to open `{path}`: {error}")]
136 FileOpen {
137 path: PathBuf,
138 error: io::Error,
139 },
140
141 #[error("Failed to read `{path}`: {error}")]
143 FileRead {
144 path: PathBuf,
145 error: io::Error,
146 },
147
148 #[error("Tried to take only a single result from a query that contains multiple")]
150 LossyTake(Response),
151
152 #[error("The protocol or storage engine does not support backups on this architecture")]
155 BackupsNotSupported,
156
157 #[error("server version `{server_version}` does not match the range supported by the client `{supported_versions}`")]
159 VersionMismatch {
160 server_version: semver::Version,
161 supported_versions: String,
162 },
163
164 #[error("server build `{server_metadata}` is older than the minimum supported build `{supported_metadata}`")]
166 BuildMetadataMismatch {
167 server_metadata: semver::BuildMetadata,
168 supported_metadata: semver::BuildMetadata,
169 },
170
171 #[error("The protocol or storage engine does not support live queries on this architecture")]
174 LiveQueriesNotSupported,
175
176 #[error("Live queries on objects not supported")]
178 LiveOnObject,
179
180 #[error("Live queries on arrays not supported")]
182 LiveOnArray,
183
184 #[error("Live queries on edges not supported")]
186 LiveOnEdges,
187
188 #[error("Live queries on unspecified resource not supported")]
190 LiveOnUnspecified,
191
192 #[error("Query statement {0} is not a live query")]
194 NotLiveQuery(usize),
195
196 #[error("Query statement {0} is out of bounds")]
198 QueryIndexOutOfBounds(usize),
199
200 #[error("Tried to take a query response that has already been taken")]
202 ResponseAlreadyTaken,
203
204 #[error("Insert queries on objects are not supported")]
206 InsertOnObject,
207
208 #[error("Insert queries on arrays are not supported")]
210 InsertOnArray,
211
212 #[error("Insert queries on edges are not supported")]
214 InsertOnEdges,
215
216 #[error("Insert queries on ranges are not supported")]
218 InsertOnRange,
219
220 #[error("Insert queries on unspecified resource with no data are not supported")]
222 InsertOnUnspecified,
223
224 #[error("{0}")]
225 InvalidNetTarget(#[from] ParseNetTargetError),
226
227 #[error("{0}")]
228 InvalidFuncTarget(#[from] ParseFuncTargetError),
229
230 #[error("failed to serialize Value: {0}")]
231 SerializeValue(String),
232 #[error("failed to deserialize Value: {0}")]
233 DeSerializeValue(String),
234
235 #[error("failed to serialize to a Value: {0}")]
236 Serializer(String),
237 #[error("failed to deserialize from a Value: {0}")]
238 Deserializer(String),
239
240 #[error("tried to convert from a value which contained non-primitive values to a value which only allows primitive values.")]
242 RecievedInvalidValue,
243}
244
245impl serde::ser::Error for Error {
246 fn custom<T>(msg: T) -> Self
247 where
248 T: std::fmt::Display,
249 {
250 Error::SerializeValue(msg.to_string())
251 }
252}
253
254impl serde::de::Error for Error {
255 fn custom<T>(msg: T) -> Self
256 where
257 T: std::fmt::Display,
258 {
259 Error::DeSerializeValue(msg.to_string())
260 }
261}
262
263impl From<Infallible> for crate::Error {
264 fn from(_: Infallible) -> Self {
265 unreachable!()
266 }
267}
268
269impl From<ParseNetTargetError> for crate::Error {
270 fn from(e: ParseNetTargetError) -> Self {
271 Self::Api(Error::from(e))
272 }
273}
274
275impl From<ParseFuncTargetError> for crate::Error {
276 fn from(e: ParseFuncTargetError) -> Self {
277 Self::Api(Error::from(e))
278 }
279}
280
281#[cfg(feature = "protocol-http")]
282impl From<reqwest::Error> for crate::Error {
283 fn from(e: reqwest::Error) -> Self {
284 Self::Api(Error::Http(e.to_string()))
285 }
286}
287
288#[cfg(all(feature = "protocol-ws", not(target_arch = "wasm32")))]
289#[cfg_attr(docsrs, doc(cfg(all(feature = "protocol-ws", not(target_arch = "wasm32")))))]
290impl From<tokio_tungstenite::tungstenite::Error> for crate::Error {
291 fn from(error: tokio_tungstenite::tungstenite::Error) -> Self {
292 Self::Api(Error::Ws(error.to_string()))
293 }
294}
295
296impl<T> From<channel::SendError<T>> for crate::Error {
297 fn from(error: channel::SendError<T>) -> Self {
298 Self::Api(Error::InternalError(error.to_string()))
299 }
300}
301
302impl From<channel::RecvError> for crate::Error {
303 fn from(error: channel::RecvError) -> Self {
304 Self::Api(Error::InternalError(error.to_string()))
305 }
306}
307
308impl From<url::ParseError> for crate::Error {
309 fn from(error: url::ParseError) -> Self {
310 Self::Api(Error::InternalError(error.to_string()))
311 }
312}
313
314#[cfg(all(feature = "protocol-ws", target_arch = "wasm32"))]
315#[cfg_attr(docsrs, doc(cfg(all(feature = "protocol-ws", target_arch = "wasm32"))))]
316impl From<ws_stream_wasm::WsErr> for crate::Error {
317 fn from(error: ws_stream_wasm::WsErr) -> Self {
318 Self::Api(Error::Ws(error.to_string()))
319 }
320}
321
322#[cfg(all(feature = "protocol-ws", target_arch = "wasm32"))]
323#[cfg_attr(docsrs, doc(cfg(all(feature = "protocol-ws", target_arch = "wasm32"))))]
324impl From<pharos::PharErr> for crate::Error {
325 fn from(error: pharos::PharErr) -> Self {
326 Self::Api(Error::Ws(error.to_string()))
327 }
328}
329
330impl Serialize for Error {
331 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
332 where
333 S: serde::Serializer,
334 {
335 serializer.serialize_str(self.to_string().as_str())
336 }
337}