json_rpc_types/
error.rs

1#[rustfmt::skip]
2
3use serde::{Serialize, Deserialize};
4use serde::de::{Deserializer};
5use serde::ser::{Serializer};
6
7use core::fmt;
8use core::mem;
9
10pub(crate) type StrBuf = str_buf::StrBuf<31>;
11
12///JSON-RPC error code
13#[derive(Debug, PartialEq, Clone, Copy)]
14pub enum ErrorCode {
15    ///Invalid JSON was received by the server.
16    ///An error occurred on the server while parsing the JSON text.
17    ParseError,
18    ///The JSON sent is not a valid Request object.
19    InvalidRequest,
20    ///The method does not exist / is not available.
21    MethodNotFound,
22    ///Invalid method parameters.
23    InvalidParams,
24    ///Internal JSON-RPC error.
25    InternalError,
26    ///Reserved for implementation-defined server-errors.
27    ServerError(i64),
28}
29
30impl ErrorCode {
31    ///Creates new instance from code.
32    pub const fn from_code(code: i64) -> Self {
33        match code {
34            -32700 => ErrorCode::ParseError,
35            -32600 => ErrorCode::InvalidRequest,
36            -32601 => ErrorCode::MethodNotFound,
37            -32602 => ErrorCode::InvalidParams,
38            -32603 => ErrorCode::InternalError,
39            code => ErrorCode::ServerError(code),
40        }
41    }
42
43    ///Returns integer code value
44    pub const fn code(&self) -> i64 {
45        match self {
46            ErrorCode::ParseError => -32700,
47            ErrorCode::InvalidRequest => -32600,
48            ErrorCode::MethodNotFound => -32601,
49            ErrorCode::InvalidParams => -32602,
50            ErrorCode::InternalError => -32603,
51            ErrorCode::ServerError(code) => *code,
52        }
53    }
54
55    ///Returns textual representation of the code.
56    pub const fn message(&self) -> &'static str {
57        match self {
58            ErrorCode::ParseError => "Parse error",
59            ErrorCode::InvalidRequest => "Invalid Request",
60            ErrorCode::MethodNotFound => "Method not found",
61            ErrorCode::InvalidParams => "Invalid params",
62            ErrorCode::InternalError => "Internal error",
63            ErrorCode::ServerError(_) => "Server error",
64        }
65    }
66}
67
68impl<'a> Deserialize<'a> for ErrorCode {
69    #[inline]
70    fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<ErrorCode, D::Error> {
71        let code: i64 = Deserialize::deserialize(deserializer)?;
72        Ok(ErrorCode::from_code(code))
73    }
74}
75
76impl Serialize for ErrorCode {
77    #[inline]
78    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
79        serializer.serialize_i64(self.code())
80    }
81}
82
83///Error object, defined by JSON-RPC
84#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
85#[serde(deny_unknown_fields)]
86pub struct Error<T, M=StrBuf> {
87    ///Code
88    pub code: ErrorCode,
89    ///Message
90    pub message: M,
91    ///Optional data
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub data: Option<T>,
94}
95
96impl<'a, T, EM: From<&'a str>> Error<T, EM> {
97    #[inline]
98    ///Constructs error by converting message from string.
99    pub fn with_text_message(code: ErrorCode, message: &'a str) -> Self {
100        Self {
101            code,
102            message: message.into(),
103            data: None,
104        }
105    }
106}
107
108impl<T> fmt::Display for Error<T> {
109    #[inline(always)]
110    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
111        fmt.write_str(self.code.message())
112    }
113}
114
115impl<const N: usize, T> Error<T, str_buf::StrBuf<N>> {
116    ///Constructs error with custom message
117    pub const fn with_custom_msg_truncated(code: ErrorCode, message: &str) -> Self {
118        let mut storage = [mem::MaybeUninit::uninit(); N];
119        let msg = message.as_bytes();
120        let mut idx = 0;
121
122        let idx_limit = if storage.len() > msg.len() {
123            msg.len()
124        } else {
125            storage.len()
126        };
127
128        loop {
129            storage[idx] = mem::MaybeUninit::new(msg[idx]);
130            idx += 1;
131            if idx == idx_limit {
132                break;
133            }
134        }
135
136        let message = unsafe {
137            str_buf::StrBuf::from_storage(storage, idx as u8)
138        };
139
140        Self {
141            code,
142            message,
143            data: None,
144        }
145    }
146
147    ///Constructs error with custom message
148    pub const fn with_custom_msg(code: ErrorCode, message: &str) -> Self {
149        let mut storage = [mem::MaybeUninit::uninit(); N];
150        let msg = message.as_bytes();
151        let mut idx = 0;
152        loop {
153            storage[idx] = mem::MaybeUninit::new(msg[idx]);
154            idx += 1;
155            if idx == msg.len() {
156                break;
157            }
158        }
159
160        let message = unsafe {
161            str_buf::StrBuf::from_storage(storage, msg.len() as u8)
162        };
163
164        Self {
165            code,
166            message,
167            data: None,
168        }
169    }
170
171    #[inline]
172    ///Creates new error, deriving message from code.
173    pub const fn from_code(code: ErrorCode) -> Self {
174        Self::with_custom_msg(code, code.message())
175    }
176
177    #[inline(always)]
178    ///Adds optional payload to instance
179    pub fn set_data(self, data: T) -> Self {
180        Self {
181            code: self.code,
182            message: self.message,
183            data: Some(data)
184        }
185    }
186}