jsonrpc_macros/
delegates.rs

1use std::sync::Arc;
2use std::collections::HashMap;
3
4use jsonrpc_core::{Params, Value, Error};
5use jsonrpc_core::{BoxFuture, Metadata, RemoteProcedure, RpcMethod, RpcNotification};
6use jsonrpc_core::futures::IntoFuture;
7
8use jsonrpc_pubsub::{self, SubscriptionId, Subscriber, PubSubMetadata};
9
10struct DelegateAsyncMethod<T, F> {
11	delegate: Arc<T>,
12	closure: F,
13}
14
15impl<T, M, F, I> RpcMethod<M> for DelegateAsyncMethod<T, F> where
16	M: Metadata,
17	F: Fn(&T, Params) -> I,
18	I: IntoFuture<Item = Value, Error = Error>,
19	T: Send + Sync + 'static,
20	F: Send + Sync + 'static,
21	I::Future: Send + 'static,
22{
23	fn call(&self, params: Params, _meta: M) -> BoxFuture<Value> {
24		let closure = &self.closure;
25		Box::new(closure(&self.delegate, params).into_future())
26	}
27}
28
29struct DelegateMethodWithMeta<T, F> {
30	delegate: Arc<T>,
31	closure: F,
32}
33
34impl<T, M, F, I> RpcMethod<M> for DelegateMethodWithMeta<T, F> where
35	M: Metadata,
36	F: Fn(&T, Params, M) -> I,
37	I: IntoFuture<Item = Value, Error = Error>,
38	T: Send + Sync + 'static,
39	F: Send + Sync + 'static,
40	I::Future: Send + 'static,
41{
42	fn call(&self, params: Params, meta: M) -> BoxFuture<Value> {
43		let closure = &self.closure;
44		Box::new(closure(&self.delegate, params, meta).into_future())
45	}
46}
47
48struct DelegateNotification<T, F> {
49	delegate: Arc<T>,
50	closure: F,
51}
52
53impl<T, M, F> RpcNotification<M> for DelegateNotification<T, F> where
54	F: Fn(&T, Params) + 'static,
55	F: Send + Sync + 'static,
56	T: Send + Sync + 'static,
57	M: Metadata,
58{
59	fn execute(&self, params: Params, _meta: M) {
60		let closure = &self.closure;
61		closure(&self.delegate, params)
62	}
63}
64
65struct DelegateSubscribe<T, F> {
66	delegate: Arc<T>,
67	closure: F,
68}
69
70impl<T, M, F> jsonrpc_pubsub::SubscribeRpcMethod<M> for DelegateSubscribe<T, F> where
71	M: PubSubMetadata,
72	F: Fn(&T, Params, M, Subscriber),
73	T: Send + Sync + 'static,
74	F: Send + Sync + 'static,
75{
76	fn call(&self, params: Params, meta: M, subscriber: Subscriber) {
77		let closure = &self.closure;
78		closure(&self.delegate, params, meta, subscriber)
79	}
80}
81
82struct DelegateUnsubscribe<T, F> {
83	delegate: Arc<T>,
84	closure: F,
85}
86
87impl<M, T, F, I> jsonrpc_pubsub::UnsubscribeRpcMethod<M> for DelegateUnsubscribe<T, F> where
88	M: PubSubMetadata,
89	F: Fn(&T, SubscriptionId, Option<M>) -> I,
90	I: IntoFuture<Item = Value, Error = Error>,
91	T: Send + Sync + 'static,
92	F: Send + Sync + 'static,
93	I::Future: Send + 'static,
94{
95	type Out = I::Future;
96	fn call(&self, id: SubscriptionId, meta: Option<M>) -> Self::Out {
97		let closure = &self.closure;
98		closure(&self.delegate, id, meta).into_future()
99	}
100}
101
102/// A set of RPC methods and notifications tied to single `delegate` struct.
103pub struct IoDelegate<T, M = ()> where
104	T: Send + Sync + 'static,
105	M: Metadata,
106{
107	delegate: Arc<T>,
108	methods: HashMap<String, RemoteProcedure<M>>,
109}
110
111impl<T, M> IoDelegate<T, M> where
112	T: Send + Sync + 'static,
113	M: Metadata,
114{
115	/// Creates new `IoDelegate`
116	pub fn new(delegate: Arc<T>) -> Self {
117		IoDelegate {
118			delegate: delegate,
119			methods: HashMap::new(),
120		}
121	}
122
123	/// Adds an alias to existing method.
124	/// NOTE: Aliases are not transitive, i.e. you cannot create alias to an alias.
125	pub fn add_alias(&mut self, from: &str, to: &str) {
126		self.methods.insert(from.into(), RemoteProcedure::Alias(to.into()));
127	}
128
129	/// Adds async method to the delegate.
130	pub fn add_method<F, I>(&mut self, name: &str, method: F) where
131		F: Fn(&T, Params) -> I,
132		I: IntoFuture<Item = Value, Error = Error>,
133		F: Send + Sync + 'static,
134		I::Future: Send + 'static,
135	{
136		self.methods.insert(name.into(), RemoteProcedure::Method(Arc::new(
137			DelegateAsyncMethod {
138				delegate: self.delegate.clone(),
139				closure: method,
140			}
141		)));
142	}
143
144	/// Adds async method with metadata to the delegate.
145	pub fn add_method_with_meta<F, I>(&mut self, name: &str, method: F) where
146		F: Fn(&T, Params, M) -> I,
147		I: IntoFuture<Item = Value, Error = Error>,
148		F: Send + Sync + 'static,
149		I::Future: Send + 'static,
150	{
151		self.methods.insert(name.into(), RemoteProcedure::Method(Arc::new(
152			DelegateMethodWithMeta {
153				delegate: self.delegate.clone(),
154				closure: method,
155			}
156		)));
157	}
158
159	/// Adds notification to the delegate.
160	pub fn add_notification<F>(&mut self, name: &str, notification: F) where
161		F: Fn(&T, Params),
162		F: Send + Sync + 'static,
163	{
164		self.methods.insert(name.into(), RemoteProcedure::Notification(Arc::new(
165			DelegateNotification {
166				delegate: self.delegate.clone(),
167				closure: notification,
168			}
169		)));
170	}
171}
172
173impl<T, M> IoDelegate<T, M> where
174	T: Send + Sync + 'static,
175	M: PubSubMetadata,
176{
177	/// Adds subscription to the delegate.
178	pub fn add_subscription<Sub, Unsub, I>(
179		&mut self,
180		name: &str,
181		subscribe: (&str, Sub),
182		unsubscribe: (&str, Unsub),
183	) where
184		Sub: Fn(&T, Params, M, Subscriber),
185		Sub: Send + Sync + 'static,
186		Unsub: Fn(&T, SubscriptionId, Option<M>) -> I,
187		I: IntoFuture<Item = Value, Error = Error>,
188		Unsub: Send + Sync + 'static,
189		I::Future: Send + 'static,
190	{
191		let (sub, unsub) = jsonrpc_pubsub::new_subscription(
192			name,
193			DelegateSubscribe {
194				delegate: self.delegate.clone(),
195				closure: subscribe.1,
196			},
197			DelegateUnsubscribe {
198				delegate: self.delegate.clone(),
199				closure: unsubscribe.1,
200			}
201		);
202		self.add_method_with_meta(subscribe.0, move |_, params, meta| sub.call(params, meta));
203		self.add_method_with_meta(unsubscribe.0, move |_, params, meta| unsub.call(params, meta));
204	}
205}
206
207impl<T, M> Into<HashMap<String, RemoteProcedure<M>>> for IoDelegate<T, M> where
208	T: Send + Sync + 'static,
209	M: Metadata,
210{
211	fn into(self) -> HashMap<String, RemoteProcedure<M>> {
212		self.methods
213	}
214}