Skip to content

Commit d86d7a1

Browse files
authored
Error on too many params (paritytech#394)
* Get rid of scary conversions in to_delegate.rs * Fix minor Clippy complaints * Update derive/src/to_delegate.rs Co-Authored-By: kirushik <[email protected]> * error on too many params * Fix too-many-params.stderr * Add comment explaining 16 field limit
1 parent d71d3bb commit d86d7a1

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

derive/src/rpc_trait.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ fn generate_rpc_item_trait(item_trait: &syn::ItemTrait) -> Result<(syn::ItemTrai
130130
}
131131

132132
let to_delegate_method =
133-
generate_trait_item_method(&method_registrations, &item_trait, rpc_trait.has_metadata, has_pubsub_methods);
133+
generate_trait_item_method(&method_registrations, &item_trait, rpc_trait.has_metadata, has_pubsub_methods)?;
134134
item_trait.items.push(syn::TraitItem::Method(to_delegate_method));
135135

136136
let trait_bounds: Punctuated<syn::TypeParamBound, Token![+]> =

derive/src/to_delegate.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::HashSet;
33
use quote::quote;
44
use syn::{
55
parse_quote, Token, punctuated::Punctuated,
6-
visit::{self, Visit},
6+
visit::{self, Visit}, Result,
77
};
88
use crate::rpc_attr::RpcMethodAttribute;
99

@@ -20,7 +20,7 @@ pub enum MethodRegistration {
2020
}
2121

2222
impl MethodRegistration {
23-
fn generate(&self) -> proc_macro2::TokenStream {
23+
fn generate(&self) -> Result<proc_macro2::TokenStream> {
2424
match self {
2525
MethodRegistration::Standard { method, has_metadata } => {
2626
let rpc_name = &method.name();
@@ -30,17 +30,17 @@ impl MethodRegistration {
3030
} else {
3131
quote!(add_method)
3232
};
33-
let closure = method.generate_delegate_closure(false);
33+
let closure = method.generate_delegate_closure(false)?;
3434
let add_aliases = method.generate_add_aliases();
3535

36-
quote! {
36+
Ok(quote! {
3737
del.#add_method(#rpc_name, #closure);
3838
#add_aliases
39-
}
39+
})
4040
},
4141
MethodRegistration::PubSub { name, subscribe, unsubscribe } => {
4242
let sub_name = subscribe.name();
43-
let sub_closure = subscribe.generate_delegate_closure(true);
43+
let sub_closure = subscribe.generate_delegate_closure(true)?;
4444
let sub_aliases = subscribe.generate_add_aliases();
4545

4646
let unsub_name = unsubscribe.name();
@@ -57,15 +57,15 @@ impl MethodRegistration {
5757
};
5858
let unsub_aliases = unsubscribe.generate_add_aliases();
5959

60-
quote! {
60+
Ok(quote! {
6161
del.add_subscription(
6262
#name,
6363
(#sub_name, #sub_closure),
6464
(#unsub_name, #unsub_closure),
6565
);
6666
#sub_aliases
6767
#unsub_aliases
68-
}
68+
})
6969
},
7070
}
7171
}
@@ -75,24 +75,25 @@ const SUBCRIBER_TYPE_IDENT: &str = "Subscriber";
7575
const METADATA_CLOSURE_ARG: &str = "meta";
7676
const SUBSCRIBER_CLOSURE_ARG: &str = "subscriber";
7777

78-
const TUPLE_FIELD_NAMES: [&str; 26] = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
78+
// tuples are limited to 16 fields: the maximum supported by `serde::Deserialize`
79+
const TUPLE_FIELD_NAMES: [&str; 16] = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"];
7980

8081
pub fn generate_trait_item_method(
8182
methods: &[MethodRegistration],
8283
trait_item: &syn::ItemTrait,
8384
has_metadata: bool,
8485
has_pubsub_methods: bool,
85-
) -> syn::TraitItemMethod {
86+
) -> Result<syn::TraitItemMethod> {
8687
let io_delegate_type =
8788
if has_pubsub_methods {
8889
quote!(_jsonrpc_pubsub::IoDelegate)
8990
} else {
9091
quote!(_jsonrpc_core::IoDelegate)
9192
};
92-
let add_methods: Vec<_> = methods
93+
let add_methods = methods
9394
.iter()
9495
.map(MethodRegistration::generate)
95-
.collect();
96+
.collect::<Result<Vec<_>>>()?;
9697
let to_delegate_body =
9798
quote! {
9899
let mut del = #io_delegate_type::new(self.into());
@@ -123,7 +124,7 @@ pub fn generate_trait_item_method(
123124
.make_where_clause()
124125
.predicates
125126
.extend(predicates);
126-
method
127+
Ok(method)
127128
}
128129

129130
#[derive(Clone)]
@@ -151,7 +152,7 @@ impl RpcMethod {
151152
self.attr.is_pubsub()
152153
}
153154

154-
fn generate_delegate_closure(&self, is_subscribe: bool) -> proc_macro2::TokenStream {
155+
fn generate_delegate_closure(&self, is_subscribe: bool) -> Result<proc_macro2::TokenStream> {
155156
let mut param_types: Vec<_> =
156157
self.trait_item.sig.decl.inputs
157158
.iter()
@@ -170,6 +171,12 @@ impl RpcMethod {
170171
param_types.retain(|ty|
171172
special_args.iter().find(|(_,sty)| sty == ty).is_none());
172173

174+
if param_types.len() > TUPLE_FIELD_NAMES.len() {
175+
return Err(syn::Error::new_spanned(
176+
&self.trait_item,
177+
&format!("Maximum supported number of params is {}", TUPLE_FIELD_NAMES.len())
178+
));
179+
}
173180
let tuple_fields : &Vec<_> =
174181
&(TUPLE_FIELD_NAMES.iter().take(param_types.len()).map(|name| ident(name)).collect());
175182
let param_types = &param_types;
@@ -220,15 +227,15 @@ impl RpcMethod {
220227
}
221228
};
222229

223-
quote! {
230+
Ok(quote! {
224231
move |#closure_args| {
225232
let method = &(Self::#method_ident as #method_sig);
226233
#parse_params
227234
match params {
228235
#match_params
229236
}
230237
}
231-
}
238+
})
232239
}
233240

234241
fn special_args(param_types: &[syn::Type]) -> Vec<(syn::Ident, syn::Type)> {

derive/tests/ui/too-many-params.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
extern crate serde;
2+
extern crate jsonrpc_core;
3+
#[macro_use]
4+
extern crate jsonrpc_derive;
5+
6+
use jsonrpc_core::Result;
7+
8+
#[rpc]
9+
pub trait Rpc {
10+
/// Has too many params
11+
#[rpc(name = "tooManyParams")]
12+
fn to_many_params(
13+
&self,
14+
_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64,
15+
_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64,
16+
) -> Result<String>;
17+
}
18+
19+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Maximum supported number of params is 16
2+
--> $DIR/too-many-params.rs:10:2
3+
|
4+
10 | /// Has too many params
5+
| _____^
6+
11 | | #[rpc(name = "tooManyParams")]
7+
12 | | fn to_many_params(
8+
13 | | &self,
9+
14 | | _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64,
10+
15 | | _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64,
11+
16 | | ) -> Result<String>;
12+
| |________________________^
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)