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
102pub 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 pub fn new(delegate: Arc<T>) -> Self {
117 IoDelegate {
118 delegate: delegate,
119 methods: HashMap::new(),
120 }
121 }
122
123 pub fn add_alias(&mut self, from: &str, to: &str) {
126 self.methods.insert(from.into(), RemoteProcedure::Alias(to.into()));
127 }
128
129 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 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 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 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}