Skip to content

Commit 6cced4a

Browse files
committed
Merge branch 'use-jsonrpc-core-types-more'
2 parents cc2de04 + 19bccc3 commit 6cced4a

File tree

3 files changed

+56
-49
lines changed

3 files changed

+56
-49
lines changed

core/src/lib.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ extern crate serde;
6363
extern crate serde_json;
6464

6565
use futures::future::Future;
66+
use jsonrpc_core::types::{Id, MethodCall, Params, Version};
6667
use serde_json::Value as JsonValue;
6768

6869
/// Contains the main macro of this crate, `jsonrpc_client`.
@@ -146,24 +147,30 @@ pub trait Transport: Clone + Send + 'static {
146147
/// # Not intended for direct use
147148
/// This is being called from the client structs generated by the `jsonrpc_client` macro. This
148149
/// function is not intended to be used directly, only the generated structs should call this.
149-
pub fn call_method<T, P, R>(mut transport: T, method: &str, params: P) -> RpcRequest<R>
150+
pub fn call_method<T, P, R>(mut transport: T, method: String, params: P) -> RpcRequest<R>
150151
where
151152
T: Transport,
152153
P: serde::Serialize,
153-
for<'de> R: serde::Deserialize<'de> + Send + 'static,
154+
R: serde::de::DeserializeOwned + Send + 'static,
154155
{
155-
let id = transport.get_next_id();
156-
trace!("Serializing call to method \"{}\" with id {}", method, id);
157-
let request = serialize_request(id, method, params).chain_err(|| ErrorKind::SerializeError);
158-
let method_copy1 = method.to_owned();
159-
let method_copy2 = method.to_owned();
156+
let raw_id = transport.get_next_id();
157+
let id = Id::Num(raw_id);
158+
trace!(
159+
"Serializing call to method \"{}\" with id {}",
160+
method,
161+
raw_id
162+
);
163+
let request = serialize_request(id.clone(), method.clone(), params)
164+
.chain_err(|| ErrorKind::SerializeError);
165+
let method_copy1 = method.clone();
166+
let method_copy2 = method.clone();
160167

161168
let future = futures::future::result(request)
162169
.and_then(move |request_raw| {
163170
trace!(
164171
"Sending call to method \"{}\" with id {} to transport",
165172
method_copy1,
166-
id
173+
raw_id
167174
);
168175
transport
169176
.send(request_raw)
@@ -173,7 +180,7 @@ where
173180
trace!(
174181
"Deserializing response to method \"{}\" with id {}",
175182
method_copy2,
176-
id
183+
raw_id
177184
);
178185
response::parse::<R>(&response_raw, id)
179186
});
@@ -183,20 +190,26 @@ where
183190

184191
/// Creates a JSON-RPC 2.0 request to the given method with the given parameters.
185192
fn serialize_request<P>(
186-
id: u64,
187-
method: &str,
193+
id: Id,
194+
method: String,
188195
params: P,
189196
) -> ::std::result::Result<Vec<u8>, serde_json::error::Error>
190197
where
191198
P: serde::Serialize,
192199
{
193-
let mut request_map = serde_json::Map::new();
194-
request_map.insert(String::from("jsonrpc"), JsonValue::from("2.0"));
195-
request_map.insert(String::from("id"), JsonValue::from(id));
196-
request_map.insert(String::from("method"), JsonValue::from(method));
197-
request_map.insert(String::from("params"), serde_json::to_value(params)?);
198-
199-
serde_json::to_vec(&JsonValue::Object(request_map))
200+
let serialized_params = match serde_json::to_value(params)? {
201+
JsonValue::Null => None,
202+
JsonValue::Array(vec) => Some(Params::Array(vec)),
203+
JsonValue::Object(obj) => Some(Params::Map(obj)),
204+
value => Some(Params::Array(vec![value])),
205+
};
206+
let method_call = MethodCall {
207+
jsonrpc: Some(Version::V2),
208+
method: method.to_owned(),
209+
params: serialized_params,
210+
id,
211+
};
212+
serde_json::to_vec(&method_call)
200213
}
201214

202215

core/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ macro_rules! jsonrpc_client {
3434
pub fn $method(&mut $selff $(, $arg_name: $arg_ty)*)
3535
-> $crate::RpcRequest<$return_ty>
3636
{
37-
let method = stringify!($method);
37+
let method = String::from(stringify!($method));
3838
let params = expand_params!($($arg_name,)*);
3939
$crate::call_method($selff.transport.clone(), method, params)
4040
}

core/src/response.rs

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,42 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
use {Error, ErrorKind, Result, ResultExt};
10-
use jsonrpc_core;
9+
use {ErrorKind, Result, ResultExt};
10+
use jsonrpc_core::types::{Id, Output, Version};
1111
use serde;
12-
use serde_json::{self, Value as JsonValue};
12+
use serde_json;
1313

1414
/// Parses a binary response into json, extracts the "result" field and tries to deserialize that
1515
/// to the desired type.
16-
pub fn parse<R>(response: &[u8], expected_id: u64) -> Result<R>
16+
pub fn parse<R>(response_raw: &[u8], expected_id: Id) -> Result<R>
1717
where
18-
for<'de> R: serde::Deserialize<'de>,
18+
R: serde::de::DeserializeOwned,
1919
{
20-
let response_json = deserialize_response(response)?;
21-
let result_json = check_response_and_get_result(response_json, expected_id)?;
22-
debug!("Received json result: {}", result_json);
23-
serde_json::from_value::<R>(result_json)
24-
.chain_err(|| ErrorKind::ResponseError("Not valid for target type"))
25-
}
26-
27-
fn deserialize_response(response: &[u8]) -> Result<JsonValue> {
28-
serde_json::from_slice(response).chain_err(|| ErrorKind::ResponseError("Not valid json"))
20+
let response: Output = serde_json::from_slice(response_raw)
21+
.chain_err(|| ErrorKind::ResponseError("Not valid json"))?;
22+
match response {
23+
Output::Success(success) => {
24+
check_response(success.jsonrpc, success.id, expected_id)?;
25+
debug!("Received json result: {}", success.result);
26+
serde_json::from_value::<R>(success.result)
27+
.chain_err(|| ErrorKind::ResponseError("Not valid for target type"))
28+
}
29+
Output::Failure(failure) => {
30+
check_response(failure.jsonrpc, failure.id, expected_id)?;
31+
Err(ErrorKind::JsonRpcError(failure.error).into())
32+
}
33+
}
2934
}
3035

31-
/// Validate if response is a valid JSON-RPC 2.0 response object. If it is, it returns the
32-
/// content of the "result" field of that object.
33-
fn check_response_and_get_result(mut response: JsonValue, expected_id: u64) -> Result<JsonValue> {
34-
let response_map = response.as_object_mut().ok_or_else(|| {
35-
Error::from_kind(ErrorKind::ResponseError("Not a json object"))
36-
})?;
36+
/// Validate if response is a valid JSON-RPC 2.0 response object with the correct Id.
37+
fn check_response(version: Option<Version>, id: Id, expected_id: Id) -> Result<()> {
3738
ensure!(
38-
response_map.get("jsonrpc") == Some(&JsonValue::from("2.0")),
39+
version == Some(Version::V2),
3940
ErrorKind::ResponseError("Not JSON-RPC 2.0 compatible")
4041
);
4142
ensure!(
42-
response_map.get("id") == Some(&JsonValue::from(expected_id)),
43+
id == expected_id,
4344
ErrorKind::ResponseError("Response id not equal to request id")
4445
);
45-
if let Some(error_json) = response_map.remove("error") {
46-
let error: jsonrpc_core::Error = serde_json::from_value(error_json)
47-
.chain_err(|| ErrorKind::ResponseError("Malformed error object"))?;
48-
bail!(ErrorKind::JsonRpcError(error));
49-
}
50-
response_map
51-
.remove("result")
52-
.ok_or_else(|| ErrorKind::ResponseError("No \"result\" field").into())
46+
Ok(())
5347
}

0 commit comments

Comments
 (0)