//! Delegate rpc calls use std::collections::HashMap; use std::future::Future; use std::sync::Arc; use crate::calls::{Metadata, RemoteProcedure, RpcMethod, RpcNotification}; use crate::types::{Error, Params, Value}; use crate::BoxFuture; struct DelegateAsyncMethod { delegate: Arc, closure: F, } impl RpcMethod for DelegateAsyncMethod where M: Metadata, F: Fn(&T, Params) -> I, I: Future> + Send + 'static, T: Send + Sync + 'static, F: Send + Sync + 'static, { fn call(&self, params: Params, _meta: M) -> BoxFuture> { let closure = &self.closure; Box::pin(closure(&self.delegate, params)) } } struct DelegateMethodWithMeta { delegate: Arc, closure: F, } impl RpcMethod for DelegateMethodWithMeta where M: Metadata, F: Fn(&T, Params, M) -> I, I: Future> + Send + 'static, T: Send + Sync + 'static, F: Send + Sync + 'static, { fn call(&self, params: Params, meta: M) -> BoxFuture> { let closure = &self.closure; Box::pin(closure(&self.delegate, params, meta)) } } struct DelegateNotification { delegate: Arc, closure: F, } impl RpcNotification for DelegateNotification where M: Metadata, F: Fn(&T, Params) + 'static, F: Send + Sync + 'static, T: Send + Sync + 'static, { fn execute(&self, params: Params, _meta: M) { let closure = &self.closure; closure(&self.delegate, params) } } struct DelegateNotificationWithMeta { delegate: Arc, closure: F, } impl RpcNotification for DelegateNotificationWithMeta where M: Metadata, F: Fn(&T, Params, M) + 'static, F: Send + Sync + 'static, T: Send + Sync + 'static, { fn execute(&self, params: Params, meta: M) { let closure = &self.closure; closure(&self.delegate, params, meta) } } /// A set of RPC methods and notifications tied to single `delegate` struct. pub struct IoDelegate where T: Send + Sync + 'static, M: Metadata, { delegate: Arc, methods: HashMap>, } impl IoDelegate where T: Send + Sync + 'static, M: Metadata, { /// Creates new `IoDelegate` pub fn new(delegate: Arc) -> Self { IoDelegate { delegate, methods: HashMap::new(), } } /// Adds an alias to existing method. /// NOTE: Aliases are not transitive, i.e. you cannot create alias to an alias. pub fn add_alias(&mut self, from: &str, to: &str) { self.methods.insert(from.into(), RemoteProcedure::Alias(to.into())); } /// Adds async method to the delegate. pub fn add_method(&mut self, name: &str, method: F) where F: Fn(&T, Params) -> I, I: Future> + Send + 'static, F: Send + Sync + 'static, { self.methods.insert( name.into(), RemoteProcedure::Method(Arc::new(DelegateAsyncMethod { delegate: self.delegate.clone(), closure: method, })), ); } /// Adds async method with metadata to the delegate. pub fn add_method_with_meta(&mut self, name: &str, method: F) where F: Fn(&T, Params, M) -> I, I: Future> + Send + 'static, F: Send + Sync + 'static, { self.methods.insert( name.into(), RemoteProcedure::Method(Arc::new(DelegateMethodWithMeta { delegate: self.delegate.clone(), closure: method, })), ); } /// Adds notification to the delegate. pub fn add_notification(&mut self, name: &str, notification: F) where F: Fn(&T, Params), F: Send + Sync + 'static, { self.methods.insert( name.into(), RemoteProcedure::Notification(Arc::new(DelegateNotification { delegate: self.delegate.clone(), closure: notification, })), ); } /// Adds notification with metadata to the delegate. pub fn add_notification_with_meta(&mut self, name: &str, notification: F) where F: Fn(&T, Params, M), F: Send + Sync + 'static, { self.methods.insert( name.into(), RemoteProcedure::Notification(Arc::new(DelegateNotificationWithMeta { delegate: self.delegate.clone(), closure: notification, })), ); } } impl crate::io::IoHandlerExtension for IoDelegate where T: Send + Sync + 'static, M: Metadata, { fn augment>(self, handler: &mut crate::MetaIoHandler) { handler.extend_with(self.methods) } } impl IntoIterator for IoDelegate where T: Send + Sync + 'static, M: Metadata, { type Item = (String, RemoteProcedure); type IntoIter = std::collections::hash_map::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.methods.into_iter() } }