1use crate::{ErrorVariant, JsonValue};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[derive(Serialize, Deserialize, Debug, Clone)]
6pub struct JrpcRequest {
7 jsonrpc: String,
8 method: String,
9
10 #[serde(skip_serializing_if = "Option::is_none")]
11 params: Option<JsonValue>,
12
13 #[serde(skip_serializing_if = "Option::is_none")]
14 id: Option<JsonValue>,
15}
16
17impl JrpcRequest {
18 pub fn new<T: ToString>(
19 method: T,
20 params: Option<JsonValue>,
21 id: Option<JsonValue>,
22 ) -> Result<JrpcRequest, ErrorVariant> {
23 let method = method.to_string();
24 let jrpc_request = JrpcRequest {
25 jsonrpc: "2.0".to_string(),
26 method,
27 params,
28 id,
29 };
30
31 jrpc_request.validate()
32 }
33
34 pub fn prepare_to_send_notification<T: ToString>(
35 method: T,
36 params: Option<JsonValue>,
37 ) -> Result<JrpcRequest, ErrorVariant> {
38 let method = method.to_string();
39 let id = None;
40 let jrpc_request = JrpcRequest {
41 jsonrpc: "2.0".to_string(),
42 method,
43 params,
44 id,
45 };
46
47 jrpc_request.validate()
48 }
49
50 pub fn prepare_to_send_request<T: ToString>(
51 method: T,
52 params: Option<JsonValue>,
53 ) -> Result<JrpcRequest, ErrorVariant> {
54 let method = method.to_string();
55 let id = Some(JsonValue::String(Uuid::new_v4().to_string()));
56 let jrpc_request = JrpcRequest {
57 jsonrpc: "2.0".to_string(),
58 method,
59 params,
60 id,
61 };
62
63 jrpc_request.validate()
64 }
65
66 pub fn parse<F: ToString>(message: F) -> Result<Self, ErrorVariant> {
67 let message = message.to_string();
68 serde_json::from_str::<Self>(message.as_str())
69 .map_err(|e| ErrorVariant::JsonParseError(e))
70 .and_then(|parsed| parsed.validate())
71 }
72
73 pub fn generate_response(
74 &self,
75 response: JrpcResponseParam,
76 ) -> Result<JrpcResponse, ErrorVariant> {
77 JrpcResponse::from_jrpc_request(self, response)
78 }
79
80 fn validate(self) -> Result<Self, ErrorVariant> {
81 if self.get_jsonrpc() != "2.0" {
82 return Err(ErrorVariant::InvalidJsonRpcVersion);
83 }
84
85 match self.get_id() {
87 Some(JsonValue::String(_)) => (),
88 Some(JsonValue::Number(_)) => (),
89 Some(JsonValue::Null) => (),
90 None => (),
91 _ => return Err(ErrorVariant::InvalidJsonRpcId),
92 }
93
94 Ok(self)
95 }
96
97 pub fn is_notification(&self) -> bool {
98 self.id.is_none()
99 }
100
101 pub fn get_jsonrpc(&self) -> &String {
102 &self.jsonrpc
103 }
104
105 pub fn get_method(&self) -> &String {
106 &self.method
107 }
108
109 pub fn get_params(&self) -> &Option<JsonValue> {
110 &self.params
111 }
112
113 pub fn get_id(&self) -> &Option<JsonValue> {
114 &self.id
115 }
116}
117
118#[derive(Debug, Clone)]
119pub enum JrpcResponseParam {
120 JrpcResult(JsonValue),
121 JrpcError(JrpcError),
122}
123
124impl JrpcResponseParam {
125 pub fn generate_result(response: JsonValue) -> Result<Self, ErrorVariant> {
126 Ok(JrpcResponseParam::JrpcResult(response))
127 }
128
129 pub fn generate_error(response: JrpcError) -> Result<Self, ErrorVariant> {
130 Ok(JrpcResponseParam::JrpcError(response))
131 }
132}
133
134#[derive(Serialize, Deserialize, Debug, Clone)]
135pub struct JrpcResponse {
136 jsonrpc: String,
137
138 #[serde(skip_serializing_if = "Option::is_none")]
139 result: Option<JsonValue>,
140
141 #[serde(skip_serializing_if = "Option::is_none")]
142 error: Option<JrpcError>,
143
144 id: JsonValue,
145}
146
147impl JrpcResponse {
148 pub fn new(
149 result: Option<JsonValue>,
150 error: Option<JrpcError>,
151 id: JsonValue,
152 ) -> Result<Self, ErrorVariant> {
153 let jrpc_response = JrpcResponse {
154 jsonrpc: "2.0".to_string(),
155 result,
156 error,
157 id,
158 };
159
160 jrpc_response.validate()
161 }
162
163 pub fn from_jrpc_request(
164 request: &JrpcRequest,
165 response: JrpcResponseParam,
166 ) -> Result<Self, ErrorVariant> {
167 let mut result = None;
168 let mut error = None;
169 let id = match request.get_id() {
170 Some(i) => i.clone(),
171 None => JsonValue::Null,
172 };
173
174 match response {
175 JrpcResponseParam::JrpcResult(r) => result = Some(r),
176 JrpcResponseParam::JrpcError(e) => error = Some(e),
177 }
178
179 JrpcResponse::new(result, error, id)
180 }
181
182 pub fn parse<F: ToString>(message: F) -> Result<Self, ErrorVariant> {
183 let message = message.to_string();
184 serde_json::from_str::<Self>(message.as_str())
185 .map_err(|e| ErrorVariant::JsonParseError(e))
186 .and_then(|parsed| parsed.validate())
187 }
188
189 pub fn validate(self) -> Result<Self, ErrorVariant> {
190 if self.get_jsonrpc() != "2.0" {
191 return Err(ErrorVariant::InvalidJsonRpcVersion);
192 }
193
194 if self.get_result().is_some() && self.get_error().is_some() {
195 return Err(ErrorVariant::ResponseCannotContainResultAndError);
196 }
197
198 if self.get_result().is_none() && self.get_error().is_none() {
199 return Err(ErrorVariant::ResponseCannotContainResultAndError);
200 }
201
202 match self.get_id() {
204 JsonValue::String(_) => (),
205 JsonValue::Number(_) => (),
206 JsonValue::Null => (),
207 _ => return Err(ErrorVariant::InvalidJsonRpcId),
208 }
209
210 Ok(self)
211 }
212
213 pub fn get_jsonrpc(&self) -> &String {
214 &self.jsonrpc
215 }
216
217 pub fn get_result(&self) -> &Option<JsonValue> {
218 &self.result
219 }
220
221 pub fn get_error(&self) -> &Option<JrpcError> {
222 &self.error
223 }
224
225 pub fn get_id(&self) -> &JsonValue {
226 &self.id
227 }
228}
229
230#[derive(Debug, Clone)]
231pub enum JrpcErrorEnum {
232 ParseError = -32700,
233 InvalidRequest = -32600,
234 MethodNotFound = -32601,
235 InvalidParams = -32602,
236 InternalError = -32603,
237 ServerError = -32000,
238 Other = 0,
239}
240
241impl From<i32> for JrpcErrorEnum {
242 fn from(code: i32) -> Self {
243 if code == -32700 {
244 JrpcErrorEnum::ParseError
245 } else if code == -32600 {
246 JrpcErrorEnum::InvalidRequest
247 } else if code == -32601 {
248 JrpcErrorEnum::MethodNotFound
249 } else if code == -32602 {
250 JrpcErrorEnum::InvalidParams
251 } else if code == -32603 {
252 JrpcErrorEnum::InternalError
253 } else if code >= -32099 && code <= -32000 {
254 JrpcErrorEnum::ServerError
255 } else {
256 JrpcErrorEnum::Other
257 }
258 }
259}
260
261impl From<JrpcErrorEnum> for i32 {
262 fn from(jrpc_error: JrpcErrorEnum) -> i32 {
263 match jrpc_error {
264 JrpcErrorEnum::ParseError => -32700,
265 JrpcErrorEnum::InvalidRequest => -32600,
266 JrpcErrorEnum::MethodNotFound => -32601,
267 JrpcErrorEnum::InvalidParams => -32602,
268 JrpcErrorEnum::InternalError => -32603,
269 JrpcErrorEnum::ServerError => -32000,
270 JrpcErrorEnum::Other => 0,
271 }
272 }
273}
274
275#[derive(Serialize, Deserialize, Debug, Clone)]
276pub struct JrpcError {
277 code: i32,
278 message: String,
279 data: Option<JsonValue>,
280}
281
282impl JrpcError {
283 pub fn new<T: ToString>(code: i32, message: T, data: Option<JsonValue>) -> Self {
284 let message = message.to_string();
285 JrpcError {
286 code,
287 message,
288 data,
289 }
290 }
291
292 pub fn parse<F: ToString>(message: F) -> Result<Self, ErrorVariant> {
293 let message = message.to_string();
294 let parsed: JrpcError =
295 serde_json::from_str(message.as_str()).map_err(|e| ErrorVariant::JsonParseError(e))?;
296
297 Ok(parsed)
298 }
299
300 pub fn get_code(&self) -> &i32 {
301 &self.code
302 }
303
304 pub fn get_message(&self) -> &String {
305 &self.message
306 }
307
308 pub fn get_data(&self) -> &Option<JsonValue> {
309 &self.data
310 }
311}
312
313impl From<JrpcErrorEnum> for JrpcError {
314 fn from(error_enum: JrpcErrorEnum) -> Self {
315 let message = match error_enum {
316 JrpcErrorEnum::ParseError => "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.",
317 JrpcErrorEnum::InvalidRequest => "The JSON sent is not a valid Request object.",
318 JrpcErrorEnum::MethodNotFound => "The method does not exist / is not available.",
319 JrpcErrorEnum::InvalidParams => "Invalid method parameter(s).",
320 JrpcErrorEnum::InternalError => "Internal JSON-RPC error.",
321 JrpcErrorEnum::ServerError => "Reserved for implementation-defined server-errors.",
322 JrpcErrorEnum::Other => "JsonRpc Error",
323 };
324 let code = i32::from(error_enum);
325 let message = message.to_string();
326 let data = None;
327 JrpcError::new(code, message, data)
328 }
329}
330
331impl From<i32> for JrpcError {
332 fn from(error_code: i32) -> Self {
333 let jrpc_error_enum = JrpcErrorEnum::from(error_code);
334 JrpcError::from(jrpc_error_enum)
335 }
336}
337
338impl From<ErrorVariant> for JrpcError {
339 fn from(error_variant: ErrorVariant) -> Self {
340 match error_variant {
341 ErrorVariant::MethodSignatureNotFound(_) => JrpcError::from(-32601),
342 ErrorVariant::JsonParseError(_) => JrpcError::from(-32700),
343 ErrorVariant::InvalidJsonRpcVersion => JrpcError::from(-32600),
344 ErrorVariant::InvalidJsonRpcId => JrpcError::from(-32600),
345 ErrorVariant::ResponseCannotContainResultAndError => JrpcError::from(-32600),
346 ErrorVariant::ResponseMustContainResultOrError => JrpcError::from(-32600),
347 _ => JrpcError::from(-32603),
348 }
349 }
350}