jsonrpc_pubsub/
delegates.rs

1use std::marker::PhantomData;
2use std::sync::Arc;
3
4use crate::core::futures::Future;
5use crate::core::{self, Metadata, Params, RemoteProcedure, RpcMethod, Value};
6use crate::handler::{SubscribeRpcMethod, UnsubscribeRpcMethod};
7use crate::subscription::{new_subscription, Subscriber};
8use crate::types::{PubSubMetadata, SubscriptionId};
9
10struct DelegateSubscription<T, F> {
11	delegate: Arc<T>,
12	closure: F,
13}
14
15impl<T, M, F> SubscribeRpcMethod<M> for DelegateSubscription<T, F>
16where
17	M: PubSubMetadata,
18	F: Fn(&T, Params, M, Subscriber),
19	T: Send + Sync + 'static,
20	F: Send + Sync + 'static,
21{
22	fn call(&self, params: Params, meta: M, subscriber: Subscriber) {
23		let closure = &self.closure;
24		closure(&self.delegate, params, meta, subscriber)
25	}
26}
27
28impl<M, T, F, I> UnsubscribeRpcMethod<M> for DelegateSubscription<T, F>
29where
30	M: PubSubMetadata,
31	F: Fn(&T, SubscriptionId, Option<M>) -> I,
32	I: Future<Output = core::Result<Value>> + Send + 'static,
33	T: Send + Sync + 'static,
34	F: Send + Sync + 'static,
35{
36	type Out = I;
37	fn call(&self, id: SubscriptionId, meta: Option<M>) -> Self::Out {
38		let closure = &self.closure;
39		closure(&self.delegate, id, meta)
40	}
41}
42
43/// Wire up rpc subscriptions to `delegate` struct
44pub struct IoDelegate<T, M = ()>
45where
46	T: Send + Sync + 'static,
47	M: Metadata,
48{
49	inner: core::IoDelegate<T, M>,
50	delegate: Arc<T>,
51	_data: PhantomData<M>,
52}
53
54impl<T, M> IoDelegate<T, M>
55where
56	T: Send + Sync + 'static,
57	M: PubSubMetadata,
58{
59	/// Creates new `PubSubIoDelegate`, wrapping the core IoDelegate
60	pub fn new(delegate: Arc<T>) -> Self {
61		IoDelegate {
62			inner: core::IoDelegate::new(delegate.clone()),
63			delegate,
64			_data: PhantomData,
65		}
66	}
67
68	/// Adds subscription to the delegate.
69	pub fn add_subscription<Sub, Unsub, I>(&mut self, name: &str, subscribe: (&str, Sub), unsubscribe: (&str, Unsub))
70	where
71		Sub: Fn(&T, Params, M, Subscriber),
72		Sub: Send + Sync + 'static,
73		Unsub: Fn(&T, SubscriptionId, Option<M>) -> I,
74		I: Future<Output = core::Result<Value>> + Send + 'static,
75		Unsub: Send + Sync + 'static,
76	{
77		let (sub, unsub) = new_subscription(
78			name,
79			DelegateSubscription {
80				delegate: self.delegate.clone(),
81				closure: subscribe.1,
82			},
83			DelegateSubscription {
84				delegate: self.delegate.clone(),
85				closure: unsubscribe.1,
86			},
87		);
88		self.inner
89			.add_method_with_meta(subscribe.0, move |_, params, meta| sub.call(params, meta));
90		self.inner
91			.add_method_with_meta(unsubscribe.0, move |_, params, meta| unsub.call(params, meta));
92	}
93
94	/// Adds an alias to existing method.
95	pub fn add_alias(&mut self, from: &str, to: &str) {
96		self.inner.add_alias(from, to)
97	}
98
99	// TODO [ToDr] Consider sync?
100	/// Adds async method to the delegate.
101	pub fn add_method<F, I>(&mut self, name: &str, method: F)
102	where
103		F: Fn(&T, Params) -> I,
104		I: Future<Output = core::Result<Value>> + Send + 'static,
105		F: Send + Sync + 'static,
106	{
107		self.inner.add_method(name, method)
108	}
109
110	/// Adds async method with metadata to the delegate.
111	pub fn add_method_with_meta<F, I>(&mut self, name: &str, method: F)
112	where
113		F: Fn(&T, Params, M) -> I,
114		I: Future<Output = core::Result<Value>> + Send + 'static,
115		F: Send + Sync + 'static,
116	{
117		self.inner.add_method_with_meta(name, method)
118	}
119
120	/// Adds notification to the delegate.
121	pub fn add_notification<F>(&mut self, name: &str, notification: F)
122	where
123		F: Fn(&T, Params),
124		F: Send + Sync + 'static,
125	{
126		self.inner.add_notification(name, notification)
127	}
128}
129
130impl<T, M> core::IoHandlerExtension<M> for IoDelegate<T, M>
131where
132	T: Send + Sync + 'static,
133	M: Metadata,
134{
135	fn augment<S: core::Middleware<M>>(self, handler: &mut core::MetaIoHandler<M, S>) {
136		handler.extend_with(self.inner)
137	}
138}
139
140impl<T, M> IntoIterator for IoDelegate<T, M>
141where
142	T: Send + Sync + 'static,
143	M: Metadata,
144{
145	type Item = (String, RemoteProcedure<M>);
146	type IntoIter = <core::IoDelegate<T, M> as IntoIterator>::IntoIter;
147
148	fn into_iter(self) -> Self::IntoIter {
149		self.inner.into_iter()
150	}
151}