use crate::{
routes::HandlerArgs, types::Response, HandlerCtx, ResponsePayload, Route, RpcRecv, RpcSend,
};
use serde_json::value::RawValue;
use std::{convert::Infallible, future::Future, marker::PhantomData, pin::Pin, task};
use tracing::{debug_span, enabled, trace, Instrument, Level};
macro_rules! convert_result {
($res:expr) => {{
match $res {
Ok(val) => ResponsePayload::Success(val),
Err(err) => ResponsePayload::internal_error_with_obj(err),
}
}};
}
#[derive(Debug)]
#[repr(transparent)]
pub struct State<S>(pub S);
#[derive(Debug)]
#[repr(transparent)]
pub struct Params<T>(pub T);
#[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 notifications_enabled = args.ctx.notifications_enabled();
let span = debug_span!(
"HandlerService::call",
notifications_enabled,
params = tracing::field::Empty
);
if enabled!(Level::TRACE) {
span.record("params", args.req.params());
}
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 {
let id = args.req.id_owned();
Box::pin(async move {
let payload = self().await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
let id = args.req.id_owned();
let ctx = args.ctx;
Box::pin(async move {
let payload = self(ctx).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
let HandlerArgs { req, .. } = args;
Box::pin(async move {
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
let payload = self(params).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
let HandlerArgs { req, .. } = args;
Box::pin(async move {
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
let payload = self(Params(params)).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
let id = args.req.id_owned();
Box::pin(async move {
let payload = self(state).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
let id = args.req.id_owned();
Box::pin(async move {
let payload = self(State(state)).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = self(ctx, params).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = self(ctx, Params(params)).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
Box::pin(async move {
let HandlerArgs { req, .. } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = self(params, state).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
drop(req);
let payload = self(ctx, state).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
drop(req);
let payload = self(ctx, State(state)).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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 {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = self(ctx, params, state).await;
Response::maybe(id.as_deref(), &payload)
})
}
}
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: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
let id = args.req.id_owned();
drop(args);
Box::pin(async move {
let payload = self().await;
Response::maybe(id.as_deref(), &convert_result!(payload))
})
}
}
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: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
drop(req);
Box::pin(async move {
let payload = convert_result!(self(ctx).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
Box::pin(async move {
let HandlerArgs { req, .. } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = convert_result!(self(params).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
Box::pin(async move {
let HandlerArgs { req, .. } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = convert_result!(self(Params(params)).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: 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 {
let id = args.req.id_owned();
Box::pin(async move {
let payload = convert_result!(self(state).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: 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 {
let id = args.req.id_owned();
Box::pin(async move {
let payload = convert_result!(self(State(state)).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = convert_result!(self(ctx, params).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: RpcSend,
{
type Future = Pin<Box<dyn Future<Output = Option<Box<RawValue>>> + Send>>;
fn call_with_state(self, args: HandlerArgs, _state: S) -> Self::Future {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = convert_result!(self(ctx, Params(params)).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: 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 {
Box::pin(async move {
let HandlerArgs { req, .. } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = convert_result!(self(params, state).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: 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 {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
drop(req);
Box::pin(async move {
let payload = convert_result!(self(ctx, state).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: 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 {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
drop(req);
Box::pin(async move {
let payload = convert_result!(self(ctx, State(state)).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
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: 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 {
Box::pin(async move {
let HandlerArgs { ctx, req } = args;
let id = req.id_owned();
let Ok(params) = req.deser_params() else {
return Response::maybe_invalid_params(id.as_deref());
};
drop(req);
let payload = convert_result!(self(ctx, params, state).await);
Response::maybe(id.as_deref(), &payload)
})
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{HandlerCtx, ResponsePayload};
#[derive(Clone)]
struct NewType;
async fn resp_ok() -> ResponsePayload<(), ()> {
ResponsePayload::Success(())
}
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);
}
}