1#![deny(non_upper_case_globals)]
22#![deny(non_camel_case_types)]
23#![deny(non_snake_case)]
24#![deny(unused_mut)]
25#![warn(missing_docs)]
26
27pub mod client;
28pub mod error;
29mod util;
30use serde::{Deserialize, Serialize};
31use serde_derive::*;
32
33#[cfg(feature = "simple_http")]
34pub mod simple_http;
35
36pub use client::{Client, Transport};
38pub use error::Error;
39
40use serde_json::value::RawValue;
41
42pub fn try_arg<T: serde::Serialize>(arg: T) -> Result<Box<RawValue>, serde_json::Error> {
45 RawValue::from_string(serde_json::to_string(&arg)?)
46}
47
48pub fn arg<T: serde::Serialize>(arg: T) -> Box<RawValue> {
53 match try_arg(arg) {
54 Ok(v) => v,
55 Err(e) => RawValue::from_string(format!("<<ERROR SERIALIZING ARGUMENT: {}>>", e))
56 .unwrap_or(RawValue::from_string("<<ERROR SERIALIZING ARGUMENT>>".to_owned()).unwrap()),
57 }
58}
59
60#[derive(Debug, Clone, Serialize)]
61pub struct Request<'a> {
63 pub method: &'a str,
65 pub params: &'a [Box<RawValue>],
67 pub id: serde_json::Value,
69 pub jsonrpc: Option<&'a str>,
71}
72
73#[derive(Debug, Clone, Deserialize, Serialize)]
74pub struct Response {
76 pub result: Option<Box<RawValue>>,
78 pub error: Option<error::RpcError>,
80 pub id: serde_json::Value,
82 pub jsonrpc: Option<String>,
84}
85
86impl Response {
87 pub fn result<T: for<'a> serde::de::Deserialize<'a>>(&self) -> Result<T, Error> {
89 if let Some(ref e) = self.error {
90 return Err(Error::Rpc(e.clone()));
91 }
92
93 if let Some(ref res) = self.result {
94 serde_json::from_str(res.get()).map_err(Error::Json)
95 } else {
96 serde_json::from_value(serde_json::Value::Null).map_err(Error::Json)
97 }
98 }
99
100 pub fn check_error(self) -> Result<(), Error> {
102 if let Some(e) = self.error {
103 Err(Error::Rpc(e))
104 } else {
105 Ok(())
106 }
107 }
108
109 pub fn is_none(&self) -> bool {
111 self.result.is_none()
112 }
113}
114
115#[cfg(test)]
116mod tests {
117
118 use super::Response;
119 use serde_derive::*;
120 use serde_json;
121 use serde_json::value::RawValue;
122
123 #[test]
124 fn response_is_none() {
125 let joanna = Response {
126 result: Some(RawValue::from_string(serde_json::to_string(&true).unwrap()).unwrap()),
127 error: None,
128 id: From::from(81),
129 jsonrpc: Some(String::from("2.0")),
130 };
131
132 let bill = Response {
133 result: None,
134 error: None,
135 id: From::from(66),
136 jsonrpc: Some(String::from("2.0")),
137 };
138
139 assert!(!joanna.is_none());
140 assert!(bill.is_none());
141 }
142
143 #[test]
144 fn response_extract() {
145 let obj = vec!["Mary", "had", "a", "little", "lamb"];
146 let response = Response {
147 result: Some(RawValue::from_string(serde_json::to_string(&obj).unwrap()).unwrap()),
148 error: None,
149 id: serde_json::Value::Null,
150 jsonrpc: Some(String::from("2.0")),
151 };
152 let recovered1: Vec<String> = response.result().unwrap();
153 assert!(response.clone().check_error().is_ok());
154 let recovered2: Vec<String> = response.result().unwrap();
155 assert_eq!(obj, recovered1);
156 assert_eq!(obj, recovered2);
157 }
158
159 #[test]
160 fn null_result() {
161 let s = r#"{"result":null,"error":null,"id":"test"}"#;
162 let response: Response = serde_json::from_str(&s).unwrap();
163 let recovered1: Result<(), _> = response.result();
164 let recovered2: Result<(), _> = response.clone().result();
165 assert!(recovered1.is_ok());
166 assert!(recovered2.is_ok());
167
168 let recovered1: Result<String, _> = response.result();
169 let recovered2: Result<String, _> = response.clone().result();
170 assert!(recovered1.is_err());
171 assert!(recovered2.is_err());
172 }
173
174 #[test]
175 fn batch_response() {
176 let s = r#"[
178 {"jsonrpc": "2.0", "result": 7, "id": "1"},
179 {"jsonrpc": "2.0", "result": 19, "id": "2"},
180 {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": null},
181 {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "5"},
182 {"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"}
183 ]"#;
184 let batch_response: Vec<Response> = serde_json::from_str(&s).unwrap();
185 assert_eq!(batch_response.len(), 5);
186 }
187
188 #[test]
189 fn test_arg() {
190 macro_rules! test_arg {
191 ($val:expr, $t:ty) => {{
192 let val1: $t = $val;
193 let arg = super::arg(val1.clone());
194 let val2: $t = serde_json::from_str(arg.get()).expect(stringify!($val));
195 assert_eq!(val1, val2, "failed test for {}", stringify!($val));
196 }};
197 }
198
199 test_arg!(true, bool);
200 test_arg!(42, u8);
201 test_arg!(42, usize);
202 test_arg!(42, isize);
203 test_arg!(vec![42, 35], Vec<u8>);
204 test_arg!(String::from("test"), String);
205
206 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
207 struct Test {
208 v: String,
209 }
210 test_arg!(
211 Test {
212 v: String::from("test"),
213 },
214 Test
215 );
216 }
217}