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(near_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::Value;
288 use serde_json::de::from_slice;
289 use serde_json::json;
290 use serde_json::ser::to_vec;
291
292 use super::*;
293
294 #[test]
301 fn message_serde() {
302 fn one(input: &str, expected: &Message) {
304 let parsed: Message = from_str(input).unwrap();
305 assert_eq!(*expected, parsed);
306 let serialized = to_vec(&parsed).unwrap();
307 let deserialized: Message = from_slice(&serialized).unwrap();
308 assert_eq!(parsed, deserialized);
309 }
310
311 one(
313 r#"{"jsonrpc": "2.0", "method": "call", "id": 1}"#,
314 &Message::Request(Request {
315 jsonrpc: Version,
316 method: "call".to_owned(),
317 params: Value::Null,
318 id: json!(1),
319 }),
320 );
321 one(
323 r#"{"jsonrpc": "2.0", "method": "call", "params": [1, 2, 3], "id": 2}"#,
324 &Message::Request(Request {
325 jsonrpc: Version,
326 method: "call".to_owned(),
327 params: json!([1, 2, 3]),
328 id: json!(2),
329 }),
330 );
331 one(
333 r#"{"jsonrpc": "2.0", "method": "notif", "params": {"x": "y"}}"#,
334 &Message::Notification(Notification {
335 jsonrpc: Version,
336 method: "notif".to_owned(),
337 params: json!({"x": "y"}),
338 }),
339 );
340 one(
342 r#"{"jsonrpc": "2.0", "result": 42, "id": 3}"#,
343 &Message::Response(Response { jsonrpc: Version, result: Ok(json!(42)), id: json!(3) }),
344 );
345 one(
347 r#"{"jsonrpc": "2.0", "result": null, "id": 3}"#,
348 &Message::Response(Response {
349 jsonrpc: Version,
350 result: Ok(Value::Null),
351 id: json!(3),
352 }),
353 );
354 one(
356 r#"{"jsonrpc": "2.0", "error": {"code": 42, "message": "Wrong!"}, "id": null}"#,
357 &Message::Response(Response {
358 jsonrpc: Version,
359 result: Err(RpcError::new(42, "Wrong!".to_owned(), None)),
360 id: Value::Null,
361 }),
362 );
363 one(
365 r#"[
366 {"jsonrpc": "2.0", "method": "notif"},
367 {"jsonrpc": "2.0", "method": "call", "id": 42}
368 ]"#,
369 &Message::Batch(vec![
370 Message::Notification(Notification {
371 jsonrpc: Version,
372 method: "notif".to_owned(),
373 params: Value::Null,
374 }),
375 Message::Request(Request {
376 jsonrpc: Version,
377 method: "call".to_owned(),
378 params: Value::Null,
379 id: json!(42),
380 }),
381 ]),
382 );
383 let parsed = from_str(
385 r#"[
386 {"jsonrpc": "2.0", "method": "notif"},
387 {"jsonrpc": "2.0", "method": "call", "id": 42},
388 true
389 ]"#,
390 )
391 .unwrap();
392 assert_eq!(
393 Message::Batch(vec![
394 Message::Notification(Notification {
395 jsonrpc: Version,
396 method: "notif".to_owned(),
397 params: Value::Null,
398 }),
399 Message::Request(Request {
400 jsonrpc: Version,
401 method: "call".to_owned(),
402 params: Value::Null,
403 id: json!(42),
404 }),
405 Message::UnmatchedSub(Value::Bool(true)),
406 ]),
407 parsed
408 );
409 to_vec(&Message::UnmatchedSub(Value::Null)).unwrap_err();
410 }
411
412 #[test]
420 fn broken() {
421 fn one(input: &str) {
423 let msg = from_str(input);
424 match msg {
425 Err(Broken::Unmatched(_)) => (),
426 _ => panic!("{} recognized as an RPC message: {:?}!", input, msg),
427 }
428 }
429
430 one(r#"{"method": "notif"}"#);
432 one(r#"{"jsonrpc": 2.0, "method": "notif"}"#);
434 one(r#"{"jsonrpc": "2.0", "result": 42, "error": {"code": 42, "message": "!"}, "id": 1}"#);
436 one(r#"{"jsonrpc": "2.0", "result": 42}"#);
438 one(r#"{"jsonrpc": "2.0", "method": "weird", "params": 42, "others": 43, "id": 2}"#);
440 one(r#"{"x": [1, 2, 3]}"#);
442
443 match from_str(r#"{]"#) {
444 Err(Broken::SyntaxError(_)) => (),
445 other => panic!("Something unexpected: {:?}", other),
446 };
447 }
448
449 #[test]
454 fn constructors() {
455 let msg1 = Message::request("call".to_owned(), json!([1, 2, 3]));
456 let msg2 = Message::request("call".to_owned(), json!([1, 2, 3]));
457 assert_ne!(msg1, msg2);
459 let (req1, req2) = if let (Message::Request(req1), Message::Request(req2)) = (msg1, msg2) {
461 assert_ne!(req1.id, req2.id);
462 assert!(req1.id.is_string());
463 assert!(req2.id.is_string());
464 (req1, req2)
465 } else {
466 panic!("Non-request received");
467 };
468 let id1 = req1.id.clone();
469 if let Message::Response(ref resp) = req1.reply(json!([1, 2, 3])) {
471 assert_eq!(*resp, Response { jsonrpc: Version, result: Ok(json!([1, 2, 3])), id: id1 });
472 } else {
473 panic!("Not a response");
474 }
475 let id2 = req2.id.clone();
476 if let Message::Response(ref resp) =
478 req2.error(RpcError::new(42, "Wrong!".to_owned(), None))
479 {
480 assert_eq!(
481 *resp,
482 Response {
483 jsonrpc: Version,
484 result: Err(RpcError::new(42, "Wrong!".to_owned(), None)),
485 id: id2,
486 }
487 );
488 } else {
489 panic!("Not a response");
490 }
491 if let Message::Response(ref resp) =
493 Message::error(RpcError::new(43, "Also wrong!".to_owned(), None))
494 {
495 assert_eq!(
496 *resp,
497 Response {
498 jsonrpc: Version,
499 result: Err(RpcError::new(43, "Also wrong!".to_owned(), None)),
500 id: Value::Null,
501 }
502 );
503 } else {
504 panic!("Not a response");
505 }
506 }
507}