use std::{future::Future, sync::Arc};
use crate::{
csp::comm::RxChan,
recoverable::Recoverable,
utils::{
captures::Captures,
fn_n::{Fn1Result, Fn1ResultAsync},
},
};
with_rt! {
use crate::{
csp::{comm::OutputTx, shutdown::ShutdownRx},
handling::server::ServeOptions,
};
}
use super::{
erased::{ErasedHandler, TypeErasedHandler},
map::{Map, MapAsync},
or::Or,
pipe::Pipe,
provide::Provide,
seq::{Seq, SeqHandler},
server::Server,
};
pub trait Handler<T, E>: Send + Sync {
type Output;
fn handle<'a>(
&'a self,
request: T,
) -> impl Future<Output = Result<Self::Output, E>> + Send + Captures<(&'a Self, T)>;
fn after<C>(self, current: C) -> Seq<C, Self>
where
C: SeqHandler<T, E, Self>,
Self: Sized,
{
Seq::new(current, self)
}
fn or<R, EE>(self, rhs: R) -> Or<Self, R>
where
Self: Sized + Handler<T, Recoverable<T, EE>>,
R: Handler<T, EE>,
{
Or::new(self, rhs)
}
#[cfg(feature = "tokio")]
fn serve<X, OTx, SRx>(
self,
rx: X,
options: ServeOptions<OTx, SRx>,
) -> impl Future<Output = Result<(), E>> + Send
where
T: Send + 'static,
E: Send + 'static,
Self::Output: Send,
Self: Sized + Clone + 'static,
X: RxChan<T, E, Self::Output>,
X::Responder: Send + 'static,
OTx: OutputTx<Self::Output, E> + 'static,
SRx: ShutdownRx<E>,
{
async move {
let mut server = self.into_server(rx);
server.serve(options).await
}
}
fn into_server<X>(self, rx: X) -> Server<Self, X>
where
Self: Sized,
X: RxChan<T, E, Self::Output>,
{
Server { handler: self, rx }
}
fn provide<Env, F>(self, env: Env, f: F) -> Provide<Env, F, Self>
where
Self: Sized,
{
Provide {
env,
f,
handler: self,
}
}
fn map_async<K, F>(self, f: F) -> MapAsync<F, Self>
where
Self: Sized,
F: Fn1ResultAsync<K, E, Ok = T>,
{
MapAsync { handler: self, f }
}
fn map<K, F>(self, f: F) -> Map<F, Self>
where
Self: Sized,
F: Fn1Result<K, E, SOut = T>,
{
Map { f, handler: self }
}
fn pipe<Dst>(self, dst: Dst) -> Pipe<Self, Dst>
where
Self: Sized,
Dst: Handler<Self::Output, E>,
{
Pipe::new(self, dst)
}
fn share(self) -> Arc<Self>
where
Self: Sized,
{
Arc::new(self)
}
fn erase(self) -> ErasedHandler<T, Self::Output, E>
where
T: Send + 'static,
Self: Sized + 'static,
{
Box::new(TypeErasedHandler(self))
}
}
impl<T, E, O, F, Fut> Handler<T, E> for F
where
F: Send + Sync + Fn(T) -> Fut,
Fut: Future<Output = Result<O, E>> + Send,
{
type Output = O;
fn handle<'a>(
&'a self,
request: T,
) -> impl Future<Output = Result<Self::Output, E>> + Send + Captures<(&'a Self, T)> {
self(request)
}
}
impl<T, E, H> Handler<T, E> for Arc<H>
where
H: Handler<T, E>,
{
type Output = H::Output;
fn handle<'a>(
&'a self,
request: T,
) -> impl Future<Output = Result<Self::Output, E>> + Send + Captures<(&'a Self, T)> {
Arc::as_ref(self).handle(request)
}
}