1use std::fmt::{Formatter, Result as FmtResult};
14
15use serde::ser::{Serialize, SerializeStruct, Serializer};
16use serde::de::{Deserialize, Deserializer, Error, Unexpected, Visitor};
17use serde_json::{to_value, Result as JsonResult, Value};
18use uuid::Uuid;
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21struct Version;
22
23impl Serialize for Version {
24 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
25 serializer.serialize_str("2.0")
26 }
27}
28
29impl<'de> Deserialize<'de> for Version {
30 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
31 struct VersionVisitor;
32 impl<'de> Visitor<'de> for VersionVisitor {
33 type Value = Version;
34
35 fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
36 formatter.write_str("a version string")
37 }
38
39 fn visit_str<E: Error>(self, value: &str) -> Result<Version, E> {
40 match value {
41 "2.0" => Ok(Version),
42 _ => Err(E::invalid_value(Unexpected::Str(value), &"value 2.0")),
43 }
44 }
45 }
46 deserializer.deserialize_str(VersionVisitor)
47 }
48}
49
50#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
52#[serde(deny_unknown_fields)]
53pub struct Request {
54 jsonrpc: Version,
55 pub method: String,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub params: Option<Value>,
58 pub id: Value,
59}
60
61impl Request {
62 pub fn reply(&self, reply: Value) -> Message {
66 Message::Response(Response {
67 jsonrpc: Version,
68 result: Ok(reply),
69 id: self.id.clone(),
70 })
71 }
72 pub fn error(&self, error: RpcError) -> Message {
74 Message::Response(Response {
75 jsonrpc: Version,
76 result: Err(error),
77 id: self.id.clone(),
78 })
79 }
80}
81
82#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
84#[serde(deny_unknown_fields)]
85pub struct RpcError {
86 pub code: i64,
87 pub message: String,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub data: Option<Value>,
90}
91
92impl RpcError {
93 pub fn new(code: i64, message: String, data: Option<Value>) -> Self {
97 RpcError {
98 code,
99 message,
100 data,
101 }
102 }
103 pub fn invalid_params(msg: Option<String>) -> Self {
105 RpcError::new(-32_602, "Invalid params".to_owned(), msg.map(Value::String))
106 }
107 pub fn server_error<E: Serialize>(e: Option<E>) -> Self {
109 RpcError::new(
110 -32_000,
111 "Server error".to_owned(),
112 e.map(|v| to_value(v).expect("Must be representable in JSON")),
113 )
114 }
115 pub fn invalid_request() -> Self {
117 RpcError::new(-32_600, "Invalid request".to_owned(), None)
118 }
119 pub fn parse_error(e: String) -> Self {
121 RpcError::new(-32_700, "Parse error".to_owned(), Some(Value::String(e)))
122 }
123 pub fn method_not_found(method: String) -> Self {
125 RpcError::new(
126 -32_601,
127 "Method not found".to_owned(),
128 Some(Value::String(method)),
129 )
130 }
131}
132
133#[derive(Debug, Clone, PartialEq)]
137pub struct Response {
138 jsonrpc: Version,
139 pub result: Result<Value, RpcError>,
140 pub id: Value,
141}
142
143impl Serialize for Response {
144 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
145 let mut sub = serializer.serialize_struct("Response", 3)?;
146 sub.serialize_field("jsonrpc", &self.jsonrpc)?;
147 match self.result {
148 Ok(ref value) => sub.serialize_field("result", value),
149 Err(ref err) => sub.serialize_field("error", err),
150 }?;
151 sub.serialize_field("id", &self.id)?;
152 sub.end()
153 }
154}
155
156fn some_value<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Value>, D::Error> {
161 Deserialize::deserialize(deserializer).map(Some)
162}
163
164#[derive(Deserialize)]
166#[serde(deny_unknown_fields)]
167struct WireResponse {
168 #[allow(dead_code)]
170 jsonrpc: Version,
171 #[serde(default, deserialize_with = "some_value")]
173 result: Option<Value>,
174 error: Option<RpcError>,
175 id: Value,
176}
177
178impl<'de> Deserialize<'de> for Response {
182 #[allow(unreachable_code)] fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
184 let wr: WireResponse = Deserialize::deserialize(deserializer)?;
185 let result = match (wr.result, wr.error) {
186 (Some(res), None) => Ok(res),
187 (None, Some(err)) => Err(err),
188 _ => {
189 let err = D::Error::custom("Either 'error' or 'result' is expected, but not both");
190 return Err(err);
191 },
192 };
193 Ok(Response {
194 jsonrpc: Version,
195 result,
196 id: wr.id,
197 })
198 }
199}
200
201#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
203#[serde(deny_unknown_fields)]
204pub struct Notification {
205 jsonrpc: Version,
206 pub method: String,
207 #[serde(skip_serializing_if = "Option::is_none")]
208 pub params: Option<Value>,
209}
210
211#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
225#[serde(untagged)]
226pub enum Message {
227 Request(Request),
229 Response(Response),
231 Notification(Notification),
233 Batch(Vec<Message>),
240 #[serde(skip_serializing)]
246 UnmatchedSub(Value),
247}
248
249impl Message {
250 pub fn request(method: String, params: Option<Value>) -> Self {
254 Message::Request(Request {
255 jsonrpc: Version,
256 method,
257 params,
258 id: Value::String(Uuid::new_v4().hyphenated().to_string()),
259 })
260 }
261 pub fn error(error: RpcError) -> Self {
263 Message::Response(Response {
264 jsonrpc: Version,
265 result: Err(error),
266 id: Value::Null,
267 })
268 }
269 pub fn notification(method: String, params: Option<Value>) -> Self {
271 Message::Notification(Notification {
272 jsonrpc: Version,
273 method,
274 params,
275 })
276 }
277}
278
279#[derive(Debug, Clone, PartialEq, Deserialize)]
283#[serde(untagged)]
284pub enum Broken {
285 Unmatched(Value),
287 #[serde(skip_deserializing)]
289 SyntaxError(String),
290}
291
292impl Broken {
293 pub fn reply(&self) -> Message {
298 match *self {
299 Broken::Unmatched(_) => Message::error(RpcError::invalid_request()),
300 Broken::SyntaxError(ref e) => Message::error(RpcError::parse_error(e.clone())),
301 }
302 }
303}
304
305#[derive(Deserialize)]
307#[serde(untagged)]
308pub(crate) enum WireMessage {
309 Message(Message),
310 Broken(Broken),
311}
312
313pub(crate) fn decoded_to_parsed(res: JsonResult<WireMessage>) -> Parsed {
314 match res {
315 Ok(WireMessage::Message(Message::UnmatchedSub(value))) => Err(Broken::Unmatched(value)),
316 Ok(WireMessage::Message(m)) => Ok(m),
317 Ok(WireMessage::Broken(b)) => Err(b),
318 Err(e) => Err(Broken::SyntaxError(format!("{}", e))),
319 }
320}
321
322pub type Parsed = Result<Message, Broken>;
323
324pub fn from_slice(s: &[u8]) -> Parsed {
328 decoded_to_parsed(::serde_json::de::from_slice(s))
329}
330
331pub fn from_str(s: &str) -> Parsed {
335 from_slice(s.as_bytes())
336}
337
338impl Into<String> for Message {
339 fn into(self) -> String {
340 ::serde_json::ser::to_string(&self).unwrap()
341 }
342}
343
344impl Into<Vec<u8>> for Message {
345 fn into(self) -> Vec<u8> {
346 ::serde_json::ser::to_vec(&self).unwrap()
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 use super::*;
353 use serde_json::Value;
354 use serde_json::ser::to_vec;
355 use serde_json::de::from_slice;
356
357 #[test]
363 fn message_serde() {
364 fn one(input: &str, expected: &Message) {
366 let parsed: Message = from_str(input).unwrap();
367 assert_eq!(*expected, parsed);
368 let serialized = to_vec(&parsed).unwrap();
369 let deserialized: Message = from_slice(&serialized).unwrap();
370 assert_eq!(parsed, deserialized);
371 }
372
373 one(
375 r#"{"jsonrpc": "2.0", "method": "call", "id": 1}"#,
376 &Message::Request(Request {
377 jsonrpc: Version,
378 method: "call".to_owned(),
379 params: None,
380 id: json!(1),
381 }),
382 );
383 one(
385 r#"{"jsonrpc": "2.0", "method": "call", "params": [1, 2, 3], "id": 2}"#,
386 &Message::Request(Request {
387 jsonrpc: Version,
388 method: "call".to_owned(),
389 params: Some(json!([1, 2, 3])),
390 id: json!(2),
391 }),
392 );
393 one(
395 r#"{"jsonrpc": "2.0", "method": "notif", "params": {"x": "y"}}"#,
396 &Message::Notification(Notification {
397 jsonrpc: Version,
398 method: "notif".to_owned(),
399 params: Some(json!({"x": "y"})),
400 }),
401 );
402 one(
404 r#"{"jsonrpc": "2.0", "result": 42, "id": 3}"#,
405 &Message::Response(Response {
406 jsonrpc: Version,
407 result: Ok(json!(42)),
408 id: json!(3),
409 }),
410 );
411 one(
413 r#"{"jsonrpc": "2.0", "result": null, "id": 3}"#,
414 &Message::Response(Response {
415 jsonrpc: Version,
416 result: Ok(Value::Null),
417 id: json!(3),
418 }),
419 );
420 one(
422 r#"{"jsonrpc": "2.0", "error": {"code": 42, "message": "Wrong!"}, "id": null}"#,
423 &Message::Response(Response {
424 jsonrpc: Version,
425 result: Err(RpcError::new(42, "Wrong!".to_owned(), None)),
426 id: Value::Null,
427 }),
428 );
429 one(
431 r#"[
432 {"jsonrpc": "2.0", "method": "notif"},
433 {"jsonrpc": "2.0", "method": "call", "id": 42}
434 ]"#,
435 &Message::Batch(vec![
436 Message::Notification(Notification {
437 jsonrpc: Version,
438 method: "notif".to_owned(),
439 params: None,
440 }),
441 Message::Request(Request {
442 jsonrpc: Version,
443 method: "call".to_owned(),
444 params: None,
445 id: json!(42),
446 }),
447 ]),
448 );
449 let parsed = from_str(
451 r#"[
452 {"jsonrpc": "2.0", "method": "notif"},
453 {"jsonrpc": "2.0", "method": "call", "id": 42},
454 true
455 ]"#,
456 ).unwrap();
457 assert_eq!(
458 Message::Batch(vec![
459 Message::Notification(Notification {
460 jsonrpc: Version,
461 method: "notif".to_owned(),
462 params: None,
463 }),
464 Message::Request(Request {
465 jsonrpc: Version,
466 method: "call".to_owned(),
467 params: None,
468 id: json!(42),
469 }),
470 Message::UnmatchedSub(Value::Bool(true)),
471 ]),
472 parsed
473 );
474 to_vec(&Message::UnmatchedSub(Value::Null)).unwrap_err();
475 }
476
477 #[test]
485 fn broken() {
486 fn one(input: &str) {
488 let msg = from_str(input);
489 match msg {
490 Err(Broken::Unmatched(_)) => (),
491 _ => panic!("{} recognized as an RPC message: {:?}!", input, msg),
492 }
493 }
494
495 one(r#"{"method": "notif"}"#);
497 one(r#"{"jsonrpc": 2.0, "method": "notif"}"#);
499 one(r#"{"jsonrpc": "2.0", "result": 42, "error": {"code": 42, "message": "!"}, "id": 1}"#);
501 one(r#"{"jsonrpc": "2.0", "result": 42}"#);
503 one(r#"{"jsonrpc": "2.0", "method": "weird", "params": 42, "others": 43, "id": 2}"#);
505 one(r#"{"x": [1, 2, 3]}"#);
507
508 match from_str(r#"{]"#) {
509 Err(Broken::SyntaxError(_)) => (),
510 other => panic!("Something unexpected: {:?}", other),
511 };
512 }
513
514 #[test]
519 fn constructors() {
520 let msg1 = Message::request("call".to_owned(), Some(json!([1, 2, 3])));
521 let msg2 = Message::request("call".to_owned(), Some(json!([1, 2, 3])));
522 assert_ne!(msg1, msg2);
524 let (req1, req2) = if let (Message::Request(req1), Message::Request(req2)) = (msg1, msg2) {
526 assert_ne!(req1.id, req2.id);
527 assert!(req1.id.is_string());
528 assert!(req2.id.is_string());
529 (req1, req2)
530 } else {
531 panic!("Non-request received");
532 };
533 let id1 = req1.id.clone();
534 if let Message::Response(ref resp) = req1.reply(json!([1, 2, 3])) {
536 assert_eq!(
537 *resp,
538 Response {
539 jsonrpc: Version,
540 result: Ok(json!([1, 2, 3])),
541 id: id1,
542 }
543 );
544 } else {
545 panic!("Not a response");
546 }
547 let id2 = req2.id.clone();
548 if let Message::Response(ref resp) =
550 req2.error(RpcError::new(42, "Wrong!".to_owned(), None))
551 {
552 assert_eq!(
553 *resp,
554 Response {
555 jsonrpc: Version,
556 result: Err(RpcError::new(42, "Wrong!".to_owned(), None)),
557 id: id2,
558 }
559 );
560 } else {
561 panic!("Not a response");
562 }
563 if let Message::Response(ref resp) =
565 Message::error(RpcError::new(43, "Also wrong!".to_owned(), None))
566 {
567 assert_eq!(
568 *resp,
569 Response {
570 jsonrpc: Version,
571 result: Err(RpcError::new(43, "Also wrong!".to_owned(), None)),
572 id: Value::Null,
573 }
574 );
575 } else {
576 panic!("Not a response");
577 }
578 }
579}