1use std::convert::Infallible;
28use std::fmt;
29
30use serde::de::Deserializer;
31use serde::ser::Serializer;
32use serde::{Deserialize, Serialize};
33use serde_json::value::RawValue;
34use std::borrow::{Borrow, Cow as StdCow};
35use thiserror::Error;
36
37pub type ErrorObjectOwned = ErrorObject<'static>;
39
40#[derive(Debug, Deserialize, Serialize, Clone, thiserror::Error)]
42#[serde(deny_unknown_fields)]
43#[error("{self:?}")]
44pub struct ErrorObject<'a> {
45 code: ErrorCode,
47 message: StdCow<'a, str>,
49 #[serde(skip_serializing_if = "Option::is_none")]
51 data: Option<StdCow<'a, RawValue>>,
52}
53
54impl<'a> ErrorObject<'a> {
55 pub fn code(&self) -> i32 {
57 self.code.code()
58 }
59
60 pub fn message(&self) -> &str {
62 self.message.borrow()
63 }
64
65 pub fn data(&self) -> Option<&RawValue> {
67 self.data.as_ref().map(|d| d.borrow())
68 }
69
70 pub fn owned<S: Serialize>(code: i32, message: impl Into<String>, data: Option<S>) -> ErrorObject<'static> {
72 let data = data.and_then(|d| serde_json::value::to_raw_value(&d).ok());
73 ErrorObject { code: code.into(), message: message.into().into(), data: data.map(StdCow::Owned) }
74 }
75
76 pub fn borrowed(code: i32, message: &'a str, data: Option<&'a RawValue>) -> ErrorObject<'a> {
78 ErrorObject { code: code.into(), message: StdCow::Borrowed(message), data: data.map(StdCow::Borrowed) }
79 }
80
81 pub fn into_owned(self) -> ErrorObject<'static> {
83 ErrorObject {
84 code: self.code,
85 message: StdCow::Owned(self.message.into_owned()),
86 data: self.data.map(|d| StdCow::Owned(d.into_owned())),
87 }
88 }
89
90 pub fn borrow(&'a self) -> ErrorObject<'a> {
92 ErrorObject {
93 code: self.code,
94 message: StdCow::Borrowed(self.message.borrow()),
95 data: self.data.as_ref().map(|d| StdCow::Borrowed(d.borrow())),
96 }
97 }
98}
99
100impl PartialEq for ErrorObject<'_> {
101 fn eq(&self, other: &Self) -> bool {
102 let this_raw = self.data.as_ref().map(|r| r.get());
103 let other_raw = other.data.as_ref().map(|r| r.get());
104 self.code == other.code && self.message == other.message && this_raw == other_raw
105 }
106}
107
108impl From<ErrorCode> for ErrorObject<'_> {
109 fn from(code: ErrorCode) -> Self {
110 Self { code, message: code.message().into(), data: None }
111 }
112}
113
114impl From<Infallible> for ErrorObject<'_> {
115 fn from(e: Infallible) -> Self {
116 match e {}
117 }
118}
119
120pub const PARSE_ERROR_CODE: i32 = -32700;
122pub const INVALID_REQUEST_CODE: i32 = -32600;
124pub const METHOD_NOT_FOUND_CODE: i32 = -32601;
126pub const INVALID_PARAMS_CODE: i32 = -32602;
128pub const INTERNAL_ERROR_CODE: i32 = -32603;
130pub const CALL_EXECUTION_FAILED_CODE: i32 = -32000;
132pub const UNKNOWN_ERROR_CODE: i32 = -32001;
134pub const BATCHES_NOT_SUPPORTED_CODE: i32 = -32005;
136pub const TOO_MANY_SUBSCRIPTIONS_CODE: i32 = -32006;
138pub const OVERSIZED_REQUEST_CODE: i32 = -32007;
140pub const OVERSIZED_RESPONSE_CODE: i32 = -32008;
142pub const SERVER_IS_BUSY_CODE: i32 = -32009;
144pub const TOO_BIG_BATCH_REQUEST_CODE: i32 = -32010;
146pub const TOO_BIG_BATCH_RESPONSE_CODE: i32 = -32011;
148
149pub const PARSE_ERROR_MSG: &str = "Parse error";
151pub const OVERSIZED_REQUEST_MSG: &str = "Request is too big";
153pub const OVERSIZED_RESPONSE_MSG: &str = "Response is too big";
155pub const INTERNAL_ERROR_MSG: &str = "Internal error";
157pub const INVALID_PARAMS_MSG: &str = "Invalid params";
159pub const INVALID_REQUEST_MSG: &str = "Invalid request";
161pub const METHOD_NOT_FOUND_MSG: &str = "Method not found";
163pub const SERVER_IS_BUSY_MSG: &str = "Server is busy, try again later";
165pub const SERVER_ERROR_MSG: &str = "Server error";
167pub const BATCHES_NOT_SUPPORTED_MSG: &str = "Batched requests are not supported by this server";
169pub const TOO_MANY_SUBSCRIPTIONS_MSG: &str = "Too many subscriptions on the connection";
171pub const TOO_BIG_BATCH_REQUEST_MSG: &str = "The batch request was too large";
173pub const TOO_BIG_BATCH_RESPONSE_MSG: &str = "The batch response was too large";
175
176#[derive(Error, Debug, PartialEq, Eq, Copy, Clone)]
178pub enum ErrorCode {
179 ParseError,
182 OversizedRequest,
184 InvalidRequest,
186 MethodNotFound,
188 ServerIsBusy,
190 InvalidParams,
192 InternalError,
194 ServerError(i32),
196}
197
198impl ErrorCode {
199 pub const fn code(&self) -> i32 {
201 use ErrorCode::*;
202 match *self {
203 ParseError => PARSE_ERROR_CODE,
204 OversizedRequest => OVERSIZED_REQUEST_CODE,
205 InvalidRequest => INVALID_REQUEST_CODE,
206 MethodNotFound => METHOD_NOT_FOUND_CODE,
207 ServerIsBusy => SERVER_IS_BUSY_CODE,
208 InvalidParams => INVALID_PARAMS_CODE,
209 InternalError => INTERNAL_ERROR_CODE,
210 ServerError(code) => code,
211 }
212 }
213
214 pub const fn message(&self) -> &'static str {
216 use ErrorCode::*;
217 match self {
218 ParseError => PARSE_ERROR_MSG,
219 OversizedRequest => OVERSIZED_REQUEST_MSG,
220 InvalidRequest => INVALID_REQUEST_MSG,
221 MethodNotFound => METHOD_NOT_FOUND_MSG,
222 ServerIsBusy => SERVER_IS_BUSY_MSG,
223 InvalidParams => INVALID_PARAMS_MSG,
224 InternalError => INTERNAL_ERROR_MSG,
225 ServerError(_) => SERVER_ERROR_MSG,
226 }
227 }
228}
229
230impl fmt::Display for ErrorCode {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 write!(f, "{}: {}", self.code(), self.message())
233 }
234}
235
236impl From<i32> for ErrorCode {
237 fn from(code: i32) -> Self {
238 use ErrorCode::*;
239 match code {
240 PARSE_ERROR_CODE => ParseError,
241 OVERSIZED_REQUEST_CODE => OversizedRequest,
242 INVALID_REQUEST_CODE => InvalidRequest,
243 METHOD_NOT_FOUND_CODE => MethodNotFound,
244 INVALID_PARAMS_CODE => InvalidParams,
245 INTERNAL_ERROR_CODE => InternalError,
246 code => ServerError(code),
247 }
248 }
249}
250
251impl<'a> serde::Deserialize<'a> for ErrorCode {
252 fn deserialize<D>(deserializer: D) -> Result<ErrorCode, D::Error>
253 where
254 D: Deserializer<'a>,
255 {
256 let code: i32 = Deserialize::deserialize(deserializer)?;
257 Ok(ErrorCode::from(code))
258 }
259}
260
261impl serde::Serialize for ErrorCode {
262 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
263 where
264 S: Serializer,
265 {
266 serializer.serialize_i32(self.code())
267 }
268}
269
270pub fn reject_too_many_subscriptions(limit: u32) -> ErrorObjectOwned {
272 ErrorObjectOwned::owned(
273 TOO_MANY_SUBSCRIPTIONS_CODE,
274 TOO_MANY_SUBSCRIPTIONS_MSG,
275 Some(format!("Exceeded max limit of {limit}")),
276 )
277}
278
279pub fn reject_too_big_request(limit: u32) -> ErrorObjectOwned {
281 ErrorObjectOwned::owned(
282 OVERSIZED_REQUEST_CODE,
283 OVERSIZED_REQUEST_MSG,
284 Some(format!("Exceeded max limit of {limit}")),
285 )
286}
287
288pub fn reject_too_big_batch_request(limit: usize) -> ErrorObjectOwned {
290 ErrorObjectOwned::owned(
291 TOO_BIG_BATCH_REQUEST_CODE,
292 TOO_BIG_BATCH_REQUEST_MSG,
293 Some(format!("Exceeded max limit of {limit}")),
294 )
295}
296
297pub fn reject_too_big_batch_response(limit: usize) -> ErrorObjectOwned {
299 ErrorObjectOwned::owned(
300 TOO_BIG_BATCH_RESPONSE_CODE,
301 TOO_BIG_BATCH_RESPONSE_MSG,
302 Some(format!("Exceeded max limit of {limit}")),
303 )
304}
305
306#[cfg(test)]
307mod tests {
308 use super::{ErrorCode, ErrorObject};
309
310 #[test]
311 fn deserialize_works() {
312 let ser = r#"{"code":-32700,"message":"Parse error"}"#;
313 let exp: ErrorObject = ErrorCode::ParseError.into();
314 let err: ErrorObject = serde_json::from_str(ser).unwrap();
315 assert_eq!(exp, err);
316 }
317
318 #[test]
319 fn deserialize_with_optional_data() {
320 let ser = r#"{"code":-32700,"message":"Parse error", "data":"vegan"}"#;
321 let data = serde_json::value::to_raw_value(&"vegan").unwrap();
322 let exp = ErrorObject::owned(ErrorCode::ParseError.code(), "Parse error", Some(data));
323 let err: ErrorObject = serde_json::from_str(ser).unwrap();
324 assert_eq!(exp, err);
325 }
326
327 #[test]
328 fn deserialized_error_with_quoted_str() {
329 let raw = r#"{
330 "code": 1002,
331 "message": "desc: \"Could not decode `ChargeAssetTxPayment::asset_id`\" } })",
332 "data": "\\\"validate_transaction\\\""
333 }"#;
334 let err: ErrorObject = serde_json::from_str(raw).unwrap();
335
336 let data = serde_json::value::to_raw_value(&"\\\"validate_transaction\\\"").unwrap();
337 let exp = ErrorObject::borrowed(
338 1002,
339 "desc: \"Could not decode `ChargeAssetTxPayment::asset_id`\" } })",
340 Some(&*data),
341 );
342
343 assert_eq!(err, exp);
344 }
345
346 #[test]
347 fn serialize_works() {
348 let exp = r#"{"code":-32603,"message":"Internal error"}"#;
349 let err: ErrorObject = ErrorCode::InternalError.into();
350 let ser = serde_json::to_string(&err).unwrap();
351 assert_eq!(exp, ser);
352 }
353
354 #[test]
355 fn serialize_optional_data_works() {
356 let exp = r#"{"code":-32699,"message":"food","data":"not vegan"}"#;
357 let data = serde_json::value::to_raw_value(&"not vegan").unwrap();
358 let ser = serde_json::to_string(&ErrorObject::owned(-32699, "food", Some(data))).unwrap();
359 assert_eq!(exp, ser);
360 }
361}