1use std::fmt;
2
3use serde::{de::DeserializeOwned, Deserialize, Serialize};
4use serde_json::{from_value, Map, Value};
5
6use crate::{error::Error, id::Id, v2::version::Version};
7
8#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
13#[serde(untagged)]
14pub enum Params {
15 Array(Vec<Value>),
17 Map(Map<String, Value>),
19}
20
21impl Default for Params {
22 fn default() -> Self {
23 Params::Array(vec![])
24 }
25}
26
27impl fmt::Display for Params {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 let json = serde_json::to_string(self).expect("`Params` is serializable");
30 write!(f, "{}", json)
31 }
32}
33
34impl Params {
35 pub fn parse<D>(self) -> Result<D, Error>
37 where
38 D: DeserializeOwned,
39 {
40 let value = self.into();
41 from_value(value).map_err(Error::invalid_params)
42 }
43
44 pub fn is_empty_array(&self) -> bool {
46 matches!(self, Params::Array(array) if array.is_empty())
47 }
48
49 pub fn is_array(&self) -> bool {
51 matches!(self, Params::Array(_))
52 }
53
54 pub fn is_map(&self) -> bool {
56 matches!(self, Params::Map(_))
57 }
58}
59
60impl From<Params> for Value {
61 fn from(params: Params) -> Value {
62 match params {
63 Params::Array(array) => Value::Array(array),
64 Params::Map(object) => Value::Object(object),
65 }
66 }
67}
68
69#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
71#[serde(deny_unknown_fields)]
72pub struct MethodCall {
73 pub jsonrpc: Version,
75 pub method: String,
80 #[serde(skip_serializing_if = "Option::is_none")]
83 pub params: Option<Params>,
84 pub id: Id,
87}
88
89impl fmt::Display for MethodCall {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 let json = serde_json::to_string(self).expect("`MethodCall` is serializable");
92 write!(f, "{}", json)
93 }
94}
95
96impl MethodCall {
97 pub fn new<M: Into<String>>(method: M, params: Option<Params>, id: Id) -> Self {
99 Self {
100 jsonrpc: Version::V2_0,
101 method: method.into(),
102 params,
103 id,
104 }
105 }
106}
107
108#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
116#[serde(deny_unknown_fields)]
117pub struct Notification {
118 pub jsonrpc: Version,
120 pub method: String,
125 #[serde(skip_serializing_if = "Option::is_none")]
128 pub params: Option<Params>,
129}
130
131impl fmt::Display for Notification {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 let json = serde_json::to_string(self).expect("`Notification` is serializable");
134 write!(f, "{}", json)
135 }
136}
137
138impl Notification {
139 pub fn new<M: Into<String>>(method: M, params: Option<Params>) -> Self {
141 Self {
142 jsonrpc: Version::V2_0,
143 method: method.into(),
144 params,
145 }
146 }
147}
148
149#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
151#[serde(deny_unknown_fields)]
152pub struct SubscriptionNotificationParams<T = Value> {
153 pub subscription: Id,
155 pub result: T,
157}
158
159impl<T: Serialize + DeserializeOwned> SubscriptionNotificationParams<T> {
160 pub fn new(id: Id, result: T) -> Self {
162 Self {
163 subscription: id,
164 result,
165 }
166 }
167}
168
169#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
171#[serde(deny_unknown_fields)]
172pub struct SubscriptionNotification<T = Value> {
173 pub jsonrpc: Version,
175 pub method: String,
177 pub params: SubscriptionNotificationParams<T>,
179}
180
181impl<T: Serialize> fmt::Display for SubscriptionNotification<T> {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 let json = serde_json::to_string(self).expect("`SubscriptionNotification` is serializable");
184 write!(f, "{}", json)
185 }
186}
187
188impl<T: Serialize + DeserializeOwned> SubscriptionNotification<T> {
189 pub fn new<M: Into<String>>(method: M, params: SubscriptionNotificationParams<T>) -> Self {
191 Self {
192 jsonrpc: Version::V2_0,
193 method: method.into(),
194 params,
195 }
196 }
197}
198
199#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
201#[serde(deny_unknown_fields)]
202#[serde(untagged)]
203pub enum Call {
204 MethodCall(MethodCall),
206 Notification(Notification),
208}
209
210impl fmt::Display for Call {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 let json = serde_json::to_string(self).expect("`Call` is serializable");
213 write!(f, "{}", json)
214 }
215}
216
217impl Call {
218 pub fn method(&self) -> &str {
220 match self {
221 Self::MethodCall(call) => &call.method,
222 Self::Notification(notification) => ¬ification.method,
223 }
224 }
225
226 pub fn params(&self) -> &Option<Params> {
228 match self {
229 Self::MethodCall(call) => &call.params,
230 Self::Notification(notification) => ¬ification.params,
231 }
232 }
233
234 pub fn id(&self) -> Option<Id> {
236 match self {
237 Self::MethodCall(call) => Some(call.id.clone()),
238 Self::Notification(_notification) => None,
239 }
240 }
241}
242
243impl From<MethodCall> for Call {
244 fn from(call: MethodCall) -> Self {
245 Self::MethodCall(call)
246 }
247}
248
249impl From<Notification> for Call {
250 fn from(notify: Notification) -> Self {
251 Self::Notification(notify)
252 }
253}
254
255#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
257#[serde(deny_unknown_fields)]
258#[serde(untagged)]
259pub enum Request {
260 Single(Call),
262 Batch(Vec<Call>),
264}
265
266impl fmt::Display for Request {
267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268 let json = serde_json::to_string(self).expect("`Request` is serializable");
269 write!(f, "{}", json)
270 }
271}
272
273#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
275#[serde(deny_unknown_fields)]
276#[serde(untagged)]
277pub enum MethodCallRequest {
278 Single(MethodCall),
280 Batch(Vec<MethodCall>),
282}
283
284impl From<MethodCall> for MethodCallRequest {
285 fn from(call: MethodCall) -> Self {
286 Self::Single(call)
287 }
288}
289
290impl From<Vec<MethodCall>> for MethodCallRequest {
291 fn from(calls: Vec<MethodCall>) -> Self {
292 Self::Batch(calls)
293 }
294}
295
296impl fmt::Display for MethodCallRequest {
297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298 let json = serde_json::to_string(self).expect("`MethodCallRequest` is serializable");
299 write!(f, "{}", json)
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use super::*;
306
307 #[test]
308 fn params_serialization() {
309 let array = vec![Value::from(1), Value::Bool(true)];
310 let params = Params::Array(array.clone());
311 assert_eq!(serde_json::to_string(¶ms).unwrap(), r#"[1,true]"#);
312 assert_eq!(serde_json::from_str::<Params>(r#"[1,true]"#).unwrap(), params);
313
314 let object = {
315 let mut map = Map::new();
316 map.insert("key".into(), Value::String("value".into()));
317 map
318 };
319 let params = Params::Map(object.clone());
320 assert_eq!(serde_json::to_string(¶ms).unwrap(), r#"{"key":"value"}"#);
321 assert_eq!(serde_json::from_str::<Params>(r#"{"key":"value"}"#).unwrap(), params);
322
323 let params = Params::Array(vec![
324 Value::Null,
325 Value::Bool(true),
326 Value::from(-1),
327 Value::from(1),
328 Value::from(1.2),
329 Value::String("hello".to_string()),
330 Value::Array(vec![]),
331 Value::Array(array),
332 Value::Object(object),
333 ]);
334 assert_eq!(
335 serde_json::to_string(¶ms).unwrap(),
336 r#"[null,true,-1,1,1.2,"hello",[],[1,true],{"key":"value"}]"#
337 );
338 assert_eq!(
339 serde_json::from_str::<Params>(r#"[null,true,-1,1,1.2,"hello",[],[1,true],{"key":"value"}]"#).unwrap(),
340 params
341 );
342 }
343
344 #[test]
345 fn single_param_parsed_as_tuple() {
346 let params: (u64,) = Params::Array(vec![Value::from(1)]).parse().unwrap();
347 assert_eq!(params, (1,));
348 }
349
350 #[test]
351 fn invalid_params() {
352 let params = serde_json::from_str::<Params>("[1,true]").unwrap();
353 assert_eq!(
354 params.parse::<(u8, bool, String)>().unwrap_err(),
355 Error::invalid_params("invalid length 2, expected a tuple of size 3")
356 );
357 }
358
359 fn method_call_cases() -> Vec<(MethodCall, &'static str)> {
360 vec![
361 (
362 MethodCall {
364 jsonrpc: Version::V2_0,
365 method: "foo".to_string(),
366 params: Some(Params::Array(vec![Value::from(1), Value::Bool(true)])),
367 id: Id::Num(1),
368 },
369 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true],"id":1}"#,
370 ),
371 (
372 MethodCall {
374 jsonrpc: Version::V2_0,
375 method: "foo".to_string(),
376 params: Some(Params::Array(vec![])),
377 id: Id::Num(1),
378 },
379 r#"{"jsonrpc":"2.0","method":"foo","params":[],"id":1}"#,
380 ),
381 (
382 MethodCall {
384 jsonrpc: Version::V2_0,
385 method: "foo".to_string(),
386 params: None,
387 id: Id::Num(1),
388 },
389 r#"{"jsonrpc":"2.0","method":"foo","id":1}"#,
390 ),
391 ]
392 }
393
394 fn notification_cases() -> Vec<(Notification, &'static str)> {
395 vec![
396 (
397 Notification {
399 jsonrpc: Version::V2_0,
400 method: "foo".to_string(),
401 params: Some(Params::Array(vec![Value::from(1), Value::Bool(true)])),
402 },
403 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true]}"#,
404 ),
405 (
406 Notification {
408 jsonrpc: Version::V2_0,
409 method: "foo".to_string(),
410 params: Some(Params::Array(vec![])),
411 },
412 r#"{"jsonrpc":"2.0","method":"foo","params":[]}"#,
413 ),
414 (
415 Notification {
417 jsonrpc: Version::V2_0,
418 method: "foo".to_string(),
419 params: None,
420 },
421 r#"{"jsonrpc":"2.0","method":"foo"}"#,
422 ),
423 ]
424 }
425
426 #[test]
427 fn method_call_serialization() {
428 for (method_call, expect) in method_call_cases() {
429 let ser = serde_json::to_string(&method_call).unwrap();
430 assert_eq!(ser, expect);
431 let de = serde_json::from_str::<MethodCall>(expect).unwrap();
432 assert_eq!(de, method_call);
433 }
434 }
435
436 #[test]
437 fn notification_serialization() {
438 for (notification, expect) in notification_cases() {
439 let ser = serde_json::to_string(¬ification).unwrap();
440 assert_eq!(ser, expect);
441 let de = serde_json::from_str::<Notification>(expect).unwrap();
442 assert_eq!(de, notification);
443 }
444 }
445
446 #[test]
447 fn call_serialization() {
448 for (method_call, expect) in method_call_cases() {
449 let call = Call::MethodCall(method_call);
450 assert_eq!(serde_json::to_string(&call).unwrap(), expect);
451 assert_eq!(serde_json::from_str::<Call>(expect).unwrap(), call);
452 }
453
454 for (notification, expect) in notification_cases() {
455 let call = Call::Notification(notification);
456 assert_eq!(serde_json::to_string(&call).unwrap(), expect);
457 assert_eq!(serde_json::from_str::<Call>(expect).unwrap(), call);
458 }
459 }
460
461 #[test]
462 fn request_serialization() {
463 for (method_call, expect) in method_call_cases() {
464 let call_request = Request::Single(Call::MethodCall(method_call));
465 assert_eq!(serde_json::to_string(&call_request).unwrap(), expect);
466 assert_eq!(serde_json::from_str::<Request>(expect).unwrap(), call_request);
467 }
468
469 for (notification, expect) in notification_cases() {
470 let notification_request = Request::Single(Call::Notification(notification));
471 assert_eq!(serde_json::to_string(¬ification_request).unwrap(), expect);
472 assert_eq!(serde_json::from_str::<Request>(expect).unwrap(), notification_request);
473 }
474
475 let batch_request = Request::Batch(vec![
476 Call::MethodCall(MethodCall::new("foo", None, 1.into())),
477 Call::MethodCall(MethodCall::new("bar", None, 2.into())),
478 ]);
479 let batch_expect = r#"[{"jsonrpc":"2.0","method":"foo","id":1},{"jsonrpc":"2.0","method":"bar","id":2}]"#;
480 assert_eq!(serde_json::to_string(&batch_request).unwrap(), batch_expect);
481 assert_eq!(serde_json::from_str::<Request>(&batch_expect).unwrap(), batch_request);
482 }
483
484 #[test]
485 fn invalid_request() {
486 let cases = vec![
487 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true],"id":1,"unknown":[]}"#,
489 r#"{"jsonrpc":"2.0"`,"method":"foo","params":[1,true],"id":1.2}"#,
490 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true],"id":null,"unknown":[]}"#,
491 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true],"id":null}"#,
492 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true],"unknown":[]}"#,
493 r#"{"jsonrpc":"2.0","method":"foo","unknown":[]}"#,
494 r#"{"jsonrpc":"2.0","unknown":[]}"#,
495 ];
496
497 for case in cases {
498 let request = serde_json::from_str::<Request>(case);
499 assert!(request.is_err());
500 }
501 }
502
503 #[test]
504 fn valid_request() {
505 let cases = vec![
506 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true],"id":1}"#,
508 r#"{"jsonrpc":"2.0","method":"foo","params":[],"id":1}"#,
509 r#"{"jsonrpc":"2.0","method":"foo","id":1}"#,
510 r#"{"jsonrpc":"2.0","method":"foo","params":[1,true]}"#,
511 r#"{"jsonrpc":"2.0","method":"foo","params":[]}"#,
512 r#"{"jsonrpc":"2.0","method":"foo"}"#,
513 ];
514
515 for case in cases {
516 let request = serde_json::from_str::<Request>(case);
517 assert!(request.is_ok());
518 }
519 }
520}