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