lsp_primitives/json_rpc/
mod.rs

1pub mod error;
2
3use base64::Engine as _;
4use serde::de::DeserializeOwned;
5use serde::{Deserialize, Serialize};
6use std::str::FromStr;
7
8pub use crate::json_rpc::error::{DefaultError, ErrorData};
9use crate::lsps0::parameter_validation;
10pub use crate::no_params::NoParams;
11
12#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash)]
13#[serde(untagged)]
14pub enum JsonRpcId {
15    String(String),
16    Number(i64),
17    None,
18}
19
20impl PartialEq<serde_json::Value> for JsonRpcId {
21    fn eq(&self, value: &serde_json::Value) -> bool {
22        match self {
23            Self::String(s) => value == s,
24            Self::Number(n) => value == n,
25            Self::None => value == &serde_json::Value::Null,
26        }
27    }
28}
29
30impl PartialEq<&str> for JsonRpcId {
31    fn eq(&self, value: &&str) -> bool {
32        match self {
33            Self::String(s) => s == value,
34            Self::Number(_) => false,
35            Self::None => false,
36        }
37    }
38}
39
40impl From<&str> for JsonRpcId {
41    fn from(value: &str) -> Self {
42        Self::String(value.to_string())
43    }
44}
45
46impl FromStr for JsonRpcId {
47    type Err = anyhow::Error;
48
49    fn from_str(value: &str) -> Result<Self, Self::Err> {
50        Ok(Self::String(value.to_string()))
51    }
52}
53
54/// Generate a random json_rpc_id string that follows the requirements of LSPS0
55///
56/// - Should be a String
57/// - Should be at generated using at least 80 bits of randomness
58pub fn generate_random_rpc_id() -> JsonRpcId {
59    // The specification requires an id using least 80 random bits of randomness
60    let seed: [u8; 10] = rand::random();
61    let str_id = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(seed);
62    JsonRpcId::String(str_id)
63}
64
65/// Defines a json-rpc method and describes the schema
66/// of the input I, output O and error-type E.
67///
68/// The error-type can be serialized and deserialized
69#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
70pub struct JsonRpcMethod<'a, I, O, E> {
71    pub method: &'a str,
72    #[serde(skip_serializing)]
73    request: std::marker::PhantomData<I>,
74    #[serde(skip_serializing)]
75    return_type: std::marker::PhantomData<O>,
76    #[serde(skip_serializing)]
77    error_type: std::marker::PhantomData<E>,
78}
79
80impl<'a, I, O, E> JsonRpcMethod<'a, I, O, E> {
81    pub const fn new(method: &'a str) -> Self {
82        Self {
83            method,
84            request: std::marker::PhantomData,
85            return_type: std::marker::PhantomData,
86            error_type: std::marker::PhantomData,
87        }
88    }
89
90    pub const fn name(&self) -> &'a str {
91        self.method
92    }
93
94    /// Creates a JsonRpcRequest with parameters for the given method
95    pub fn create_request(&self, params: I, json_rpc_id: JsonRpcId) -> JsonRpcRequest<I> {
96        JsonRpcRequest::<I> {
97            jsonrpc: String::from("2.0"),
98            id: json_rpc_id,
99            method: self.method.into(),
100            params,
101        }
102    }
103
104    pub fn create_ok_response(
105        &self,
106        request: JsonRpcRequest<I>,
107        result: O,
108    ) -> JsonRpcResponse<O, E> {
109        JsonRpcResponse::Ok(JsonRpcResponseSuccess {
110            jsonrpc: String::from("2.0"),
111            id: request.id.clone(),
112            result,
113        })
114    }
115
116    pub fn into_typed_request(
117        &self,
118        request: JsonRpcRequest<serde_json::Value>,
119    ) -> Result<JsonRpcRequest<I>, ErrorData>
120    where
121        I: DeserializeOwned + parameter_validation::ExpectedFields,
122    {
123        let params = request.params;
124        let params: I = parameter_validation::from_value(params)?;
125
126        let request = JsonRpcRequest::<I> {
127            id: request.id,
128            jsonrpc: request.jsonrpc,
129            method: request.method,
130            params: params,
131        };
132
133        Ok(request)
134    }
135}
136
137impl<O, E> JsonRpcMethod<'_, NoParams, O, E> {
138    pub fn create_request_no_params(&self, json_rpc_id: JsonRpcId) -> JsonRpcRequest<NoParams> {
139        self.create_request(NoParams, json_rpc_id)
140    }
141}
142
143impl<'a, I, O, E> std::convert::From<&'a JsonRpcMethod<'a, I, O, E>> for String {
144    fn from(value: &JsonRpcMethod<I, O, E>) -> Self {
145        value.method.into()
146    }
147}
148
149impl<'de, I, O, E> JsonRpcMethod<'de, I, O, E>
150where
151    O: Deserialize<'de>,
152    E: Deserialize<'de>,
153{
154    pub fn parse_json_response_str(
155        &self,
156        json_str: &'de str,
157    ) -> Result<JsonRpcResponse<O, E>, serde_json::Error> {
158        serde_json::from_str(json_str)
159    }
160}
161
162impl<I, O, E> JsonRpcMethod<'_, I, O, E>
163where
164    O: DeserializeOwned,
165    E: DeserializeOwned,
166{
167    pub fn parse_json_response_value(
168        &self,
169        json_value: serde_json::Value,
170    ) -> Result<JsonRpcResponse<O, E>, serde_json::Error> {
171        serde_json::from_value(json_value)
172    }
173}
174
175#[derive(Serialize, Deserialize, Debug, Clone)]
176pub struct JsonRpcRequest<I> {
177    pub jsonrpc: String,
178    pub id: JsonRpcId,
179    pub method: String,
180    pub params: I,
181}
182
183impl<I> JsonRpcRequest<I> {
184    pub fn new<O, E>(method: JsonRpcMethod<I, O, E>, params: I) -> Self {
185        Self {
186            jsonrpc: String::from("2.0"),
187            id: generate_random_rpc_id(),
188            method: method.method.into(),
189            params,
190        }
191    }
192}
193
194impl JsonRpcRequest<serde_json::Value> {
195    pub fn deserialize<I>(self) -> Result<JsonRpcRequest<I>, serde_json::Error>
196    where
197        I: DeserializeOwned,
198    {
199        let request = JsonRpcRequest {
200            jsonrpc: self.jsonrpc,
201            id: self.id,
202            method: self.method,
203            params: serde_json::from_value(self.params)?,
204        };
205        Ok(request)
206    }
207}
208
209impl JsonRpcRequest<NoParams> {
210    pub fn new_no_params<O, E>(method: JsonRpcMethod<NoParams, O, E>) -> Self {
211        Self {
212            jsonrpc: String::from("2.0"),
213            id: generate_random_rpc_id(),
214            method: method.method.into(),
215            params: NoParams,
216        }
217    }
218}
219
220#[derive(Debug, Serialize, Deserialize)]
221pub struct JsonRpcResponseSuccess<O> {
222    pub id: JsonRpcId,
223    pub result: O,
224    pub jsonrpc: String,
225}
226
227#[derive(Debug, Serialize, Deserialize)]
228pub struct JsonRpcResponseFailure<E> {
229    pub id: JsonRpcId,
230    pub error: ErrorData<E>,
231    pub jsonrpc: String,
232}
233
234#[derive(Debug, Serialize, Deserialize)]
235#[serde(untagged)]
236pub enum JsonRpcResponse<O, E> {
237    Error(JsonRpcResponseFailure<E>),
238    Ok(JsonRpcResponseSuccess<O>),
239}
240
241impl<E, O> JsonRpcResponse<E, O> {
242    pub fn jsonrpc(&self) -> &str {
243        match self {
244            JsonRpcResponse::Ok(j) => &j.jsonrpc,
245            JsonRpcResponse::Error(j) => &j.jsonrpc,
246        }
247    }
248
249    pub fn id(&self) -> &JsonRpcId {
250        match self {
251            JsonRpcResponse::Ok(j) => &j.id,
252            JsonRpcResponse::Error(j) => &j.id,
253        }
254    }
255}
256
257impl<O, E> JsonRpcResponse<O, E> {
258    pub fn success(id: JsonRpcId, output: O) -> Self {
259        let success = JsonRpcResponseSuccess {
260            id,
261            result: output,
262            jsonrpc: String::from("2.0"),
263        };
264
265        JsonRpcResponse::Ok(success)
266    }
267
268    pub fn error(id: JsonRpcId, error: ErrorData<E>) -> Self {
269        let error = JsonRpcResponseFailure {
270            id,
271            error,
272            jsonrpc: String::from("2.0"),
273        };
274
275        JsonRpcResponse::Error(error)
276    }
277}
278
279#[cfg(test)]
280mod test {
281
282    use super::*;
283
284    #[test]
285    fn serialize_json_rpc_request() {
286        let rpc_request = JsonRpcRequest {
287            id: "abcefg".into(),
288            jsonrpc: "2.0".into(),
289            params: NoParams,
290            method: "test.method".into(),
291        };
292
293        let json_str = serde_json::to_string(&rpc_request).unwrap();
294
295        let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
296        assert_eq!(value.get("jsonrpc").unwrap(), "2.0");
297        assert_eq!(&rpc_request.id, value.get("id").unwrap());
298        assert_eq!(value.get("method").unwrap(), "test.method");
299        assert!(value.get("params").unwrap().as_object().unwrap().is_empty())
300    }
301
302    #[test]
303    fn serialize_json_rpc_response_success() {
304        let rpc_response_ok: JsonRpcResponseSuccess<String> = JsonRpcResponseSuccess {
305            id: JsonRpcId::String("abc".to_string()),
306            result: String::from("result_data"),
307            jsonrpc: String::from("2.0"),
308        };
309
310        let rpc_response: JsonRpcResponse<String, ()> = JsonRpcResponse::Ok(rpc_response_ok);
311
312        let json_str: String = serde_json::to_string(&rpc_response).unwrap();
313
314        let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
315        assert_eq!(value.get("jsonrpc").unwrap(), "2.0");
316        assert_eq!(value.get("id").unwrap(), "abc");
317        assert_eq!(value.get("result").unwrap(), "result_data")
318    }
319
320    #[test]
321    fn serialize_json_rpc_response_error() {
322        let rpc_response: JsonRpcResponse<String, ()> =
323            JsonRpcResponse::Error(JsonRpcResponseFailure {
324                jsonrpc: String::from("2.0"),
325                id: JsonRpcId::String("abc".to_string()),
326                error: ErrorData {
327                    code: -32700,
328                    message: String::from("Failed to parse data"),
329                    data: None,
330                },
331            });
332
333        let json_str: String = serde_json::to_string(&rpc_response).unwrap();
334
335        let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
336        assert_eq!(value.get("jsonrpc").unwrap(), "2.0");
337        assert_eq!(value.get("id").unwrap(), "abc");
338        assert_eq!(value.get("error").unwrap().get("code").unwrap(), -32700);
339        assert_eq!(
340            value.get("error").unwrap().get("message").unwrap(),
341            "Failed to parse data"
342        );
343    }
344
345    #[test]
346    fn create_rpc_request_from_call() {
347        let rpc_method = JsonRpcMethod::<NoParams, (), DefaultError>::new("test.method");
348        let json_rpc_id = generate_random_rpc_id();
349        let rpc_request = rpc_method.create_request_no_params(json_rpc_id);
350
351        assert_eq!(rpc_request.method, "test.method");
352        assert_eq!(rpc_request.jsonrpc, "2.0");
353        assert_eq!(rpc_request.params, NoParams);
354    }
355
356    #[test]
357    fn parse_rpc_response_success_from_call() {
358        let rpc_method = JsonRpcMethod::<NoParams, String, DefaultError>::new("test.return_string");
359
360        let json_value = serde_json::json!({
361            "jsonrpc" : "2.0",
362            "result" : "result_data",
363            "id" : "request_id"
364        });
365
366        let json_str = serde_json::to_string(&json_value).unwrap();
367
368        let result = rpc_method.parse_json_response_str(&json_str).unwrap();
369
370        match result {
371            JsonRpcResponse::Error(_) => panic!("Deserialized a good response but got panic"),
372            JsonRpcResponse::Ok(ok) => {
373                assert_eq!(ok.jsonrpc, "2.0");
374                assert_eq!(ok.id, "request_id");
375                assert_eq!(ok.result, "result_data")
376            }
377        }
378    }
379
380    #[test]
381    fn parse_rpc_response_failure_from_call() {
382        let rpc_method = JsonRpcMethod::<NoParams, String, DefaultError>::new("test.return_string");
383
384        let json_value = serde_json::json!({
385            "jsonrpc" : "2.0",
386            "error" : { "code" : -32700, "message" : "Failed to parse response"},
387            "id" : "request_id"
388        });
389
390        let json_str = serde_json::to_string(&json_value).unwrap();
391
392        let result = rpc_method.parse_json_response_str(&json_str).unwrap();
393
394        match result {
395            JsonRpcResponse::Error(err) => {
396                assert_eq!(err.jsonrpc, "2.0");
397
398                assert_eq!(err.error.code, -32700);
399
400                assert_eq!(err.error.message, "Failed to parse response");
401                assert_eq!(err.id, JsonRpcId::String("request_id".to_string()));
402            }
403            JsonRpcResponse::Ok(_ok) => {
404                panic!("Failure deserialized as Ok")
405            }
406        }
407    }
408
409    #[test]
410    fn serialize_json_rpc_id() {
411        let id_str = JsonRpcId::String("id_string".to_string());
412        let id_i64 = JsonRpcId::Number(-12);
413        let id_null = JsonRpcId::None;
414
415        assert_eq!(serde_json::json!(id_str), serde_json::json!("id_string"));
416
417        assert_eq!(serde_json::json!(id_i64), serde_json::json!(-12));
418
419        assert_eq!(serde_json::json!(id_null), serde_json::json!(null))
420    }
421
422    #[test]
423    fn deserialize_default_error() {
424        let data = serde_json::json!({
425            "jsonrpc" : "2.0",
426            "id" : "abcdef",
427            "error" : {
428                "code" : 10,
429                "message" : "Something happened",
430                "data" : { "object" : "I am an unrecegonized object and should be either ignored or parsed" }
431            }
432        });
433
434        let _: JsonRpcResponseFailure<DefaultError> = serde_json::from_value(data).unwrap();
435    }
436}