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