Unverified Commit b3e4297b authored by Niklas Adolfsson's avatar Niklas Adolfsson Committed by GitHub
Browse files

remove `ParamsSer::NoParams` (#501)

* fix(ParamsSer): serialize to empty array

Serialize `ParamsSer::NoParams` to an empty array inorder to comply with the jsonrpc v2 spec.

* fix tests

* remove ParamsSer::NoParams

* address grumbles: adjust rpc params macro
parent 36bdb85e
......@@ -63,7 +63,7 @@ pub fn jsonrpsee_types_v2(crit: &mut Criterion) {
b.iter(|| {
let params = &[1_u64.into(), 2_u32.into()];
let params = ParamsSer::ArrayRef(params);
let request = RequestSer::new(Id::Number(0), "say_hello", params);
let request = RequestSer::new(Id::Number(0), "say_hello", Some(params));
v2_serialize(request);
})
});
......@@ -71,7 +71,7 @@ pub fn jsonrpsee_types_v2(crit: &mut Criterion) {
crit.bench_function("jsonrpsee_types_v2_vec", |b| {
b.iter(|| {
let params = ParamsSer::Array(vec![1_u64.into(), 2_u32.into()]);
let request = RequestSer::new(Id::Number(0), "say_hello", params);
let request = RequestSer::new(Id::Number(0), "say_hello", Some(params));
v2_serialize(request);
})
});
......@@ -137,7 +137,7 @@ impl RequestBencher for AsyncBencher {
fn run_round_trip(rt: &TokioRuntime, crit: &mut Criterion, client: Arc<impl Client>, name: &str, request: RequestType) {
crit.bench_function(&request.group_name(name), |b| {
b.to_async(rt).iter(|| async {
black_box(client.request::<String>(request.method_name(), ParamsSer::NoParams).await.unwrap());
black_box(client.request::<String>(request.method_name(), None).await.unwrap());
})
});
}
......@@ -146,9 +146,7 @@ fn run_sub_round_trip(rt: &TokioRuntime, crit: &mut Criterion, client: Arc<impl
let mut group = crit.benchmark_group(name);
group.bench_function("subscribe", |b| {
b.to_async(rt).iter_with_large_drop(|| async {
black_box(
client.subscribe::<String>(SUB_METHOD_NAME, ParamsSer::NoParams, UNSUB_METHOD_NAME).await.unwrap(),
);
black_box(client.subscribe::<String>(SUB_METHOD_NAME, None, UNSUB_METHOD_NAME).await.unwrap());
})
});
group.bench_function("subscribe_response", |b| {
......@@ -158,10 +156,7 @@ fn run_sub_round_trip(rt: &TokioRuntime, crit: &mut Criterion, client: Arc<impl
// runtime context and simply calling `block_on` here will cause the code to panic.
tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(async {
client
.subscribe::<String>(SUB_METHOD_NAME, ParamsSer::NoParams, UNSUB_METHOD_NAME)
.await
.unwrap()
client.subscribe::<String>(SUB_METHOD_NAME, None, UNSUB_METHOD_NAME).await.unwrap()
})
})
},
......@@ -178,7 +173,7 @@ fn run_sub_round_trip(rt: &TokioRuntime, crit: &mut Criterion, client: Arc<impl
b.iter_with_setup(
|| {
rt.block_on(async {
client.subscribe::<String>(SUB_METHOD_NAME, ParamsSer::NoParams, UNSUB_METHOD_NAME).await.unwrap()
client.subscribe::<String>(SUB_METHOD_NAME, None, UNSUB_METHOD_NAME).await.unwrap()
})
},
|sub| {
......@@ -201,7 +196,7 @@ fn run_round_trip_with_batch(
) {
let mut group = crit.benchmark_group(request.group_name(name));
for batch_size in [2, 5, 10, 50, 100usize].iter() {
let batch = vec![(request.method_name(), ParamsSer::NoParams); *batch_size];
let batch = vec![(request.method_name(), None); *batch_size];
group.throughput(Throughput::Elements(*batch_size as u64));
group.bench_with_input(BenchmarkId::from_parameter(batch_size), batch_size, |b, _| {
b.to_async(rt).iter(|| async { client.batch_request::<String>(batch.clone()).await.unwrap() })
......@@ -225,9 +220,7 @@ fn run_concurrent_round_trip<C: 'static + Client + Send + Sync>(
|clients| async {
let tasks = clients.map(|client| {
rt.spawn(async move {
let _ = black_box(
client.request::<String>(request.method_name(), ParamsSer::NoParams).await.unwrap(),
);
let _ = black_box(client.request::<String>(request.method_name(), None).await.unwrap());
})
});
join_all(tasks).await;
......@@ -260,9 +253,7 @@ fn run_ws_concurrent_connections(rt: &TokioRuntime, crit: &mut Criterion, url: &
|clients| async {
let tasks = clients.into_iter().map(|client| {
rt.spawn(async move {
let _ = black_box(
client.request::<String>(request.method_name(), ParamsSer::NoParams).await.unwrap(),
);
let _ = black_box(client.request::<String>(request.method_name(), None).await.unwrap());
})
});
join_all(tasks).await;
......@@ -288,9 +279,7 @@ fn run_http_concurrent_connections(
|clients| async {
let tasks = clients.map(|client| {
rt.spawn(async move {
let _ = black_box(
client.request::<String>(request.method_name(), ParamsSer::NoParams).await.unwrap(),
);
let _ = black_box(client.request::<String>(request.method_name(), None).await.unwrap());
})
});
join_all(tasks).await;
......
......@@ -25,7 +25,7 @@
// DEALINGS IN THE SOFTWARE.
use jsonrpsee::{
types::{traits::Client, v2::ParamsSer},
types::traits::Client,
ws_client::WsClientBuilder,
ws_server::{RpcModule, WsServerBuilder},
};
......@@ -38,7 +38,7 @@ async fn main() -> anyhow::Result<()> {
let url = format!("ws://{}", addr);
let client = WsClientBuilder::default().build(&url).await?;
let response: String = client.request("say_hello", ParamsSer::NoParams).await?;
let response: String = client.request("say_hello", None).await?;
println!("r: {:?}", response);
Ok(())
......
......@@ -26,7 +26,7 @@
use jsonrpsee::{
rpc_params,
types::{traits::SubscriptionClient, v2::ParamsSer},
types::traits::SubscriptionClient,
ws_client::WsClientBuilder,
ws_server::{RpcModule, WsServerBuilder},
};
......@@ -42,12 +42,12 @@ async fn main() -> anyhow::Result<()> {
// Subscription with a single parameter
let mut sub_params_one =
client.subscribe::<Option<char>>("sub_one_param", rpc_params!(3), "unsub_one_param").await?;
client.subscribe::<Option<char>>("sub_one_param", rpc_params![3], "unsub_one_param").await?;
println!("subscription with one param: {:?}", sub_params_one.next().await);
// Subscription with multiple parameters
let params = ParamsSer::Array(vec![2.into(), 5.into()]);
let mut sub_params_two = client.subscribe::<String>("sub_params_two", params, "unsub_params_two").await?;
let mut sub_params_two =
client.subscribe::<String>("sub_params_two", rpc_params![2, 5], "unsub_params_two").await?;
println!("subscription with two params: {:?}", sub_params_two.next().await);
Ok(())
......
......@@ -41,7 +41,7 @@ async fn main() -> anyhow::Result<()> {
let client = WsClientBuilder::default().build(&url).await?;
let mut subscribe_hello: Subscription<String> =
client.subscribe("subscribe_hello", rpc_params!(), "unsubscribe_hello").await?;
client.subscribe("subscribe_hello", rpc_params![], "unsubscribe_hello").await?;
let mut i = 0;
while i <= NUM_SUBSCRIPTION_RESPONSES {
......
......@@ -97,7 +97,7 @@ pub struct HttpClient {
#[async_trait]
impl Client for HttpClient {
async fn notification<'a>(&self, method: &'a str, params: ParamsSer<'a>) -> Result<(), Error> {
async fn notification<'a>(&self, method: &'a str, params: Option<ParamsSer<'a>>) -> Result<(), Error> {
let notif = NotificationSer::new(method, params);
let fut = self.transport.send(serde_json::to_string(&notif).map_err(Error::ParseError)?);
match tokio::time::timeout(self.request_timeout, fut).await {
......@@ -108,7 +108,7 @@ impl Client for HttpClient {
}
/// Perform a request towards the server.
async fn request<'a, R>(&self, method: &'a str, params: ParamsSer<'a>) -> Result<R, Error>
async fn request<'a, R>(&self, method: &'a str, params: Option<ParamsSer<'a>>) -> Result<R, Error>
where
R: DeserializeOwned,
{
......@@ -150,7 +150,7 @@ impl Client for HttpClient {
}
}
async fn batch_request<'a, R>(&self, batch: Vec<(&'a str, ParamsSer<'a>)>) -> Result<Vec<R>, Error>
async fn batch_request<'a, R>(&self, batch: Vec<(&'a str, Option<ParamsSer<'a>>)>) -> Result<Vec<R>, Error>
where
R: DeserializeOwned + Default + Clone,
{
......
......@@ -33,6 +33,7 @@ use crate::HttpClientBuilder;
use jsonrpsee_test_utils::helpers::*;
use jsonrpsee_test_utils::mocks::Id;
use jsonrpsee_test_utils::TimeoutFutureExt;
use jsonrpsee_utils::rpc_params;
#[tokio::test]
async fn method_call_works() {
......@@ -50,7 +51,7 @@ async fn notification_works() {
let uri = format!("http://{}", server_addr);
let client = HttpClientBuilder::default().build(&uri).unwrap();
client
.notification("i_dont_care_about_the_response_because_the_server_should_not_respond", ParamsSer::NoParams)
.notification("i_dont_care_about_the_response_because_the_server_should_not_respond", None)
.with_default_timeout()
.await
.unwrap()
......@@ -110,11 +111,8 @@ async fn subscription_response_to_request() {
#[tokio::test]
async fn batch_request_works() {
let batch_request = vec![
("say_hello", ParamsSer::NoParams),
("say_goodbye", ParamsSer::Array(vec![0_u64.into(), 1.into(), 2.into()])),
("get_swag", ParamsSer::NoParams),
];
let batch_request =
vec![("say_hello", rpc_params![]), ("say_goodbye", rpc_params![0_u64, 1, 2]), ("get_swag", None)];
let server_response = r#"[{"jsonrpc":"2.0","result":"hello","id":0}, {"jsonrpc":"2.0","result":"goodbye","id":1}, {"jsonrpc":"2.0","result":"here's your swag","id":2}]"#.to_string();
let response =
run_batch_request_with_response(batch_request, server_response).with_default_timeout().await.unwrap().unwrap();
......@@ -123,11 +121,8 @@ async fn batch_request_works() {
#[tokio::test]
async fn batch_request_out_of_order_response() {
let batch_request = vec![
("say_hello", ParamsSer::NoParams),
("say_goodbye", ParamsSer::Array(vec![0_u64.into(), 1.into(), 2.into()])),
("get_swag", ParamsSer::NoParams),
];
let batch_request =
vec![("say_hello", rpc_params! {}), ("say_goodbye", rpc_params![0_u64, 1, 2]), ("get_swag", None)];
let server_response = r#"[{"jsonrpc":"2.0","result":"here's your swag","id":2}, {"jsonrpc":"2.0","result":"hello","id":0}, {"jsonrpc":"2.0","result":"goodbye","id":1}]"#.to_string();
let response =
run_batch_request_with_response(batch_request, server_response).with_default_timeout().await.unwrap().unwrap();
......@@ -135,7 +130,7 @@ async fn batch_request_out_of_order_response() {
}
async fn run_batch_request_with_response<'a>(
batch: Vec<(&'a str, ParamsSer<'a>)>,
batch: Vec<(&'a str, Option<ParamsSer<'a>>)>,
response: String,
) -> Result<Vec<String>, Error> {
let server_addr = http_server_with_hardcoded_response(response).with_default_timeout().await.unwrap();
......@@ -148,7 +143,7 @@ async fn run_request_with_response(response: String) -> Result<JsonValue, Error>
let server_addr = http_server_with_hardcoded_response(response).with_default_timeout().await.unwrap();
let uri = format!("http://{}", server_addr);
let client = HttpClientBuilder::default().build(&uri).unwrap();
client.request("say_hello", ParamsSer::NoParams).with_default_timeout().await.unwrap()
client.request("say_hello", None).with_default_timeout().await.unwrap()
}
fn assert_jsonrpc_error_response(err: Error, exp: ErrorObject) {
......
......@@ -101,10 +101,10 @@ impl RpcDescription {
quote! { #serde_json::to_value(&#param)? }
});
quote! {
vec![ #(#params),* ].into()
Some(vec![ #(#params),* ].into())
}
} else {
self.jrps_client_item(quote! { types::v2::params::ParamsSer::NoParams })
quote! { None }
};
// Doc-comment to be associated with the method.
......@@ -144,10 +144,10 @@ impl RpcDescription {
quote! { #serde_json::to_value(&#param)? }
});
quote! {
vec![ #(#params),* ].into()
Some(vec![ #(#params),* ].into())
}
} else {
self.jrps_client_item(quote! { types::v2::params::ParamsSer::NoParams })
quote! { None }
};
// Doc-comment to be associated with the method.
......
......@@ -2,7 +2,8 @@
use jsonrpsee::{
proc_macros::rpc,
types::{async_trait, to_json_value, traits::Client, v2::params::ParamsSer, RpcResult},
rpc_params,
types::{async_trait, traits::Client, RpcResult},
ws_client::*,
ws_server::{SubscriptionSink, WsServerBuilder},
};
......@@ -90,20 +91,11 @@ async fn main() {
assert_eq!(client.optional_params(Some(1), "a".into()).await.unwrap(), true);
assert_eq!(client.array_params(vec![1]).await.unwrap(), 1);
assert_eq!(
client
.request::<u64>("foo_array_params", vec![to_json_value(Vec::<u64>::new()).unwrap()].into())
.await
.unwrap(),
0
);
assert_eq!(client.request::<bool>("foo_optional_param", vec![].into()).await.unwrap(), false);
assert_eq!(client.request::<bool>("foo_optional_param", ParamsSer::NoParams).await.unwrap(), false);
assert_eq!(
client.request::<bool>("foo_optional_param", vec![to_json_value(Some(1)).unwrap()].into()).await.unwrap(),
true
);
assert_eq!(client.request::<u64>("foo_array_params", rpc_params![Vec::<u64>::new()]).await.unwrap(), 0);
assert_eq!(client.request::<bool>("foo_optional_param", rpc_params![]).await.unwrap(), false);
assert_eq!(client.request::<bool>("foo_optional_param", None).await.unwrap(), false);
assert_eq!(client.request::<bool>("foo_optional_param", rpc_params![1]).await.unwrap(), true);
let mut sub = client.sub().await.unwrap();
let first_recv = sub.next().await.unwrap();
......
......@@ -32,10 +32,10 @@ mod helpers;
use helpers::{http_server, websocket_server, websocket_server_with_subscription};
use jsonrpsee::{
http_client::HttpClientBuilder,
rpc_params,
types::{
error::SubscriptionClosedError,
traits::{Client, SubscriptionClient},
v2::ParamsSer,
Error, JsonValue, Subscription,
},
ws_client::WsClientBuilder,
......@@ -49,9 +49,8 @@ async fn ws_subscription_works() {
let server_url = format!("ws://{}", server_addr);
let client = WsClientBuilder::default().build(&server_url).await.unwrap();
let mut hello_sub: Subscription<String> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
let mut foo_sub: Subscription<u64> =
client.subscribe("subscribe_foo", ParamsSer::NoParams, "unsubscribe_foo").await.unwrap();
client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
let mut foo_sub: Subscription<u64> = client.subscribe("subscribe_foo", None, "unsubscribe_foo").await.unwrap();
for _ in 0..10 {
let hello = hello_sub.next().await.unwrap();
......@@ -67,7 +66,7 @@ async fn ws_subscription_with_input_works() {
let server_url = format!("ws://{}", server_addr);
let client = WsClientBuilder::default().build(&server_url).await.unwrap();
let mut add_one: Subscription<u64> =
client.subscribe("subscribe_add_one", vec![1.into()].into(), "unsubscribe_add_one").await.unwrap();
client.subscribe("subscribe_add_one", rpc_params![1], "unsubscribe_add_one").await.unwrap();
for i in 2..4 {
let next = add_one.next().await.unwrap().unwrap();
......@@ -80,7 +79,7 @@ async fn ws_method_call_works() {
let server_addr = websocket_server().await;
let server_url = format!("ws://{}", server_addr);
let client = WsClientBuilder::default().build(&server_url).await.unwrap();
let response: String = client.request("say_hello", ParamsSer::NoParams).await.unwrap();
let response: String = client.request("say_hello", None).await.unwrap();
assert_eq!(&response, "hello");
}
......@@ -89,7 +88,7 @@ async fn http_method_call_works() {
let server_addr = http_server().await;
let uri = format!("http://{}", server_addr);
let client = HttpClientBuilder::default().build(&uri).unwrap();
let response: String = client.request("say_hello", ParamsSer::NoParams).await.unwrap();
let response: String = client.request("say_hello", None).await.unwrap();
assert_eq!(&response, "hello");
}
......@@ -99,10 +98,8 @@ async fn http_concurrent_method_call_limits_works() {
let uri = format!("http://{}", server_addr);
let client = HttpClientBuilder::default().max_concurrent_requests(1).build(&uri).unwrap();
let (first, second) = tokio::join!(
client.request::<String>("say_hello", ParamsSer::NoParams),
client.request::<String>("say_hello", ParamsSer::NoParams),
);
let (first, second) =
tokio::join!(client.request::<String>("say_hello", None), client.request::<String>("say_hello", None),);
assert!(first.is_ok());
assert!(matches!(second, Err(Error::MaxSlotsExceeded)));
......@@ -117,9 +114,9 @@ async fn ws_subscription_several_clients() {
for _ in 0..10 {
let client = WsClientBuilder::default().build(&server_url).await.unwrap();
let hello_sub: Subscription<JsonValue> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
let foo_sub: Subscription<JsonValue> =
client.subscribe("subscribe_foo", ParamsSer::NoParams, "unsubscribe_foo").await.unwrap();
client.subscribe("subscribe_foo", None, "unsubscribe_foo").await.unwrap();
clients.push((client, hello_sub, foo_sub))
}
}
......@@ -134,9 +131,8 @@ async fn ws_subscription_several_clients_with_drop() {
let client =
WsClientBuilder::default().max_notifs_per_subscription(u32::MAX as usize).build(&server_url).await.unwrap();
let hello_sub: Subscription<String> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
let foo_sub: Subscription<u64> =
client.subscribe("subscribe_foo", ParamsSer::NoParams, "unsubscribe_foo").await.unwrap();
client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
let foo_sub: Subscription<u64> = client.subscribe("subscribe_foo", None, "unsubscribe_foo").await.unwrap();
clients.push((client, hello_sub, foo_sub))
}
......@@ -178,7 +174,7 @@ async fn ws_subscription_without_polling_doesnt_make_client_unuseable() {
let client = WsClientBuilder::default().max_notifs_per_subscription(4).build(&server_url).await.unwrap();
let mut hello_sub: Subscription<JsonValue> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
// don't poll the subscription stream for 2 seconds, should be full now.
tokio::time::sleep(Duration::from_secs(2)).await;
......@@ -192,11 +188,11 @@ async fn ws_subscription_without_polling_doesnt_make_client_unuseable() {
assert!(hello_sub.next().await.unwrap().is_none());
// The client should still be useable => make sure it still works.
let _hello_req: JsonValue = client.request("say_hello", ParamsSer::NoParams).await.unwrap();
let _hello_req: JsonValue = client.request("say_hello", None).await.unwrap();
// The same subscription should be possible to register again.
let mut other_sub: Subscription<JsonValue> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
other_sub.next().await.unwrap();
}
......@@ -211,7 +207,7 @@ async fn ws_making_more_requests_than_allowed_should_not_deadlock() {
for _ in 0..6 {
let c = client.clone();
requests.push(tokio::spawn(async move { c.request::<String>("say_hello", ParamsSer::NoParams).await }));
requests.push(tokio::spawn(async move { c.request::<String>("say_hello", None).await }));
}
for req in requests {
......@@ -230,7 +226,7 @@ async fn http_making_more_requests_than_allowed_should_not_deadlock() {
for _ in 0..6 {
let c = client.clone();
requests.push(tokio::spawn(async move { c.request::<String>("say_hello", ParamsSer::NoParams).await }));
requests.push(tokio::spawn(async move { c.request::<String>("say_hello", None).await }));
}
for req in requests {
......@@ -242,7 +238,7 @@ async fn http_making_more_requests_than_allowed_should_not_deadlock() {
#[ignore]
async fn https_works() {
let client = HttpClientBuilder::default().build("https://kusama-rpc.polkadot.io").unwrap();
let response: String = client.request("system_chain", ParamsSer::NoParams).await.unwrap();
let response: String = client.request("system_chain", None).await.unwrap();
assert_eq!(&response, "Kusama");
}
......@@ -250,7 +246,7 @@ async fn https_works() {
#[ignore]
async fn wss_works() {
let client = WsClientBuilder::default().build("wss://kusama-rpc.polkadot.io").await.unwrap();
let response: String = client.request("system_chain", ParamsSer::NoParams).await.unwrap();
let response: String = client.request("system_chain", None).await.unwrap();
assert_eq!(&response, "Kusama");
}
......@@ -263,7 +259,7 @@ async fn ws_with_non_ascii_url_doesnt_hang_or_panic() {
#[tokio::test]
async fn http_with_non_ascii_url_doesnt_hang_or_panic() {
let client = HttpClientBuilder::default().build("http://♥♥♥♥♥♥∀∂").unwrap();
let err: Result<(), Error> = client.request("system_chain", ParamsSer::NoParams).await;
let err: Result<(), Error> = client.request("system_chain", None).await;
assert!(matches!(err, Err(Error::Transport(_))));
}
......@@ -274,11 +270,9 @@ async fn ws_unsubscribe_releases_request_slots() {
let client = WsClientBuilder::default().max_concurrent_requests(1).build(&server_url).await.unwrap();
let sub1: Subscription<JsonValue> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
let sub1: Subscription<JsonValue> = client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
drop(sub1);
let _: Subscription<JsonValue> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
let _: Subscription<JsonValue> = client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
}
#[tokio::test]
......@@ -288,8 +282,7 @@ async fn server_should_be_able_to_close_subscriptions() {
let client = WsClientBuilder::default().build(&server_url).await.unwrap();
let mut sub: Subscription<String> =
client.subscribe("subscribe_noop", ParamsSer::NoParams, "unsubscribe_noop").await.unwrap();
let mut sub: Subscription<String> = client.subscribe("subscribe_noop", None, "unsubscribe_noop").await.unwrap();
let res = sub.next().await;
......@@ -303,15 +296,13 @@ async fn ws_close_pending_subscription_when_server_terminated() {
let c1 = WsClientBuilder::default().build(&server_url).await.unwrap();
let mut sub: Subscription<String> =
c1.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
let mut sub: Subscription<String> = c1.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
assert!(matches!(sub.next().await, Ok(Some(_))));
handle.stop().unwrap().await;
let sub2: Result<Subscription<String>, _> =
c1.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await;
let sub2: Result<Subscription<String>, _> = c1.subscribe("subscribe_hello", None, "unsubscribe_hello").await;
// no new request should be accepted.
assert!(matches!(sub2, Err(_)));
......@@ -360,8 +351,7 @@ async fn ws_server_should_stop_subscription_after_client_drop() {
let client = WsClientBuilder::default().build(&server_url).await.unwrap();
let mut sub: Subscription<usize> =
client.subscribe("subscribe_hello", ParamsSer::NoParams, "unsubscribe_hello").await.unwrap();
let mut sub: Subscription<usize> = client.subscribe("subscribe_hello", None, "unsubscribe_hello").await.unwrap();
let res = sub.next().await.unwrap();
......
......@@ -35,10 +35,10 @@ use serde_json::value::RawValue;
#[async_trait]
pub trait Client {
/// Send a [notification request](https://www.jsonrpc.org/specification#notification)
async fn notification<'a>(&self, method: &'a str, params: ParamsSer<'a>) -> Result<(), Error>;
async fn notification<'a>(&self, method: &'a str, params: Option<ParamsSer<'a>>) -> Result<(), Error>;
/// Send a [method call request](https://www.jsonrpc.org/specification#request_object).
async fn request<'a, R>(&self, method: &'a str, params: ParamsSer<'a>) -> Result<R, Error>
async fn request<'a, R>(&self, method: &'a str, params: Option<ParamsSer<'a>>) -> Result<R, Error>
where
R: DeserializeOwned;
......@@ -48,7 +48,7 @@ pub trait Client {
///
/// Returns `Ok` if all requests in the batch were answered successfully.
/// Returns `Error` if any of the requests in batch fails.
async fn batch_request<'a, R>(&self, batch: Vec<(&'a str, ParamsSer<'a>)>) -> Result<Vec<R>, Error>
async fn batch_request<'a, R>(&self, batch: Vec<(&'a str, Option<ParamsSer<'a>>)>) -> Result<Vec<R>, Error>
where
R: DeserializeOwned + Default + Clone;
}
......@@ -71,7 +71,7 @@ pub trait SubscriptionClient: Client {
async fn subscribe<'a, Notif>(
&self,
subscribe_method: &'a str,
params: ParamsSer<'a>,
params: Option<ParamsSer<'a>>,
unsubscribe_method: &'a str,
) -> Result<Subscription<Notif>, Error>
where
......
......@@ -258,8 +258,6 @@ impl<'a> ParamsSequence<'a> {
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum ParamsSer<'a> {
/// No params.
NoParams,
/// Positional params (heap allocated).
Array(Vec<JsonValue>),
/// Positional params (slice).
......@@ -401,7 +399,7 @@ mod test {
#[test]
fn params_serialize() {
let test_vector = &[
("null", ParamsSer::NoParams),
("[]", ParamsSer::Array(serde_json::from_str("[]").unwrap())),
("[42,23]", ParamsSer::Array(serde_json::from_str("[42,23]").unwrap())),
(
r#"{"a":42,"b":null,"c":"aa"}"#,
......
......@@ -80,12 +80,13 @@ pub struct RequestSer<'a> {
/// Name of the method to be invoked.
pub method: &'a str,
/// Parameter values of the request.
pub params: ParamsSer<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<ParamsSer<'a>>,
}
impl<'a> RequestSer<'a> {
/// Create a new serializable JSON-RPC request.
pub fn new(id: Id<'a>, method: &'a str, params: ParamsSer<'a>) -> Self {
pub fn new(id: Id<'a>, method: &'a str, params: Option<ParamsSer<'a>>) -> Self {
Self { jsonrpc: TwoPointZero, id, method, params }
}
}
......@@ -98,12 +99,13 @@ pub struct NotificationSer<'a> {
/// Name of the method to be invoked.
pub method: &'a str,
/// Parameter values of the request.
pub params: ParamsSer<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<ParamsSer<'a>>,
}
impl<'a> NotificationSer<'a> {
/// Create a new serializable JSON-RPC request.
pub fn new(method: &'a str, params: ParamsSer<'a>) -> Self {
pub fn new(method: &'a str, params: Option<ParamsSer<'a>>) -> Self {
Self { jsonrpc: TwoPointZero, method, params }
}
}
......@@ -176,9 +178,9 @@ mod test {
// Without ID field.
(r#"{"jsonrpc":"2.0","id":null,"method":"subtract","params":[42,23]}"#, None, Some(params)),
// Without params field