use crate::{
routes::HandlerArgs, types::Response, HandlerCtx, IntoErrorPayload, ResponsePayload, Route,
RpcRecv, RpcSend,
};
use serde_json::value::RawValue;
use std::{convert::Infallible, future::Future, marker::PhantomData, pin::Pin, task};
use tracing::{trace, Instrument};
#[derive(Debug)]
#[repr(transparent)]
pub struct State<S>(pub S);
#[derive(Debug)]
#[repr(transparent)]
pub struct Params<T>(pub T);
impl<T> From<T> for Params<T> {
fn from(value: T) -> Self {
Self(value)
}
}
#[allow(missing_debug_implementations, unreachable_pub)]
pub struct PhantomState<S>(PhantomData<S>);
#[allow(missing_debug_implementations, unreachable_pub)]
pub struct PhantomParams<T>(PhantomData<T>);
#[cfg_attr(
feature = "pubsub",
doc = "see the [`Listener`] documetnation for more information."
)]
#[cfg_attr(feature = "pubsub", doc = " [`Listener`]: crate::pubsub::Listener")]
pub trait Handler<T, S>: Clone + Send + Sync + Sized + 'static {
type Future: Future<Output = Option<Box<RawValue>>> + Send + 'static;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future;
}
pub(crate) trait HandlerInternal<T, S>: Handler<T, S> {
fn with_state(self, state: S) -> HandlerService<Self, T, S> {
HandlerService::new(self, state)
}
#[allow(private_interfaces)]
fn into_route(self, state: S) -> Route
where
T: Send + 'static,
S: Clone + Send + Sync + 'static,
{
Route::new(self.with_state(state))
}
}
impl<T, S, H> HandlerInternal<T, S> for H where H: Handler<T, S> {}
#[derive(Debug)]
pub(crate) struct HandlerService<H, T, S> {
handler: H,
state: S,
_marker: std::marker::PhantomData<fn() -> T>,
}
impl<H, T, S> Clone for HandlerService<H, T, S>
where
H: Clone,
S: Clone,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
state: self.state.clone(),
_marker: PhantomData,
}
}
}
impl<H, T, S> HandlerService<H, T, S> {
pub(crate) const fn new(handler: H, state: S) -> Self {
Self {
handler,
state,
_marker: PhantomData,
}
}
}
impl<H, T, S> tower::Service<HandlerArgs> for HandlerService<H, T, S>
where
Self: Clone,
H: Handler<T, S>,
T: Send + 'static,
S: Clone + Send + Sync + 'static,
{
type Response = Option<Box<RawValue>>;
type Error = Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Option<Box<RawValue>>, Infallible>> + Send>>;
fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> task::Poll<Result<(), Self::Error>> {
task::Poll::Ready(Ok(()))
}
fn call(&mut self, args: HandlerArgs) -> Self::Future {
let this = self.clone();
Box::pin(async move {
let span = args.span().clone();
Ok(this
.handler
.call_with_state(args, this.state.clone())
.instrument(span)
.await
.inspect(|res| {
trace!(?res, "handler response");
}))
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OutputResult {
_sealed: (),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OutputResponsePayload {
_sealed: (),
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload,), S> for F
where
F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self())
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx), S> for F
where
F: FnOnce(HandlerCtx) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(ctx))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, PhantomParams<Input>), S>
for F
where
F: FnOnce(Input) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(params: Input))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, Params<Input>), S> for F
where
F: FnOnce(Params<Input>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(params: Input))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, PhantomState<S>), S> for F
where
F: FnOnce(S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: RpcSend,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(state))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, State<S>), S> for F
where
F: FnOnce(State<S>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: RpcSend,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(State(state)))
}
}
impl<F, Fut, Input, Payload, ErrData, S>
Handler<(OutputResponsePayload, HandlerCtx, PhantomParams<Input>), S> for F
where
F: FnOnce(HandlerCtx, Input) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, params: Input))
}
}
impl<F, Fut, Input, Payload, ErrData, S>
Handler<(OutputResponsePayload, HandlerCtx, Params<Input>), S> for F
where
F: FnOnce(HandlerCtx, Params<Input>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, params: Input))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, Input, S), S> for F
where
F: FnOnce(Input, S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: RpcSend,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(params: Input, state))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx, PhantomState<S>), S>
for F
where
F: FnOnce(HandlerCtx, S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: RpcSend,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, state))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx, State<S>), S> for F
where
F: FnOnce(HandlerCtx, State<S>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: RpcSend,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, State(state)))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx, Input, S), S>
for F
where
F: FnOnce(HandlerCtx, Input, S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = ResponsePayload<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: RpcSend,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, params: Input, state))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResult,), S> for F
where
F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: IntoErrorPayload,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self())
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResult, HandlerCtx), S> for F
where
F: FnOnce(HandlerCtx) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: IntoErrorPayload,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(ctx))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResult, PhantomParams<Input>), S> for F
where
F: FnOnce(Input) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: IntoErrorPayload,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(params: Input))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResult, Params<Input>), S> for F
where
F: FnOnce(Params<Input>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: IntoErrorPayload,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(params: Input))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResult, PhantomState<S>), S> for F
where
F: FnOnce(S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: IntoErrorPayload,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(state))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResult, State<S>), S> for F
where
F: FnOnce(State<S>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: IntoErrorPayload,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(State(state)))
}
}
impl<F, Fut, Input, Payload, ErrData, S>
Handler<(OutputResult, HandlerCtx, PhantomParams<Input>), S> for F
where
F: FnOnce(HandlerCtx, Input) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: IntoErrorPayload,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, params: Input))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResult, HandlerCtx, Params<Input>), S> for F
where
F: FnOnce(HandlerCtx, Params<Input>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: IntoErrorPayload,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, params: Input))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResult, Input, S), S> for F
where
F: FnOnce(Input, S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: IntoErrorPayload,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(params: Input, state))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResult, HandlerCtx, PhantomState<S>), S> for F
where
F: FnOnce(HandlerCtx, S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: IntoErrorPayload,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, state))
}
}
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResult, HandlerCtx, State<S>), S> for F
where
F: FnOnce(HandlerCtx, State<S>) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Payload: RpcSend,
ErrData: IntoErrorPayload,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, State(state)))
}
}
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResult, HandlerCtx, Input, S), S> for F
where
F: FnOnce(HandlerCtx, Input, S) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Payload, ErrData>> + Send + 'static,
Input: RpcRecv,
Payload: RpcSend,
ErrData: IntoErrorPayload,
S: Send + Sync + 'static,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, state: S) -> Self::Future {
impl_handler_call!(args, self(ctx, params: Input, state))
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{HandlerCtx, ResponsePayload};
#[derive(Clone)]
struct NewType;
async fn resp_ok() -> ResponsePayload<(), ()> {
ResponsePayload(Ok(()))
}
async fn ok() -> Result<(), ()> {
Ok(())
}
#[test]
#[ignore = "compilation_only"]
#[allow(unused_variables)]
fn combination_inference() {
let router: crate::Router<()> = crate::Router::<NewType>::new()
.route("respnse", ok)
.route("respnse, ctx", |_: HandlerCtx| resp_ok())
.route("respnse, params", |_: u16| resp_ok())
.route("respnse, ctx, params", |_: HandlerCtx, _: u16| resp_ok())
.route("respnse, params, state", |_: u8, _: NewType| resp_ok())
.route("respnse, ctx, state", |_: HandlerCtx, _: NewType| resp_ok())
.route(
"respnse, ctx, params, state",
|_: HandlerCtx, _: u8, _: NewType| resp_ok(),
)
.route("result", ok)
.route("result, ctx", |_: HandlerCtx| ok())
.route("result, params", |_: u16| ok())
.route("result, ctx, params", |_: HandlerCtx, _: u16| ok())
.route("result, params, state", |_: u8, _: NewType| ok())
.route("result, ctx, state", |_: HandlerCtx, _: NewType| ok())
.route(
"result, ctx, params, state",
|_: HandlerCtx, _: u8, _: NewType| ok(),
)
.with_state::<u8>(NewType)
.route::<_, (OutputResult, State<u8>)>("no inference error", |State(state)| ok())
.with_state(1u8);
}
}