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