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