@@ -206,21 +206,39 @@ impl RpcMethod {
206206 }
207207
208208 fn generate_delegate_closure ( & self , is_subscribe : bool ) -> Result < proc_macro2:: TokenStream > {
209- let mut param_types : Vec < _ > = self
209+ let args = self
210210 . trait_item
211211 . sig
212212 . inputs
213213 . iter ( )
214214 . cloned ( )
215- . filter_map ( |arg| match arg {
216- syn:: FnArg :: Typed ( ty) => Some ( * ty. ty ) ,
217- _ => None ,
215+ . filter_map ( |arg| {
216+ if let syn:: FnArg :: Typed ( pat_type) = arg {
217+ Some ( pat_type)
218+ } else {
219+ None
220+ }
218221 } )
219- . collect ( ) ;
222+ . enumerate ( ) ;
220223
221224 // special args are those which are not passed directly via rpc params: metadata, subscriber
222- let special_args = Self :: special_args ( & param_types) ;
223- param_types. retain ( |ty| !special_args. iter ( ) . any ( |( _, sty) | sty == ty) ) ;
225+ let mut special_args = vec ! [ ] ;
226+ let mut fn_args = vec ! [ ] ;
227+
228+ for ( i, arg) in args {
229+ if let Some ( sarg) = Self :: special_arg ( i, arg. clone ( ) ) {
230+ special_args. push ( sarg) ;
231+ } else {
232+ fn_args. push ( arg) ;
233+ }
234+ }
235+
236+ let special_args: Vec < _ > = special_args;
237+ let fn_args: Vec < _ > = fn_args;
238+
239+ let param_types: Vec < _ > = fn_args. iter ( ) . cloned ( ) . map ( |arg| * arg. ty ) . collect ( ) ;
240+ let arg_names: Vec < _ > = fn_args. iter ( ) . cloned ( ) . map ( |arg| * arg. pat ) . collect ( ) ;
241+
224242 if param_types. len ( ) > TUPLE_FIELD_NAMES . len ( ) {
225243 return Err ( syn:: Error :: new_spanned (
226244 & self . trait_item ,
@@ -232,28 +250,38 @@ impl RpcMethod {
232250 . take ( param_types. len ( ) )
233251 . map ( |name| ident ( name) )
234252 . collect ( ) ) ;
235- let param_types = & param_types;
236- let parse_params = {
237- // last arguments that are `Option`-s are optional 'trailing' arguments
238- let trailing_args_num = param_types. iter ( ) . rev ( ) . take_while ( |t| is_option_type ( t) ) . count ( ) ;
239-
240- if trailing_args_num != 0 {
241- self . params_with_trailing ( trailing_args_num, param_types, tuple_fields)
242- } else if param_types. is_empty ( ) {
243- quote ! { let params = params. expect_no_params( ) ; }
244- } else if self . attr . params_style == Some ( ParamStyle :: Raw ) {
245- quote ! { let params: _jsonrpc_core:: Result <_> = Ok ( ( params, ) ) ; }
246- } else if self . attr . params_style == Some ( ParamStyle :: Positional ) {
247- quote ! { let params = params. parse:: <( #( #param_types, ) * ) >( ) ; }
248- } else {
249- unimplemented ! ( "Server side named parameters are not implemented" ) ;
253+ let parse_params = if param_types. is_empty ( ) {
254+ quote ! { let params = params. expect_no_params( ) ; }
255+ } else {
256+ match self . attr . params_style . as_ref ( ) . unwrap ( ) {
257+ ParamStyle :: Raw => quote ! { let params: _jsonrpc_core:: Result <_> = Ok ( ( params, ) ) ; } ,
258+ ParamStyle :: Positional => {
259+ // last arguments that are `Option`-s are optional 'trailing' arguments
260+ let trailing_args_num = param_types. iter ( ) . rev ( ) . take_while ( |t| is_option_type ( t) ) . count ( ) ;
261+ if trailing_args_num != 0 {
262+ self . params_with_trailing ( trailing_args_num, & param_types, tuple_fields)
263+ } else {
264+ quote ! { let params = params. parse:: <( #( #param_types, ) * ) >( ) ; }
265+ }
266+ }
267+ ParamStyle :: Named => quote ! {
268+ #[ derive( serde:: Deserialize ) ]
269+ #[ allow( non_camel_case_types) ]
270+ struct __Params {
271+ #(
272+ #fn_args,
273+ ) *
274+ }
275+ let params = params. parse:: <__Params>( )
276+ . map( |__Params { #( #arg_names, ) * } | ( #( #arg_names, ) * ) ) ;
277+ } ,
250278 }
251279 } ;
252280
253281 let method_ident = self . ident ( ) ;
254282 let result = & self . trait_item . sig . output ;
255- let extra_closure_args: & Vec < _ > = & special_args. iter ( ) . cloned ( ) . map ( |arg| arg. 0 ) . collect ( ) ;
256- let extra_method_types: & Vec < _ > = & special_args. iter ( ) . cloned ( ) . map ( |arg| arg. 1 ) . collect ( ) ;
283+ let extra_closure_args: Vec < _ > = special_args. iter ( ) . cloned ( ) . map ( |arg| * arg. pat ) . collect ( ) ;
284+ let extra_method_types: Vec < _ > = special_args. iter ( ) . cloned ( ) . map ( |arg| * arg. ty ) . collect ( ) ;
257285
258286 let closure_args = quote ! { base, params, #( #extra_closure_args) , * } ;
259287 let method_sig = quote ! { fn ( & Self , #( #extra_method_types, ) * #( #param_types) , * ) #result } ;
@@ -301,34 +329,35 @@ impl RpcMethod {
301329 } )
302330 }
303331
304- fn special_args ( param_types : & [ syn:: Type ] ) -> Vec < ( syn:: Ident , syn:: Type ) > {
305- let meta_arg = param_types. first ( ) . and_then ( |ty| {
306- if * ty == parse_quote ! ( Self :: Metadata ) {
307- Some ( ty. clone ( ) )
308- } else {
309- None
310- }
311- } ) ;
312- let subscriber_arg = param_types. get ( 1 ) . and_then ( |ty| {
313- if let syn:: Type :: Path ( path) = ty {
314- if path. path . segments . iter ( ) . any ( |s| s. ident == SUBSCRIBER_TYPE_IDENT ) {
315- Some ( ty. clone ( ) )
316- } else {
317- None
332+ fn special_arg ( index : usize , arg : syn:: PatType ) -> Option < syn:: PatType > {
333+ match index {
334+ 0 if arg. ty == parse_quote ! ( Self :: Metadata ) => Some ( syn:: PatType {
335+ pat : Box :: new ( syn:: Pat :: Ident ( syn:: PatIdent {
336+ attrs : vec ! [ ] ,
337+ by_ref : None ,
338+ mutability : None ,
339+ ident : ident ( METADATA_CLOSURE_ARG ) ,
340+ subpat : None ,
341+ } ) ) ,
342+ ..arg
343+ } ) ,
344+ 1 => match * arg. ty {
345+ syn:: Type :: Path ( ref path) if path. path . segments . iter ( ) . any ( |s| s. ident == SUBSCRIBER_TYPE_IDENT ) => {
346+ Some ( syn:: PatType {
347+ pat : Box :: new ( syn:: Pat :: Ident ( syn:: PatIdent {
348+ attrs : vec ! [ ] ,
349+ by_ref : None ,
350+ mutability : None ,
351+ ident : ident ( SUBSCRIBER_CLOSURE_ARG ) ,
352+ subpat : None ,
353+ } ) ) ,
354+ ..arg
355+ } )
318356 }
319- } else {
320- None
321- }
322- } ) ;
323-
324- let mut special_args = Vec :: new ( ) ;
325- if let Some ( meta) = meta_arg {
326- special_args. push ( ( ident ( METADATA_CLOSURE_ARG ) , meta) ) ;
327- }
328- if let Some ( subscriber) = subscriber_arg {
329- special_args. push ( ( ident ( SUBSCRIBER_CLOSURE_ARG ) , subscriber) ) ;
357+ _ => None ,
358+ } ,
359+ _ => None ,
330360 }
331- special_args
332361 }
333362
334363 fn params_with_trailing (
0 commit comments