jsonrpc_macros/
auto_args.rs

1// because we reuse the type names as idents in the macros as a dirty hack to
2// work around `concat_idents!` being unstable.
3#![allow(non_snake_case)]
4
5///! Automatically serialize and deserialize parameters around a strongly-typed function.
6
7use jsonrpc_core::{Error, Params, Value, Metadata, Result};
8use jsonrpc_core::futures::{self, Future, IntoFuture};
9use jsonrpc_core::futures::future::{self, Either};
10use jsonrpc_pubsub::{PubSubMetadata, Subscriber};
11use pubsub;
12use serde::Serialize;
13use serde::de::DeserializeOwned;
14use util::{invalid_params, expect_no_params, to_value};
15
16/// Auto-generates an RPC trait from trait definition.
17///
18/// This just copies out all the methods, docs, and adds another
19/// function `to_delegate` which will automatically wrap each strongly-typed
20/// function in a wrapper which handles parameter and output type serialization.
21///
22/// RPC functions may come in a couple forms: synchronous, async and async with metadata.
23/// These are parsed with the custom `#[rpc]` attribute, which must follow
24/// documentation.
25///
26/// ## The #[rpc] attribute
27///
28/// Valid forms:
29///  - `#[rpc(name = "name_here")]` (an async rpc function which should be bound to the given name)
30///  - `#[rpc(meta, name = "name_here")]` (an async rpc function with metadata which should be bound to the given name)
31///
32/// Synchronous function format:
33/// `fn foo(&self, Param1, Param2, Param3) -> Result<Out>`.
34///
35/// Asynchronous RPC functions must come in this form:
36/// `fn foo(&self, Param1, Param2, Param3) -> BoxFuture<Out>;
37///
38/// Asynchronous RPC functions with metadata must come in this form:
39/// `fn foo(&self, Self::Metadata, Param1, Param2, Param3) -> BoxFuture<Out>;
40///
41/// Anything else will be rejected by the code generator.
42///
43/// ## The #[pubsub] attribute
44///
45/// Valid form:
46/// ```rust,ignore
47///	#[pubsub(name = "hello")] {
48///	  #[rpc(name = "hello_subscribe")]
49///	  fn subscribe(&self, Self::Metadata, pubsub::Subscriber<String>, u64);
50///	  #[rpc(name = "hello_unsubscribe")]
51///	  fn unsubscribe(&self, Option<Self::Metadata>, SubscriptionId) -> Result<bool>;
52///	}
53///	```
54///
55/// The attribute is used to create a new pair of subscription methods
56/// (if underlying transport supports that.)
57
58
59#[macro_export]
60macro_rules! metadata {
61	() => {
62		/// Requests metadata
63		type Metadata: $crate::jsonrpc_core::Metadata;
64	};
65	(
66		$( $sub_name: ident )+
67	) => {
68		/// Requests metadata
69		type Metadata: $crate::jsonrpc_pubsub::PubSubMetadata;
70	};
71}
72
73#[macro_export]
74macro_rules! build_rpc_trait {
75	(
76		$(#[$t_attr: meta])*
77		pub trait $name:ident $(<$( $generics:ident ),*>
78			$(
79				where
80					$( $generics2:ident : $bounds:tt $( + $morebounds:tt )* ,)+
81			)*
82		)*
83		{
84			$( $rest: tt )+
85		}
86	) => {
87		build_rpc_trait! {
88			@WITH_BOUNDS
89			$(#[$t_attr])*
90			pub trait $name $(<
91				// first generic parameters with both bounds
92				$( $generics ,)*
93				@BOUNDS
94				// then specialised ones
95				$( $( $generics2 : $bounds $( + $morebounds )* ,)* )*
96			> )* {
97				$( $rest )+
98			}
99		}
100	};
101	(
102		@WITH_BOUNDS
103		$(#[$t_attr: meta])*
104		pub trait $name:ident $(<
105			$( $simple_generics:ident ,)*
106			@BOUNDS
107			$( $generics:ident : $bounds:tt $( + $morebounds:tt )* ,)*
108		>)* {
109			$(
110				$( #[doc=$m_doc:expr] )*
111				#[ rpc( $($t:tt)* ) ]
112				fn $m_name: ident ( $( $p: tt )* ) -> $result: tt <$out: ty $(, $error: ty)* >;
113			)*
114		}
115	) => {
116		$(#[$t_attr])*
117		pub trait $name $(<$( $simple_generics ,)* $( $generics , )*>)* : Sized + Send + Sync + 'static {
118			build_rpc_trait!(
119				GENERATE_FUNCTIONS
120				$(
121					$(#[doc=$m_doc])*
122					fn $m_name ( $( $p )* ) -> $result <$out $(, $error) *>;
123				)*
124			);
125
126			/// Transform this into an `IoDelegate`, automatically wrapping
127			/// the parameters.
128			#[deprecated(since = "10.0", note = "Generated by jsonrpc-macros. Please use `#[rpc]` from jsonrpc-derive instead")]
129			fn to_delegate<M: $crate::jsonrpc_core::Metadata>(self) -> $crate::IoDelegate<Self, M>
130				where $(
131					$($simple_generics: Send + Sync + 'static + $crate::Serialize + $crate::DeserializeOwned ,)*
132					$($generics: Send + Sync + 'static + $bounds $( + $morebounds )* ,)*
133				)*
134			{
135				let mut del = $crate::IoDelegate::new(self.into());
136				$(
137					build_rpc_trait!(WRAP del =>
138						( $($t)* )
139						fn $m_name ( $( $p )* ) -> $result <$out $(, $error)* >
140					);
141				)*
142				del
143			}
144		}
145	};
146
147	// entry-point for trait with metadata methods
148	(
149		@WITH_BOUNDS
150		$(#[$t_attr: meta])*
151		pub trait $name: ident $(<
152			$( $simple_generics:ident ,)*
153			@BOUNDS
154			$( $generics:ident : $bounds:tt $( + $morebounds:tt )* ,)*
155		>)* {
156			type Metadata;
157
158			$(
159				$( #[ doc=$m_doc:expr ] )*
160				#[ rpc( $($t:tt)* ) ]
161				fn $m_name: ident ( $( $p: tt )* ) -> $result: tt <$out: ty $(, $error_std: ty) *>;
162			)*
163
164			$(
165				#[ pubsub( $($pubsub_t:tt)+ ) ] {
166					$( #[ doc= $sub_doc:expr ] )*
167					#[ rpc( $($sub_t:tt)* ) ]
168					fn $sub_name: ident ( $($sub_p: tt)* );
169					$( #[ doc= $unsub_doc:expr ] )*
170					#[ rpc( $($unsub_t:tt)* ) ]
171					fn $unsub_name: ident ( $($unsub_p: tt)* ) -> $sub_result: tt <$sub_out: ty $(, $error_unsub: ty)* >;
172				}
173			)*
174
175		}
176	) => {
177		$(#[$t_attr])*
178		pub trait $name $(<$( $simple_generics ,)* $( $generics , )* >)* : Sized + Send + Sync + 'static {
179			// Metadata bound differs for traits with subscription methods.
180			metadata! (
181				$( $sub_name )*
182			);
183
184			build_rpc_trait!(GENERATE_FUNCTIONS
185				$(
186					$(#[doc=$m_doc])*
187					fn $m_name ( $( $p )* ) -> $result <$out $(, $error_std) *>;
188				)*
189			);
190
191			build_rpc_trait!(GENERATE_FUNCTIONS
192				$(
193					$(#[doc=$sub_doc])*
194					fn $sub_name ( $( $sub_p )* );
195					$(#[doc=$unsub_doc])*
196					fn $unsub_name ( $( $unsub_p )* ) -> $sub_result <$sub_out $(, $error_unsub) *>;
197				)*
198			);
199
200			/// Transform this into an `IoDelegate`, automatically wrapping
201			/// the parameters.
202			#[deprecated(since = "10.0", note = "Generated by jsonrpc-macros. Please use `#[rpc]` from jsonrpc-derive instead")]
203			fn to_delegate(self) -> $crate::IoDelegate<Self, Self::Metadata>
204				where $(
205					$($simple_generics: Send + Sync + 'static + $crate::Serialize + $crate::DeserializeOwned ,)*
206					$($generics: Send + Sync + 'static + $bounds $( + $morebounds )* , )*
207				)*
208			{
209				let mut del = $crate::IoDelegate::new(self.into());
210				$(
211					build_rpc_trait!(WRAP del =>
212						( $($t)* )
213						fn $m_name ( $( $p )* ) -> $result <$out $(, $error_std)* >
214					);
215				)*
216				$(
217					build_rpc_trait!(WRAP del =>
218						pubsub: ( $($pubsub_t)* )
219						subscribe: ( $($sub_t)* )
220						fn $sub_name ( $($sub_p)* );
221						unsubscribe: ( $($unsub_t)* )
222						fn $unsub_name ( $($unsub_p)* ) -> $sub_result <$sub_out $(, $error_unsub)* >;
223					);
224				)*
225				del
226			}
227		}
228	};
229
230	(GENERATE_FUNCTIONS
231		$(
232			$( #[doc=$m_doc:expr] )*
233			fn $m_name: ident (&self $(, $p: ty)* ) $( -> $result: ty)*;
234		)*
235	) => {
236		$(
237			$(#[doc=$m_doc])*
238			fn $m_name (&self $(, _: $p )* ) $( -> $result)*;
239		)*
240	};
241
242	( WRAP $del: expr =>
243		(meta, name = $name: expr $(, alias = [ $( $alias: expr, )+ ])*)
244		fn $method: ident (&self, Self::Metadata $(, $param: ty)*) -> $result: tt <$out: ty $(, $error: ty)* >
245	) => {
246		$del.add_method_with_meta($name, move |base, params, meta| {
247			$crate::WrapMeta::wrap_rpc(&(Self::$method as fn(&_, Self::Metadata $(, $param)*) -> $result <$out $(, $error)* >), base, params, meta)
248		});
249		$(
250			$(
251				$del.add_alias($alias, $name);
252			)+
253		)*
254	};
255
256	( WRAP $del: expr =>
257		pubsub: (name = $name: expr)
258		subscribe: (name = $subscribe: expr $(, alias = [ $( $sub_alias: expr, )+ ])*)
259		fn $sub_method: ident (&self, Self::Metadata $(, $sub_p: ty)+);
260		unsubscribe: (name = $unsubscribe: expr $(, alias = [ $( $unsub_alias: expr, )+ ])*)
261		fn $unsub_method: ident (&self, Option < Self::Metadata > $(, $unsub_p: ty)+) -> $result: tt <$out: ty $(, $error_unsub: ty)* >;
262	) => {
263		$del.add_subscription(
264			$name,
265			($subscribe, move |base, params, meta, subscriber| {
266				$crate::WrapSubscribe::wrap_rpc(
267					&(Self::$sub_method as fn(&_, Self::Metadata $(, $sub_p)*)),
268					base,
269					params,
270					meta,
271					subscriber,
272				)
273			}),
274			($unsubscribe, move |base, id, meta| {
275				use $crate::jsonrpc_core::futures::{IntoFuture, Future};
276				Self::$unsub_method(base, meta, id).into_future()
277					.map($crate::to_value)
278					.map_err(Into::into)
279			}),
280		);
281
282		$(
283			$(
284				$del.add_alias($sub_alias, $subscribe);
285			)*
286		)*
287		$(
288			$(
289				$del.add_alias($unsub_alias, $unsubscribe);
290			)*
291		)*
292	};
293
294	( WRAP $del: expr =>
295		(name = $name: expr $(, alias = [ $( $alias: expr, )+ ])*)
296		fn $method: ident (&self $(, $param: ty)*) -> $result: tt <$out: ty $(, $error: ty)* >
297	) => {
298		$del.add_method($name, move |base, params| {
299			$crate::WrapAsync::wrap_rpc(&(Self::$method as fn(&_ $(, $param)*) -> $result <$out $(, $error)*>), base, params)
300		});
301		$(
302			$(
303				$del.add_alias($alias, $name);
304			)+
305		)*
306	};
307}
308
309/// A wrapper type without an implementation of `Deserialize`
310/// which allows a special implementation of `Wrap` for functions
311/// that take a trailing default parameter.
312pub struct Trailing<T>(Option<T>);
313
314impl<T> Into<Option<T>> for Trailing<T> {
315	fn into(self) -> Option<T> {
316		self.0
317	}
318}
319
320impl<T> From<Option<T>> for Trailing<T> {
321	fn from(o: Option<T>) -> Self {
322		Trailing(o)
323	}
324}
325
326impl<T: DeserializeOwned> Trailing<T> {
327	/// Returns a underlying value if present or provided value.
328	pub fn unwrap_or(self, other: T) -> T {
329		self.0.unwrap_or(other)
330	}
331
332	/// Returns an underlying value or computes it if not present.
333	pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
334		self.0.unwrap_or_else(f)
335	}
336}
337
338impl<T: Default + DeserializeOwned> Trailing<T> {
339	/// Returns an underlying value or the default value.
340	pub fn unwrap_or_default(self) -> T {
341		self.0.unwrap_or_default()
342	}
343}
344
345type WrappedFuture<F, OUT, E> = future::MapErr<
346	future::Map<F, fn(OUT) -> Value>,
347	fn(E) -> Error
348>;
349type WrapResult<F, OUT, E> = Either<
350	WrappedFuture<F, OUT, E>,
351	future::FutureResult<Value, Error>,
352>;
353
354fn as_future<F, OUT, E, I>(el: I) -> WrappedFuture<F, OUT, E> where
355	OUT: Serialize,
356	E: Into<Error>,
357	F: Future<Item = OUT, Error = E>,
358	I: IntoFuture<Item = OUT, Error = E, Future = F>
359{
360	el.into_future()
361		.map(to_value as fn(OUT) -> Value)
362		.map_err(Into::into as fn(E) -> Error)
363}
364
365/// Wrapper trait for asynchronous RPC functions.
366pub trait WrapAsync<B> {
367	/// Output type.
368	type Out: IntoFuture<Item = Value, Error = Error>;
369
370	/// Invokes asynchronous RPC method.
371	fn wrap_rpc(&self, base: &B, params: Params) -> Self::Out;
372}
373
374/// Wrapper trait for meta RPC functions.
375pub trait WrapMeta<B, M> {
376	/// Output type.
377	type Out: IntoFuture<Item = Value, Error = Error>;
378	/// Invokes asynchronous RPC method with Metadata.
379	fn wrap_rpc(&self, base: &B, params: Params, meta: M) -> Self::Out;
380}
381
382/// Wrapper trait for subscribe RPC functions.
383pub trait WrapSubscribe<B, M> {
384	/// Invokes subscription.
385	fn wrap_rpc(&self, base: &B, params: Params, meta: M, subscriber: Subscriber);
386}
387
388// special impl for no parameters.
389impl<B, OUT, E, F, I> WrapAsync<B> for fn(&B) -> I where
390	B: Send + Sync + 'static,
391	OUT: Serialize + 'static,
392	E: Into<Error> + 'static,
393	F: Future<Item = OUT, Error = E> + Send + 'static,
394	I: IntoFuture<Item = OUT, Error = E, Future = F>,
395{
396	type Out = WrapResult<F, OUT, E>;
397
398	fn wrap_rpc(&self, base: &B, params: Params) -> Self::Out {
399		match expect_no_params(params) {
400			Ok(()) => Either::A(as_future((self)(base))),
401			Err(e) => Either::B(futures::failed(e)),
402		}
403	}
404}
405
406impl<M, B, OUT, E, F, I> WrapMeta<B, M> for fn(&B, M) -> I where
407	M: Metadata,
408	B: Send + Sync + 'static,
409	OUT: Serialize + 'static,
410	E: Into<Error> + 'static,
411	F: Future<Item = OUT, Error = E> + Send + 'static,
412	I: IntoFuture<Item = OUT, Error = E, Future = F>,
413{
414	type Out = WrapResult<F, OUT, E>;
415
416	fn wrap_rpc(&self, base: &B, params: Params, meta: M) -> Self::Out {
417		match expect_no_params(params) {
418			Ok(()) => Either::A(as_future((self)(base, meta))),
419			Err(e) => Either::B(futures::failed(e)),
420		}
421	}
422}
423
424impl<M, B, OUT> WrapSubscribe<B, M> for fn(&B, M, pubsub::Subscriber<OUT>) where
425	M: PubSubMetadata,
426	B: Send + Sync + 'static,
427	OUT: Serialize,
428{
429	fn wrap_rpc(&self, base: &B, params: Params, meta: M, subscriber: Subscriber) {
430		match expect_no_params(params) {
431			Ok(()) => (self)(base, meta, pubsub::Subscriber::new(subscriber)),
432			Err(e) => {
433				let _ = subscriber.reject(e);
434			},
435		}
436	}
437}
438
439// creates a wrapper implementation which deserializes the parameters,
440// calls the function with concrete type, and serializes the output.
441macro_rules! wrap {
442	($($x: ident),+) => {
443
444		// asynchronous implementation
445		impl <
446			BASE: Send + Sync + 'static,
447			OUT: Serialize + 'static,
448			$($x: DeserializeOwned,)+
449			ERR: Into<Error> + 'static,
450			X: Future<Item = OUT, Error = ERR> + Send + 'static,
451			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
452		> WrapAsync<BASE> for fn(&BASE, $($x,)+ ) -> Z {
453			type Out = WrapResult<X, OUT, ERR>;
454			fn wrap_rpc(&self, base: &BASE, params: Params) -> Self::Out {
455				match params.parse::<($($x,)+)>() {
456					Ok(($($x,)+)) => Either::A(as_future((self)(base, $($x,)+))),
457					Err(e) => Either::B(futures::failed(e)),
458				}
459			}
460		}
461
462		// asynchronous implementation with meta
463		impl <
464			BASE: Send + Sync + 'static,
465			META: Metadata,
466			OUT: Serialize + 'static,
467			$($x: DeserializeOwned,)+
468			ERR: Into<Error> + 'static,
469			X: Future<Item = OUT, Error = ERR> + Send + 'static,
470			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
471		> WrapMeta<BASE, META> for fn(&BASE, META, $($x,)+) -> Z {
472			type Out = WrapResult<X, OUT, ERR>;
473			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META) -> Self::Out {
474				match params.parse::<($($x,)+)>() {
475					Ok(($($x,)+)) => Either::A(as_future((self)(base, meta, $($x,)+))),
476					Err(e) => Either::B(futures::failed(e)),
477				}
478			}
479		}
480
481		// subscribe implementation
482		impl <
483			BASE: Send + Sync + 'static,
484			META: PubSubMetadata,
485			OUT: Serialize,
486			$($x: DeserializeOwned,)+
487		> WrapSubscribe<BASE, META> for fn(&BASE, META, pubsub::Subscriber<OUT>, $($x,)+) {
488			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META, subscriber: Subscriber) {
489				match params.parse::<($($x,)+)>() {
490					Ok(($($x,)+)) => (self)(base, meta, pubsub::Subscriber::new(subscriber), $($x,)+),
491					Err(e) => {
492						let _ = subscriber.reject(e);
493					},
494				}
495			}
496		}
497	}
498}
499
500fn params_len(params: &Params) -> Result<usize> {
501	match *params {
502		Params::Array(ref v) => Ok(v.len()),
503		Params::None => Ok(0),
504		_ => Err(invalid_params("`params` should be an array", "")),
505	}
506}
507
508fn require_len(params: &Params, required: usize) -> Result<usize> {
509	let len = params_len(params)?;
510	if len < required {
511		return Err(invalid_params(&format!("`params` should have at least {} argument(s)", required), ""));
512	}
513	Ok(len)
514}
515
516fn parse_trailing_param<T: DeserializeOwned>(params: Params) -> Result<(Option<T>, )> {
517	let len = try!(params_len(&params));
518	let id = match len {
519		0 => Ok((None,)),
520		1 => params.parse::<(T,)>().map(|(x, )| (Some(x), )),
521		_ => Err(invalid_params("Expecting only one optional parameter.", "")),
522	};
523
524	id
525}
526
527// special impl for no parameters other than block parameter.
528impl<B, OUT, T, E, F, I> WrapAsync<B> for fn(&B, Trailing<T>) -> I where
529	B: Send + Sync + 'static,
530	OUT: Serialize + 'static,
531	T: DeserializeOwned,
532	E: Into<Error> + 'static,
533	F: Future<Item = OUT, Error = E> + Send + 'static,
534	I: IntoFuture<Item = OUT, Error = E, Future = F>,
535{
536	type Out = WrapResult<F, OUT, E>;
537	fn wrap_rpc(&self, base: &B, params: Params) -> Self::Out {
538		let id = parse_trailing_param(params);
539
540		match id {
541			Ok((id,)) => Either::A(as_future((self)(base, Trailing(id)))),
542			Err(e) => Either::B(futures::failed(e)),
543		}
544	}
545}
546
547impl<M, B, OUT, T, E, F, I> WrapMeta<B, M> for fn(&B, M, Trailing<T>) -> I where
548	M: Metadata,
549	B: Send + Sync + 'static,
550	OUT: Serialize + 'static,
551	T: DeserializeOwned,
552	E: Into<Error> + 'static,
553	F: Future<Item = OUT, Error = E> + Send + 'static,
554	I: IntoFuture<Item = OUT, Error = E, Future = F>,
555{
556	type Out = WrapResult<F, OUT, E>;
557	fn wrap_rpc(&self, base: &B, params: Params, meta: M) -> Self::Out {
558		let id = parse_trailing_param(params);
559
560		match id {
561			Ok((id,)) => Either::A(as_future((self)(base, meta, Trailing(id)))),
562			Err(e) => Either::B(futures::failed(e)),
563		}
564	}
565}
566
567impl<M, B, OUT, T> WrapSubscribe<B, M> for fn(&B, M, pubsub::Subscriber<OUT>, Trailing<T>) where
568	M: PubSubMetadata,
569	B: Send + Sync + 'static,
570	OUT: Serialize,
571	T: DeserializeOwned,
572{
573	fn wrap_rpc(&self, base: &B, params: Params, meta: M, subscriber: Subscriber) {
574		let id = parse_trailing_param(params);
575
576		match id {
577			Ok((id,)) => (self)(base, meta, pubsub::Subscriber::new(subscriber), Trailing(id)),
578			Err(e) => {
579				let _ = subscriber.reject(e);
580			},
581		}
582	}
583}
584
585// similar to `wrap!`, but handles a single default trailing parameter
586// accepts an additional argument indicating the number of non-trailing parameters.
587macro_rules! wrap_with_trailing {
588	($num: expr, $($x: ident),+) => {
589		// asynchronous implementation
590		impl <
591			BASE: Send + Sync + 'static,
592			OUT: Serialize + 'static,
593			$($x: DeserializeOwned,)+
594			TRAILING: DeserializeOwned,
595			ERR: Into<Error> + 'static,
596			X: Future<Item = OUT, Error = ERR> + Send + 'static,
597			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
598		> WrapAsync<BASE> for fn(&BASE, $($x,)+ Trailing<TRAILING>) -> Z {
599			type Out = WrapResult<X, OUT, ERR>;
600			fn wrap_rpc(&self, base: &BASE, params: Params) -> Self::Out {
601				let len = match require_len(&params, $num) {
602					Ok(len) => len,
603					Err(e) => return Either::B(futures::failed(e)),
604				};
605
606				let params = match len - $num {
607					0 => params.parse::<($($x,)+)>()
608						.map(|($($x,)+)| ($($x,)+ None)).map_err(Into::into),
609					1 => params.parse::<($($x,)+ TRAILING)>()
610						.map(|($($x,)+ id)| ($($x,)+ Some(id))).map_err(Into::into),
611					_ => Err(invalid_params(&format!("Expected {} or {} parameters.", $num, $num + 1), format!("Got: {}", len))),
612				};
613
614				match params {
615					Ok(($($x,)+ id)) => Either::A(as_future((self)(base, $($x,)+ Trailing(id)))),
616					Err(e) => Either::B(futures::failed(e)),
617				}
618			}
619		}
620
621		// asynchronous implementation with meta
622		impl <
623			BASE: Send + Sync + 'static,
624			META: Metadata,
625			OUT: Serialize + 'static,
626			$($x: DeserializeOwned,)+
627			TRAILING: DeserializeOwned,
628			ERR: Into<Error> + 'static,
629			X: Future<Item = OUT, Error = ERR> + Send + 'static,
630			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
631		> WrapMeta<BASE, META> for fn(&BASE, META, $($x,)+ Trailing<TRAILING>) -> Z {
632			type Out = WrapResult<X, OUT, ERR>;
633			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META) -> Self::Out {
634				let len = match require_len(&params, $num) {
635					Ok(len) => len,
636					Err(e) => return Either::B(futures::failed(e)),
637				};
638
639				let params = match len - $num {
640					0 => params.parse::<($($x,)+)>()
641						.map(|($($x,)+)| ($($x,)+ None)).map_err(Into::into),
642					1 => params.parse::<($($x,)+ TRAILING)>()
643						.map(|($($x,)+ id)| ($($x,)+ Some(id))).map_err(Into::into),
644					_ => Err(invalid_params(&format!("Expected {} or {} parameters.", $num, $num + 1), format!("Got: {}", len))),
645				};
646
647				match params {
648					Ok(($($x,)+ id)) => Either::A(as_future((self)(base, meta, $($x,)+ Trailing(id)))),
649					Err(e) => Either::B(futures::failed(e)),
650				}
651			}
652		}
653
654		// subscribe implementation
655		impl <
656			BASE: Send + Sync + 'static,
657			META: PubSubMetadata,
658			OUT: Serialize,
659			$($x: DeserializeOwned,)+
660			TRAILING: DeserializeOwned,
661		> WrapSubscribe<BASE, META> for fn(&BASE, META, pubsub::Subscriber<OUT>, $($x,)+ Trailing<TRAILING>) {
662			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META, subscriber: Subscriber) {
663				let len = match require_len(&params, $num) {
664					Ok(len) => len,
665					Err(e) => {
666						let _ = subscriber.reject(e);
667						return;
668					},
669				};
670
671				let params = match len - $num {
672					0 => params.parse::<($($x,)+)>()
673						.map(|($($x,)+)| ($($x,)+ None)),
674					1 => params.parse::<($($x,)+ TRAILING)>()
675						.map(|($($x,)+ id)| ($($x,)+ Some(id))),
676					_ => {
677						let _ = subscriber.reject(invalid_params(&format!("Expected {} or {} parameters.", $num, $num + 1), format!("Got: {}", len)));
678						return;
679					},
680				};
681
682				match params {
683					Ok(($($x,)+ id)) => (self)(base, meta, pubsub::Subscriber::new(subscriber), $($x,)+ Trailing(id)),
684					Err(e) => {
685						let _ = subscriber.reject(e);
686						return;
687					},
688				}
689			}
690		}
691	}
692}
693
694wrap!(A, B, C, D, E, F);
695wrap!(A, B, C, D, E);
696wrap!(A, B, C, D);
697wrap!(A, B, C);
698wrap!(A, B);
699wrap!(A);
700
701wrap_with_trailing!(6, A, B, C, D, E, F);
702wrap_with_trailing!(5, A, B, C, D, E);
703wrap_with_trailing!(4, A, B, C, D);
704wrap_with_trailing!(3, A, B, C);
705wrap_with_trailing!(2, A, B);
706wrap_with_trailing!(1, A);