1use crate::errors::RpcError;
13use serde::de::{Deserializer, Error, Unexpected, Visitor};
14use serde::ser::{SerializeStruct, Serializer};
15use serde_json::{Result as JsonResult, Value};
16use std::fmt::{Formatter, Result as FmtResult};
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19struct Version;
20
21impl serde::Serialize for Version {
22 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
23 serializer.serialize_str("2.0")
24 }
25}
26
27impl<'de> serde::Deserialize<'de> for Version {
28 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
29 struct VersionVisitor;
30 impl<'de> Visitor<'de> for VersionVisitor {
31 type Value = Version;
32
33 fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {
34 formatter.write_str("a version string")
35 }
36
37 fn visit_str<E: Error>(self, value: &str) -> Result<Version, E> {
38 match value {
39 "2.0" => Ok(Version),
40 _ => Err(E::invalid_value(Unexpected::Str(value), &"value 2.0")),
41 }
42 }
43 }
44 deserializer.deserialize_str(VersionVisitor)
45 }
46}
47
48#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
50#[serde(deny_unknown_fields)]
51pub struct Request {
52 jsonrpc: Version,
53 pub method: String,
54 #[serde(default, skip_serializing_if = "Value::is_null")]
55 pub params: Value,
56 pub id: Value,
57}
58
59impl Request {
60 pub fn reply(&self, reply: Value) -> Message {
64 Message::Response(Response { jsonrpc: Version, result: Ok(reply), id: self.id.clone() })
65 }
66 pub fn error(&self, error: RpcError) -> Message {
68 Message::Response(Response { jsonrpc: Version, result: Err(error), id: self.id.clone() })
69 }
70}
71
72#[derive(Debug, Clone, PartialEq)]
76pub struct Response {
77 jsonrpc: Version,
78 pub result: Result<Value, RpcError>,
79 pub id: Value,
80}
81
82impl serde::Serialize for Response {
83 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
84 let mut sub = serializer.serialize_struct("Response", 3)?;
85 sub.serialize_field("jsonrpc", &self.jsonrpc)?;
86 match self.result {
87 Ok(ref value) => sub.serialize_field("result", value),
88 Err(ref err) => sub.serialize_field("error", err),
89 }?;
90 sub.serialize_field("id", &self.id)?;
91 sub.end()
92 }
93}
94
95fn some_value<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Value>, D::Error> {
100 serde::Deserialize::deserialize(deserializer).map(Some)
101}
102
103#[derive(serde::Deserialize)]
105#[serde(deny_unknown_fields)]
106struct WireResponse {
107 #[allow(dead_code)]
109 jsonrpc: Version,
110 #[serde(default, deserialize_with = "some_value")]
112 result: Option<Value>,
113 error: Option<RpcError>,
114 id: Value,
115}
116
117impl<'de> serde::Deserialize<'de> for Response {
121 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
122 let wr: WireResponse = serde::Deserialize::deserialize(deserializer)?;
123 let result = match (wr.result, wr.error) {
124 (Some(res), None) => Ok(res),
125 (None, Some(err)) => Err(err),
126 _ => {
127 let err = D::Error::custom("Either 'error' or 'result' is expected, but not both");
128 return Err(err);
129 }
130 };
131 Ok(Response { jsonrpc: Version, result, id: wr.id })
132 }
133}
134
135#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
137#[serde(deny_unknown_fields)]
138pub struct Notification {
139 jsonrpc: Version,
140 pub method: String,
141 #[serde(default, skip_serializing_if = "Value::is_null")]
142 pub params: Value,
143}
144
145#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
159#[serde(untagged)]
160pub enum Message {
161 Request(Request),
163 Response(Response),
165 Notification(Notification),
167 Batch(Vec<Message>),
174 #[serde(skip_serializing)]
180 UnmatchedSub(Value),
181}
182
183impl Message {
184 pub fn request(method: String, params: Value) -> Self {
188 let id = Value::from(unc_primitives::utils::generate_random_string(9));
189 Message::Request(Request { jsonrpc: Version, method, params, id })
190 }
191 pub fn error(error: RpcError) -> Self {
193 Message::Response(Response { jsonrpc: Version, result: Err(error), id: Value::Null })
194 }
195 pub fn notification(method: String, params: Value) -> Self {
197 Message::Notification(Notification { jsonrpc: Version, method, params })
198 }
199 pub fn response(id: Value, result: Result<Value, RpcError>) -> Self {
201 Message::Response(Response { jsonrpc: Version, result, id })
202 }
203 pub fn id(&self) -> Value {
205 match self {
206 Message::Request(req) => req.id.clone(),
207 _ => Value::Null,
208 }
209 }
210}
211
212#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
216#[serde(untagged)]
217pub enum Broken {
218 Unmatched(Value),
220 #[serde(skip_deserializing)]
222 SyntaxError(String),
223}
224
225impl Broken {
226 pub fn reply(&self) -> Message {
231 match *self {
232 Broken::Unmatched(_) => Message::error(RpcError::parse_error(
233 "JSON RPC Request format was expected".to_owned(),
234 )),
235 Broken::SyntaxError(ref e) => Message::error(RpcError::parse_error(e.clone())),
236 }
237 }
238}
239
240#[derive(serde::Deserialize)]
242#[serde(untagged)]
243pub enum WireMessage {
244 Message(Message),
245 Broken(Broken),
246}
247
248pub fn decoded_to_parsed(res: JsonResult<WireMessage>) -> Parsed {
249 match res {
250 Ok(WireMessage::Message(Message::UnmatchedSub(value))) => Err(Broken::Unmatched(value)),
251 Ok(WireMessage::Message(m)) => Ok(m),
252 Ok(WireMessage::Broken(b)) => Err(b),
253 Err(e) => Err(Broken::SyntaxError(e.to_string())),
254 }
255}
256
257pub type Parsed = Result<Message, Broken>;
258
259pub fn from_slice(s: &[u8]) -> Parsed {
263 decoded_to_parsed(::serde_json::de::from_slice(s))
264}
265
266pub fn from_str(s: &str) -> Parsed {
270 from_slice(s.as_bytes())
271}
272
273impl Into<String> for Message {
274 fn into(self) -> String {
275 ::serde_json::ser::to_string(&self).unwrap()
276 }
277}
278
279impl Into<Vec<u8>> for Message {
280 fn into(self) -> Vec<u8> {
281 ::serde_json::ser::to_vec(&self).unwrap()
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use serde_json::de::from_slice;
288 use serde_json::json;
289 use serde_json::ser::to_vec;
290 use serde_json::Value;
291
292 use super::*;
293
294 #[test]
300 fn message_serde() {
301 fn one(input: &str, expected: &Message) {
303 let parsed: Message = from_str(input).unwrap();
304 assert_eq!(*expected, parsed);
305 let serialized = to_vec(&parsed).unwrap();
306 let deserialized: Message = from_slice(&serialized).unwrap();
307 assert_eq!(parsed, deserialized);
308 }
309
310 one(
312 r#"{"jsonrpc": "2.0", "method": "call", "id": 1}"#,
313 &Message::Request(Request {
314 jsonrpc: Version,
315 method: "call".to_owned(),
316 params: Value::Null,
317 id: json!(1),
318 }),
319 );
320 one(
322 r#"{"jsonrpc": "2.0", "method": "call", "params": [1, 2, 3], "id": 2}"#,
323 &Message::Request(Request {
324 jsonrpc: Version,
325 method: "call".to_owned(),
326 params: json!([1, 2, 3]),
327 id: json!(2),
328 }),
329 );
330 one(
332 r#"{"jsonrpc": "2.0", "method": "notif", "params": {"x": "y"}}"#,
333 &Message::Notification(Notification {
334 jsonrpc: Version,
335 method: "notif".to_owned(),
336 params: json!({"x": "y"}),
337 }),
338 );
339 one(
341 r#"{"jsonrpc": "2.0", "result": 42, "id": 3}"#,
342 &Message::Response(Response { jsonrpc: Version, result: Ok(json!(42)), id: json!(3) }),
343 );
344 one(
346 r#"{"jsonrpc": "2.0", "result": null, "id": 3}"#,
347 &Message::Response(Response {
348 jsonrpc: Version,
349 result: Ok(Value::Null),
350 id: json!(3),
351 }),
352 );
353 one(
355 r#"{"jsonrpc": "2.0", "error": {"code": 42, "message": "Wrong!"}, "id": null}"#,
356 &Message::Response(Response {
357 jsonrpc: Version,
358 result: Err(RpcError::new(42, "Wrong!".to_owned(), None)),
359 id: Value::Null,
360 }),
361 );
362 one(
364 r#"[
365 {"jsonrpc": "2.0", "method": "notif"},
366 {"jsonrpc": "2.0", "method": "call", "id": 42}
367 ]"#,
368 &Message::Batch(vec![
369 Message::Notification(Notification {
370 jsonrpc: Version,
371 method: "notif".to_owned(),
372 params: Value::Null,
373 }),
374 Message::Request(Request {
375 jsonrpc: Version,
376 method: "call".to_owned(),
377 params: Value::Null,
378 id: json!(42),
379 }),
380 ]),
381 );
382 let parsed = from_str(
384 r#"[
385 {"jsonrpc": "2.0", "method": "notif"},
386 {"jsonrpc": "2.0", "method": "call", "id": 42},
387 true
388 ]"#,
389 )
390 .unwrap();
391 assert_eq!(
392 Message::Batch(vec![
393 Message::Notification(Notification {
394 jsonrpc: Version,
395 method: "notif".to_owned(),
396 params: Value::Null,
397 }),
398 Message::Request(Request {
399 jsonrpc: Version,
400 method: "call".to_owned(),
401 params: Value::Null,
402 id: json!(42),
403 }),
404 Message::UnmatchedSub(Value::Bool(true)),
405 ]),
406 parsed
407 );
408 to_vec(&Message::UnmatchedSub(Value::Null)).unwrap_err();
409 }
410
411 #[test]
419 fn broken() {
420 fn one(input: &str) {
422 let msg = from_str(input);
423 match msg {
424 Err(Broken::Unmatched(_)) => (),
425 _ => panic!("{} recognized as an RPC message: {:?}!", input, msg),
426 }
427 }
428
429 one(r#"{"method": "notif"}"#);
431 one(r#"{"jsonrpc": 2.0, "method": "notif"}"#);
433 one(r#"{"jsonrpc": "2.0", "result": 42, "error": {"code": 42, "message": "!"}, "id": 1}"#);
435 one(r#"{"jsonrpc": "2.0", "result": 42}"#);
437 one(r#"{"jsonrpc": "2.0", "method": "weird", "params": 42, "others": 43, "id": 2}"#);
439 one(r#"{"x": [1, 2, 3]}"#);
441
442 match from_str(r#"{]"#) {
443 Err(Broken::SyntaxError(_)) => (),
444 other => panic!("Something unexpected: {:?}", other),
445 };
446 }
447
448 #[test]
453 fn constructors() {
454 let msg1 = Message::request("call".to_owned(), json!([1, 2, 3]));
455 let msg2 = Message::request("call".to_owned(), json!([1, 2, 3]));
456 assert_ne!(msg1, msg2);
458 let (req1, req2) = if let (Message::Request(req1), Message::Request(req2)) = (msg1, msg2) {
460 assert_ne!(req1.id, req2.id);
461 assert!(req1.id.is_string());
462 assert!(req2.id.is_string());
463 (req1, req2)
464 } else {
465 panic!("Non-request received");
466 };
467 let id1 = req1.id.clone();
468 if let Message::Response(ref resp) = req1.reply(json!([1, 2, 3])) {
470 assert_eq!(*resp, Response { jsonrpc: Version, result: Ok(json!([1, 2, 3])), id: id1 });
471 } else {
472 panic!("Not a response");
473 }
474 let id2 = req2.id.clone();
475 if let Message::Response(ref resp) =
477 req2.error(RpcError::new(42, "Wrong!".to_owned(), None))
478 {
479 assert_eq!(
480 *resp,
481 Response {
482 jsonrpc: Version,
483 result: Err(RpcError::new(42, "Wrong!".to_owned(), None)),
484 id: id2,
485 }
486 );
487 } else {
488 panic!("Not a response");
489 }
490 if let Message::Response(ref resp) =
492 Message::error(RpcError::new(43, "Also wrong!".to_owned(), None))
493 {
494 assert_eq!(
495 *resp,
496 Response {
497 jsonrpc: Version,
498 result: Err(RpcError::new(43, "Also wrong!".to_owned(), None)),
499 id: Value::Null,
500 }
501 );
502 } else {
503 panic!("Not a response");
504 }
505 }
506}