1use 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
85pub 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 pub fn new(delegate: Arc<T>) -> Self {
102 IoDelegate {
103 delegate,
104 methods: HashMap::new(),
105 }
106 }
107
108 pub fn add_alias(&mut self, from: &str, to: &str) {
111 self.methods.insert(from.into(), RemoteProcedure::Alias(to.into()));
112 }
113
114 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 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 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 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}