bitconch_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, 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	// entry-point. todo: make another for traits w/ bounds.
76	(
77		$(#[$t_attr: meta])*
78		pub trait $name: ident $(<$($generics:ident),*>)* {
79			$(
80				$( #[doc=$m_doc:expr] )*
81				#[ rpc( $($t:tt)* ) ]
82				fn $m_name: ident ( $($p: tt)* ) -> $result: tt <$out: ty $(, $error: ty)* >;
83			)*
84		}
85	) => {
86		$(#[$t_attr])*
87		pub trait $name $(<$($generics,)*>)* : Sized + Send + Sync + 'static {
88			$(
89				$(#[doc=$m_doc])*
90				fn $m_name ( $($p)* ) -> $result<$out $(, $error)* > ;
91			)*
92
93			/// Transform this into an `IoDelegate`, automatically wrapping
94			/// the parameters.
95			fn to_delegate<M: $crate::jsonrpc_core::Metadata>(self) -> $crate::IoDelegate<Self, M>
96				where $($($generics: Send + Sync + 'static + $crate::Serialize + $crate::DeserializeOwned),*)*
97			{
98				let mut del = $crate::IoDelegate::new(self.into());
99				$(
100					build_rpc_trait!(WRAP del =>
101						( $($t)* )
102						fn $m_name ( $($p)* ) -> $result <$out $(, $error)* >
103					);
104				)*
105				del
106			}
107		}
108	};
109
110	// entry-point for trait with metadata methods
111	(
112		$(#[$t_attr: meta])*
113		pub trait $name: ident $(<$($generics:ident),*>)* {
114			type Metadata;
115
116			$(
117				$( #[ doc=$m_doc:expr ] )*
118				#[ rpc( $($t:tt)* ) ]
119				fn $m_name: ident ( $($p: tt)* ) -> $result: tt <$out: ty $(, $error_std: ty) *>;
120			)*
121
122			$(
123				#[ pubsub( $($pubsub_t:tt)+ ) ] {
124					$( #[ doc= $sub_doc:expr ] )*
125					#[ rpc( $($sub_t:tt)* ) ]
126					fn $sub_name: ident ( $($sub_p: tt)* );
127					$( #[ doc= $unsub_doc:expr ] )*
128					#[ rpc( $($unsub_t:tt)* ) ]
129					fn $unsub_name: ident ( $($unsub_p: tt)* ) -> $sub_result: tt <$sub_out: ty $(, $error_unsub: ty)* >;
130				}
131			)*
132
133		}
134	) => {
135		$(#[$t_attr])*
136		pub trait $name $(<$($generics,)*>)* : Sized + Send + Sync + 'static {
137			// Metadata bound differs for traits with subscription methods.
138			metadata! (
139				$( $sub_name )*
140			);
141
142			$(
143				$(#[doc=$m_doc])*
144				fn $m_name ( $($p)* ) -> $result <$out $(, $error_std) *>;
145			)*
146
147			$(
148				$(#[doc=$sub_doc])*
149				fn $sub_name ( $($sub_p)* );
150				$(#[doc=$unsub_doc])*
151				fn $unsub_name ( $($unsub_p)* ) -> $sub_result <$sub_out $(, $error_unsub)* >;
152			)*
153
154			/// Transform this into an `IoDelegate`, automatically wrapping
155			/// the parameters.
156			fn to_delegate(self) -> $crate::IoDelegate<Self, Self::Metadata>
157				where $($($generics: Send + Sync + 'static + $crate::Serialize + $crate::DeserializeOwned),*)*
158			{
159				let mut del = $crate::IoDelegate::new(self.into());
160				$(
161					build_rpc_trait!(WRAP del =>
162						( $($t)* )
163						fn $m_name ( $($p)* ) -> $result <$out $(, $error_std)* >
164					);
165				)*
166				$(
167					build_rpc_trait!(WRAP del =>
168						pubsub: ( $($pubsub_t)* )
169						subscribe: ( $($sub_t)* )
170						fn $sub_name ( $($sub_p)* );
171						unsubscribe: ( $($unsub_t)* )
172						fn $unsub_name ( $($unsub_p)* ) -> $sub_result <$sub_out $(, $error_unsub)* >;
173					);
174				)*
175				del
176			}
177		}
178	};
179
180	( WRAP $del: expr =>
181		(name = $name: expr $(, alias = [ $( $alias: expr, )+ ])*)
182		fn $method: ident (&self $(, $param: ty)*) -> $result: tt <$out: ty $(, $error: ty)* >
183	) => {
184		$del.add_method($name, move |base, params| {
185			$crate::WrapAsync::wrap_rpc(&(Self::$method as fn(&_ $(, $param)*) -> $result <$out $(, $error)*>), base, params)
186		});
187		$(
188			$(
189				$del.add_alias($alias, $name);
190			)+
191		)*
192	};
193
194	( WRAP $del: expr =>
195		(meta, name = $name: expr $(, alias = [ $( $alias: expr, )+ ])*)
196		fn $method: ident (&self, Self::Metadata $(, $param: ty)*) -> $result: tt <$out: ty $(, $error: ty)* >
197	) => {
198		$del.add_method_with_meta($name, move |base, params, meta| {
199			$crate::WrapMeta::wrap_rpc(&(Self::$method as fn(&_, Self::Metadata $(, $param)*) -> $result <$out $(, $error)* >), base, params, meta)
200		});
201		$(
202			$(
203				$del.add_alias($alias, $name);
204			)+
205		)*
206	};
207
208	( WRAP $del: expr =>
209		pubsub: (name = $name: expr)
210		subscribe: (name = $subscribe: expr $(, alias = [ $( $sub_alias: expr, )+ ])*)
211		fn $sub_method: ident (&self, Self::Metadata $(, $sub_p: ty)+);
212		unsubscribe: (name = $unsubscribe: expr $(, alias = [ $( $unsub_alias: expr, )+ ])*)
213		fn $unsub_method: ident (&self, Self::Metadata $(, $unsub_p: ty)+) -> $result: tt <$out: ty $(, $error_unsub: ty)* >;
214	) => {
215		$del.add_subscription(
216			$name,
217			($subscribe, move |base, params, meta, subscriber| {
218				$crate::WrapSubscribe::wrap_rpc(
219					&(Self::$sub_method as fn(&_, Self::Metadata $(, $sub_p)*)),
220					base,
221					params,
222					meta,
223					subscriber,
224				)
225			}),
226			($unsubscribe, move |base, meta, id| {
227				use $crate::jsonrpc_core::futures::{IntoFuture, Future};
228				Self::$unsub_method(base, meta, id).into_future()
229					.map($crate::to_value)
230					.map_err(Into::into)
231			}),
232		);
233
234		$(
235			$(
236				$del.add_alias($sub_alias, $subscribe);
237			)*
238		)*
239		$(
240			$(
241				$del.add_alias($unsub_alias, $unsubscribe);
242			)*
243		)*
244	};
245}
246
247/// A wrapper type without an implementation of `Deserialize`
248/// which allows a special implementation of `Wrap` for functions
249/// that take a trailing default parameter.
250pub struct Trailing<T>(Option<T>);
251
252impl<T> Into<Option<T>> for Trailing<T> {
253	fn into(self) -> Option<T> {
254		self.0
255	}
256}
257
258impl<T> From<Option<T>> for Trailing<T> {
259	fn from(o: Option<T>) -> Self {
260		Trailing(o)
261	}
262}
263
264impl<T: DeserializeOwned> Trailing<T> {
265	/// Returns a underlying value if present or provided value.
266	pub fn unwrap_or(self, other: T) -> T {
267		self.0.unwrap_or(other)
268	}
269
270	/// Returns an underlying value or computes it if not present.
271	pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
272		self.0.unwrap_or_else(f)
273	}
274}
275
276impl<T: Default + DeserializeOwned> Trailing<T> {
277	/// Returns an underlying value or the default value.
278	pub fn unwrap_or_default(self) -> T {
279		self.0.unwrap_or_default()
280	}
281}
282
283type WrappedFuture<F, OUT, E> = future::MapErr<
284	future::Map<F, fn(OUT) -> Value>,
285	fn(E) -> Error
286>;
287type WrapResult<F, OUT, E> = Either<
288	WrappedFuture<F, OUT, E>,
289	future::FutureResult<Value, Error>,
290>;
291
292fn as_future<F, OUT, E, I>(el: I) -> WrappedFuture<F, OUT, E> where
293	OUT: Serialize,
294	E: Into<Error>,
295	F: Future<Item = OUT, Error = E>,
296	I: IntoFuture<Item = OUT, Error = E, Future = F>
297{
298	el.into_future()
299		.map(to_value as fn(OUT) -> Value)
300		.map_err(Into::into as fn(E) -> Error)
301}
302
303/// Wrapper trait for asynchronous RPC functions.
304pub trait WrapAsync<B> {
305	/// Output type.
306	type Out: IntoFuture<Item = Value, Error = Error>;
307
308	/// Invokes asynchronous RPC method.
309	fn wrap_rpc(&self, base: &B, params: Params) -> Self::Out;
310}
311
312/// Wrapper trait for meta RPC functions.
313pub trait WrapMeta<B, M> {
314	/// Output type.
315	type Out: IntoFuture<Item = Value, Error = Error>;
316	/// Invokes asynchronous RPC method with Metadata.
317	fn wrap_rpc(&self, base: &B, params: Params, meta: M) -> Self::Out;
318}
319
320/// Wrapper trait for subscribe RPC functions.
321pub trait WrapSubscribe<B, M> {
322	/// Invokes subscription.
323	fn wrap_rpc(&self, base: &B, params: Params, meta: M, subscriber: Subscriber);
324}
325
326// special impl for no parameters.
327impl<B, OUT, E, F, I> WrapAsync<B> for fn(&B) -> I where
328	B: Send + Sync + 'static,
329	OUT: Serialize + 'static,
330	E: Into<Error> + 'static,
331	F: Future<Item = OUT, Error = E> + Send + 'static,
332	I: IntoFuture<Item = OUT, Error = E, Future = F>,
333{
334	type Out = WrapResult<F, OUT, E>;
335
336	fn wrap_rpc(&self, base: &B, params: Params) -> Self::Out {
337		match expect_no_params(params) {
338			Ok(()) => Either::A(as_future((self)(base))),
339			Err(e) => Either::B(futures::failed(e)),
340		}
341	}
342}
343
344impl<M, B, OUT, E, F, I> WrapMeta<B, M> for fn(&B, M) -> I where
345	M: Metadata,
346	B: Send + Sync + 'static,
347	OUT: Serialize + 'static,
348	E: Into<Error> + 'static,
349	F: Future<Item = OUT, Error = E> + Send + 'static,
350	I: IntoFuture<Item = OUT, Error = E, Future = F>,
351{
352	type Out = WrapResult<F, OUT, E>;
353
354	fn wrap_rpc(&self, base: &B, params: Params, meta: M) -> Self::Out {
355		match expect_no_params(params) {
356			Ok(()) => Either::A(as_future((self)(base, meta))),
357			Err(e) => Either::B(futures::failed(e)),
358		}
359	}
360}
361
362impl<M, B, OUT> WrapSubscribe<B, M> for fn(&B, M, pubsub::Subscriber<OUT>) where
363	M: PubSubMetadata,
364	B: Send + Sync + 'static,
365	OUT: Serialize,
366{
367	fn wrap_rpc(&self, base: &B, params: Params, meta: M, subscriber: Subscriber) {
368		match expect_no_params(params) {
369			Ok(()) => (self)(base, meta, pubsub::Subscriber::new(subscriber)),
370			Err(e) => {
371				let _ = subscriber.reject(e);
372			},
373		}
374	}
375}
376
377// creates a wrapper implementation which deserializes the parameters,
378// calls the function with concrete type, and serializes the output.
379macro_rules! wrap {
380	($($x: ident),+) => {
381
382		// asynchronous implementation
383		impl <
384			BASE: Send + Sync + 'static,
385			OUT: Serialize + 'static,
386			$($x: DeserializeOwned,)+
387			ERR: Into<Error> + 'static,
388			X: Future<Item = OUT, Error = ERR> + Send + 'static,
389			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
390		> WrapAsync<BASE> for fn(&BASE, $($x,)+ ) -> Z {
391			type Out = WrapResult<X, OUT, ERR>;
392			fn wrap_rpc(&self, base: &BASE, params: Params) -> Self::Out {
393				match params.parse::<($($x,)+)>() {
394					Ok(($($x,)+)) => Either::A(as_future((self)(base, $($x,)+))),
395					Err(e) => Either::B(futures::failed(e)),
396				}
397			}
398		}
399
400		// asynchronous implementation with meta
401		impl <
402			BASE: Send + Sync + 'static,
403			META: Metadata,
404			OUT: Serialize + 'static,
405			$($x: DeserializeOwned,)+
406			ERR: Into<Error> + 'static,
407			X: Future<Item = OUT, Error = ERR> + Send + 'static,
408			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
409		> WrapMeta<BASE, META> for fn(&BASE, META, $($x,)+) -> Z {
410			type Out = WrapResult<X, OUT, ERR>;
411			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META) -> Self::Out {
412				match params.parse::<($($x,)+)>() {
413					Ok(($($x,)+)) => Either::A(as_future((self)(base, meta, $($x,)+))),
414					Err(e) => Either::B(futures::failed(e)),
415				}
416			}
417		}
418
419		// subscribe implementation
420		impl <
421			BASE: Send + Sync + 'static,
422			META: PubSubMetadata,
423			OUT: Serialize,
424			$($x: DeserializeOwned,)+
425		> WrapSubscribe<BASE, META> for fn(&BASE, META, pubsub::Subscriber<OUT>, $($x,)+) {
426			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META, subscriber: Subscriber) {
427				match params.parse::<($($x,)+)>() {
428					Ok(($($x,)+)) => (self)(base, meta, pubsub::Subscriber::new(subscriber), $($x,)+),
429					Err(e) => {
430						let _ = subscriber.reject(e);
431					},
432				}
433			}
434		}
435	}
436}
437
438fn params_len(params: &Params) -> Result<usize> {
439	match *params {
440		Params::Array(ref v) => Ok(v.len()),
441		Params::None => Ok(0),
442		_ => Err(invalid_params("`params` should be an array", "")),
443	}
444}
445
446fn require_len(params: &Params, required: usize) -> Result<usize> {
447	let len = params_len(params)?;
448	if len < required {
449		return Err(invalid_params(&format!("`params` should have at least {} argument(s)", required), ""));
450	}
451	Ok(len)
452}
453
454fn parse_trailing_param<T: DeserializeOwned>(params: Params) -> Result<(Option<T>, )> {
455	let len = try!(params_len(&params));
456	let id = match len {
457		0 => Ok((None,)),
458		1 => params.parse::<(T,)>().map(|(x, )| (Some(x), )),
459		_ => Err(invalid_params("Expecting only one optional parameter.", "")),
460	};
461
462	id
463}
464
465// special impl for no parameters other than block parameter.
466impl<B, OUT, T, E, F, I> WrapAsync<B> for fn(&B, Trailing<T>) -> I where
467	B: Send + Sync + 'static,
468	OUT: Serialize + 'static,
469	T: DeserializeOwned,
470	E: Into<Error> + 'static,
471	F: Future<Item = OUT, Error = E> + Send + 'static,
472	I: IntoFuture<Item = OUT, Error = E, Future = F>,
473{
474	type Out = WrapResult<F, OUT, E>;
475	fn wrap_rpc(&self, base: &B, params: Params) -> Self::Out {
476		let id = parse_trailing_param(params);
477
478		match id {
479			Ok((id,)) => Either::A(as_future((self)(base, Trailing(id)))),
480			Err(e) => Either::B(futures::failed(e)),
481		}
482	}
483}
484
485impl<M, B, OUT, T, E, F, I> WrapMeta<B, M> for fn(&B, M, Trailing<T>) -> I where
486	M: Metadata,
487	B: Send + Sync + 'static,
488	OUT: Serialize + 'static,
489	T: DeserializeOwned,
490	E: Into<Error> + 'static,
491	F: Future<Item = OUT, Error = E> + Send + 'static,
492	I: IntoFuture<Item = OUT, Error = E, Future = F>,
493{
494	type Out = WrapResult<F, OUT, E>;
495	fn wrap_rpc(&self, base: &B, params: Params, meta: M) -> Self::Out {
496		let id = parse_trailing_param(params);
497
498		match id {
499			Ok((id,)) => Either::A(as_future((self)(base, meta, Trailing(id)))),
500			Err(e) => Either::B(futures::failed(e)),
501		}
502	}
503}
504
505impl<M, B, OUT, T> WrapSubscribe<B, M> for fn(&B, M, pubsub::Subscriber<OUT>, Trailing<T>) where
506	M: PubSubMetadata,
507	B: Send + Sync + 'static,
508	OUT: Serialize,
509	T: DeserializeOwned,
510{
511	fn wrap_rpc(&self, base: &B, params: Params, meta: M, subscriber: Subscriber) {
512		let id = parse_trailing_param(params);
513
514		match id {
515			Ok((id,)) => (self)(base, meta, pubsub::Subscriber::new(subscriber), Trailing(id)),
516			Err(e) => {
517				let _ = subscriber.reject(e);
518			},
519		}
520	}
521}
522
523// similar to `wrap!`, but handles a single default trailing parameter
524// accepts an additional argument indicating the number of non-trailing parameters.
525macro_rules! wrap_with_trailing {
526	($num: expr, $($x: ident),+) => {
527		// asynchronous implementation
528		impl <
529			BASE: Send + Sync + 'static,
530			OUT: Serialize + 'static,
531			$($x: DeserializeOwned,)+
532			TRAILING: DeserializeOwned,
533			ERR: Into<Error> + 'static,
534			X: Future<Item = OUT, Error = ERR> + Send + 'static,
535			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
536		> WrapAsync<BASE> for fn(&BASE, $($x,)+ Trailing<TRAILING>) -> Z {
537			type Out = WrapResult<X, OUT, ERR>;
538			fn wrap_rpc(&self, base: &BASE, params: Params) -> Self::Out {
539				let len = match require_len(&params, $num) {
540					Ok(len) => len,
541					Err(e) => return Either::B(futures::failed(e)),
542				};
543
544				let params = match len - $num {
545					0 => params.parse::<($($x,)+)>()
546						.map(|($($x,)+)| ($($x,)+ None)).map_err(Into::into),
547					1 => params.parse::<($($x,)+ TRAILING)>()
548						.map(|($($x,)+ id)| ($($x,)+ Some(id))).map_err(Into::into),
549					_ => Err(invalid_params(&format!("Expected {} or {} parameters.", $num, $num + 1), format!("Got: {}", len))),
550				};
551
552				match params {
553					Ok(($($x,)+ id)) => Either::A(as_future((self)(base, $($x,)+ Trailing(id)))),
554					Err(e) => Either::B(futures::failed(e)),
555				}
556			}
557		}
558
559		// asynchronous implementation with meta
560		impl <
561			BASE: Send + Sync + 'static,
562			META: Metadata,
563			OUT: Serialize + 'static,
564			$($x: DeserializeOwned,)+
565			TRAILING: DeserializeOwned,
566			ERR: Into<Error> + 'static,
567			X: Future<Item = OUT, Error = ERR> + Send + 'static,
568			Z: IntoFuture<Item = OUT, Error = ERR, Future = X>,
569		> WrapMeta<BASE, META> for fn(&BASE, META, $($x,)+ Trailing<TRAILING>) -> Z {
570			type Out = WrapResult<X, OUT, ERR>;
571			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META) -> Self::Out {
572				let len = match require_len(&params, $num) {
573					Ok(len) => len,
574					Err(e) => return Either::B(futures::failed(e)),
575				};
576
577				let params = match len - $num {
578					0 => params.parse::<($($x,)+)>()
579						.map(|($($x,)+)| ($($x,)+ None)).map_err(Into::into),
580					1 => params.parse::<($($x,)+ TRAILING)>()
581						.map(|($($x,)+ id)| ($($x,)+ Some(id))).map_err(Into::into),
582					_ => Err(invalid_params(&format!("Expected {} or {} parameters.", $num, $num + 1), format!("Got: {}", len))),
583				};
584
585				match params {
586					Ok(($($x,)+ id)) => Either::A(as_future((self)(base, meta, $($x,)+ Trailing(id)))),
587					Err(e) => Either::B(futures::failed(e)),
588				}
589			}
590		}
591
592		// subscribe implementation
593		impl <
594			BASE: Send + Sync + 'static,
595			META: PubSubMetadata,
596			OUT: Serialize,
597			$($x: DeserializeOwned,)+
598			TRAILING: DeserializeOwned,
599		> WrapSubscribe<BASE, META> for fn(&BASE, META, pubsub::Subscriber<OUT>, $($x,)+ Trailing<TRAILING>) {
600			fn wrap_rpc(&self, base: &BASE, params: Params, meta: META, subscriber: Subscriber) {
601				let len = match require_len(&params, $num) {
602					Ok(len) => len,
603					Err(e) => {
604						let _ = subscriber.reject(e);
605						return;
606					},
607				};
608
609				let params = match len - $num {
610					0 => params.parse::<($($x,)+)>()
611						.map(|($($x,)+)| ($($x,)+ None)),
612					1 => params.parse::<($($x,)+ TRAILING)>()
613						.map(|($($x,)+ id)| ($($x,)+ Some(id))),
614					_ => {
615						let _ = subscriber.reject(invalid_params(&format!("Expected {} or {} parameters.", $num, $num + 1), format!("Got: {}", len)));
616						return;
617					},
618				};
619
620				match params {
621					Ok(($($x,)+ id)) => (self)(base, meta, pubsub::Subscriber::new(subscriber), $($x,)+ Trailing(id)),
622					Err(e) => {
623						let _ = subscriber.reject(e);
624						return;
625					},
626				}
627			}
628		}
629	}
630}
631
632wrap!(A, B, C, D, E, F);
633wrap!(A, B, C, D, E);
634wrap!(A, B, C, D);
635wrap!(A, B, C);
636wrap!(A, B);
637wrap!(A);
638
639wrap_with_trailing!(6, A, B, C, D, E, F);
640wrap_with_trailing!(5, A, B, C, D, E);
641wrap_with_trailing!(4, A, B, C, D);
642wrap_with_trailing!(3, A, B, C);
643wrap_with_trailing!(2, A, B);
644wrap_with_trailing!(1, A);