use std::fmt::Display;
use std::future::Future;
use std::sync::Arc;
use crate::remote_common::service::{Request, Responder};
pub trait Handler: Send + Sync {
fn call(&self, request: Request, responder: Responder);
}
pub trait SyncHandler: Send + Sync {
type Error: Display;
type Response: AsRef<[u8]> + 'static;
fn call(&self, request: Request) -> Result<Self::Response, Self::Error>;
}
impl<T: SyncHandler> Handler for T {
fn call(&self, request: Request, responder: Responder) {
let result = SyncHandler::call(self, request);
responder.respond(result);
}
}
pub(crate) struct HandlerFn<F, T, E>(pub F)
where
F: Fn(Request) -> Result<T, E> + Send + Sync,
T: AsRef<[u8]> + 'static,
E: Display;
impl<F, T, E> SyncHandler for HandlerFn<F, T, E>
where
F: Fn(Request) -> Result<T, E> + Send + Sync,
T: AsRef<[u8]> + 'static,
E: Display,
{
type Error = E;
type Response = T;
fn call(&self, request: Request) -> Result<Self::Response, Self::Error> {
self.0(request)
}
}
pub(crate) struct BlockingHandlerFn<F, T, E>(pub Arc<F>)
where
F: Fn(Request) -> Result<T, E> + Send + Sync + 'static,
T: AsRef<[u8]> + 'static,
E: Display;
impl<F, T, E> Handler for BlockingHandlerFn<F, T, E>
where
F: Fn(Request) -> Result<T, E> + Send + Sync + 'static,
T: AsRef<[u8]> + 'static,
E: Display,
{
fn call(&self, request: Request, responder: Responder) {
let func = self.0.clone();
tokio::task::spawn_blocking(move || {
let result = (func)(request);
responder.respond(result);
});
}
}
pub(crate) struct AsyncHandlerFn<F, Fut, T, E>(pub Arc<F>)
where
F: Fn(Request) -> Fut + Send + Sync,
Fut: Future<Output = Result<T, E>> + Send + 'static,
T: AsRef<[u8]> + 'static,
E: Display;
impl<F, Fut, T, E> Handler for AsyncHandlerFn<F, Fut, T, E>
where
F: Fn(Request) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<T, E>> + Send,
T: AsRef<[u8]> + 'static,
E: Display + Send,
{
fn call(&self, request: Request, responder: Responder) {
let func = self.0.clone();
tokio::task::spawn(async move {
let result = (func)(request).await;
responder.respond(result);
});
}
}