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}