use std::{
marker::PhantomData,
task::{Context, Poll},
};
use tower::Service;
use super::OperationShape;
pub trait OperationService<Op, Exts>: Service<Self::Normalized, Response = Op::Output, Error = Op::Error>
where
Op: OperationShape,
{
type Normalized;
fn normalize(input: Op::Input, exts: Exts) -> Self::Normalized;
}
impl<Op, S> OperationService<Op, ()> for S
where
Op: OperationShape,
S: Service<Op::Input, Response = Op::Output, Error = Op::Error>,
{
type Normalized = Op::Input;
fn normalize(input: Op::Input, _exts: ()) -> Self::Normalized {
input
}
}
impl<Op, Ext0, S> OperationService<Op, (Ext0,)> for S
where
Op: OperationShape,
S: Service<(Op::Input, Ext0), Response = Op::Output, Error = Op::Error>,
{
type Normalized = (Op::Input, Ext0);
fn normalize(input: Op::Input, exts: (Ext0,)) -> Self::Normalized {
(input, exts.0)
}
}
impl<Op, Ext0, Ext1, S> OperationService<Op, (Ext0, Ext1)> for S
where
Op: OperationShape,
S: Service<(Op::Input, Ext0, Ext1), Response = Op::Output, Error = Op::Error>,
{
type Normalized = (Op::Input, Ext0, Ext1);
fn normalize(input: Op::Input, exts: (Ext0, Ext1)) -> Self::Normalized {
(input, exts.0, exts.1)
}
}
pub trait OperationServiceExt<Op, Exts>: OperationService<Op, Exts>
where
Op: OperationShape,
{
fn normalize(self) -> Normalize<Op, Self>
where
Self: Sized,
{
Normalize {
inner: self,
_operation: PhantomData,
}
}
}
impl<F, Op, Exts> OperationServiceExt<Op, Exts> for F
where
Op: OperationShape,
F: OperationService<Op, Exts>,
{
}
#[derive(Debug)]
pub struct Normalize<Op, S> {
pub(crate) inner: S,
pub(crate) _operation: PhantomData<Op>,
}
impl<Op, S> Clone for Normalize<Op, S>
where
S: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
_operation: PhantomData,
}
}
}
impl<Op, S, Exts> Service<(Op::Input, Exts)> for Normalize<Op, S>
where
Op: OperationShape,
S: OperationService<Op, Exts>,
{
type Response = S::Response;
type Error = S::Error;
type Future = <S as Service<S::Normalized>>::Future;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, (input, exts): (Op::Input, Exts)) -> Self::Future {
let req = S::normalize(input, exts);
self.inner.call(req)
}
}