use std::marker::PhantomData;
use std::sync::Arc;
use crate::core::futures::Future;
use crate::core::{self, Metadata, Params, RemoteProcedure, RpcMethod, Value};
use crate::handler::{SubscribeRpcMethod, UnsubscribeRpcMethod};
use crate::subscription::{new_subscription, Subscriber};
use crate::types::{PubSubMetadata, SubscriptionId};
struct DelegateSubscription<T, F> {
delegate: Arc<T>,
closure: F,
}
impl<T, M, F> SubscribeRpcMethod<M> for DelegateSubscription<T, F>
where
M: PubSubMetadata,
F: Fn(&T, Params, M, Subscriber),
T: Send + Sync + 'static,
F: Send + Sync + 'static,
{
fn call(&self, params: Params, meta: M, subscriber: Subscriber) {
let closure = &self.closure;
closure(&self.delegate, params, meta, subscriber)
}
}
impl<M, T, F, I> UnsubscribeRpcMethod<M> for DelegateSubscription<T, F>
where
M: PubSubMetadata,
F: Fn(&T, SubscriptionId, Option<M>) -> I,
I: Future<Output = core::Result<Value>> + Send + 'static,
T: Send + Sync + 'static,
F: Send + Sync + 'static,
{
type Out = I;
fn call(&self, id: SubscriptionId, meta: Option<M>) -> Self::Out {
let closure = &self.closure;
closure(&self.delegate, id, meta)
}
}
pub struct IoDelegate<T, M = ()>
where
T: Send + Sync + 'static,
M: Metadata,
{
inner: core::IoDelegate<T, M>,
delegate: Arc<T>,
_data: PhantomData<M>,
}
impl<T, M> IoDelegate<T, M>
where
T: Send + Sync + 'static,
M: PubSubMetadata,
{
pub fn new(delegate: Arc<T>) -> Self {
IoDelegate {
inner: core::IoDelegate::new(delegate.clone()),
delegate,
_data: PhantomData,
}
}
pub fn add_subscription<Sub, Unsub, I>(&mut self, name: &str, subscribe: (&str, Sub), unsubscribe: (&str, Unsub))
where
Sub: Fn(&T, Params, M, Subscriber),
Sub: Send + Sync + 'static,
Unsub: Fn(&T, SubscriptionId, Option<M>) -> I,
I: Future<Output = core::Result<Value>> + Send + 'static,
Unsub: Send + Sync + 'static,
{
let (sub, unsub) = new_subscription(
name,
DelegateSubscription {
delegate: self.delegate.clone(),
closure: subscribe.1,
},
DelegateSubscription {
delegate: self.delegate.clone(),
closure: unsubscribe.1,
},
);
self.inner
.add_method_with_meta(subscribe.0, move |_, params, meta| sub.call(params, meta));
self.inner
.add_method_with_meta(unsubscribe.0, move |_, params, meta| unsub.call(params, meta));
}
pub fn add_alias(&mut self, from: &str, to: &str) {
self.inner.add_alias(from, to)
}
pub fn add_method<F, I>(&mut self, name: &str, method: F)
where
F: Fn(&T, Params) -> I,
I: Future<Output = core::Result<Value>> + Send + 'static,
F: Send + Sync + 'static,
{
self.inner.add_method(name, method)
}
pub fn add_method_with_meta<F, I>(&mut self, name: &str, method: F)
where
F: Fn(&T, Params, M) -> I,
I: Future<Output = core::Result<Value>> + Send + 'static,
F: Send + Sync + 'static,
{
self.inner.add_method_with_meta(name, method)
}
pub fn add_notification<F>(&mut self, name: &str, notification: F)
where
F: Fn(&T, Params),
F: Send + Sync + 'static,
{
self.inner.add_notification(name, notification)
}
}
impl<T, M> core::IoHandlerExtension<M> for IoDelegate<T, M>
where
T: Send + Sync + 'static,
M: Metadata,
{
fn augment<S: core::Middleware<M>>(self, handler: &mut core::MetaIoHandler<M, S>) {
handler.extend_with(self.inner)
}
}
impl<T, M> IntoIterator for IoDelegate<T, M>
where
T: Send + Sync + 'static,
M: Metadata,
{
type Item = (String, RemoteProcedure<M>);
type IntoIter = <core::IoDelegate<T, M> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}