jsonrpc_core/
delegates.rs

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