phase 3/3

This commit is contained in:
Rob Ede 2020-12-25 00:54:23 +00:00
parent bff68c3f76
commit 0d19050269
No known key found for this signature in database
GPG Key ID: C2A3B36E841A91E6
12 changed files with 441 additions and 437 deletions

View File

@ -121,6 +121,7 @@ where
>, >,
{ {
inner: Rc<(A, B)>, inner: Rc<(A, B)>,
_phantom: PhantomData<Req>,
} }
impl<A, B, Req> AndThenServiceFactory<A, B, Req> impl<A, B, Req> AndThenServiceFactory<A, B, Req>
@ -138,6 +139,7 @@ where
pub(crate) fn new(a: A, b: B) -> Self { pub(crate) fn new(a: A, b: B) -> Self {
Self { Self {
inner: Rc::new((a, b)), inner: Rc::new((a, b)),
_phantom: PhantomData,
} }
} }
} }
@ -184,6 +186,7 @@ where
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
inner: self.inner.clone(), inner: self.inner.clone(),
_phantom: PhantomData,
} }
} }
} }

View File

@ -8,65 +8,67 @@ use std::task::{Context, Poll};
use crate::{Service, ServiceFactory}; use crate::{Service, ServiceFactory};
/// `Apply` service combinator /// `Apply` service combinator
pub(crate) struct AndThenApplyFn<A, B, F, Fut, Req, Res, Err> pub(crate) struct AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
where where
A: Service<Req>, S1: Service<Req>,
B: Service<Result<A::Response, A::Error>>, S2: Service<In>,
F: FnMut(A::Response, &mut B) -> Fut, F: FnMut(S1::Response, &mut S2) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<S1::Error> + From<S2::Error>,
{ {
srv: Rc<RefCell<(A, B, F)>>, svc: Rc<RefCell<(S1, S2, F)>>,
r: PhantomData<(Fut, Res, Err)>, _phantom: PhantomData<(Fut, Req, In, Res, Err)>,
} }
impl<A, B, F, Fut, Req, Res, Err> AndThenApplyFn<A, B, F, Fut, Req, Res, Err> impl<S1, S2, F, Fut, Req, In, Res, Err> AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
where where
A: Service<Req>, S1: Service<Req>,
B: Service<Result<A::Response, A::Error>>, S2: Service<In>,
F: FnMut(A::Response, &mut B) -> Fut, F: FnMut(S1::Response, &mut S2) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<S1::Error> + From<S2::Error>,
{ {
/// Create new `Apply` combinator /// Create new `Apply` combinator
pub(crate) fn new(a: A, b: B, f: F) -> Self { pub(crate) fn new(a: S1, b: S2, wrap_fn: F) -> Self {
Self { Self {
srv: Rc::new(RefCell::new((a, b, f))), svc: Rc::new(RefCell::new((a, b, wrap_fn))),
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<A, B, F, Fut, Req, Res, Err> Clone for AndThenApplyFn<A, B, F, Fut, Req, Res, Err> impl<S1, S2, F, Fut, Req, In, Res, Err> Clone
for AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
where where
A: Service<Req>, S1: Service<Req>,
B: Service<Result<A::Response, A::Error>>, S2: Service<In>,
F: FnMut(A::Response, &mut B) -> Fut, F: FnMut(S1::Response, &mut S2) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<S1::Error> + From<S2::Error>,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
AndThenApplyFn { AndThenApplyFn {
srv: self.srv.clone(), svc: self.svc.clone(),
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<A, B, F, Fut, Req, Res, Err> Service<Req> for AndThenApplyFn<A, B, F, Fut, Req, Res, Err> impl<S1, S2, F, Fut, Req, In, Res, Err> Service<Req>
for AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
where where
A: Service<Req>, S1: Service<Req>,
B: Service<Result<A::Response, A::Error>>, S2: Service<In>,
F: FnMut(A::Response, &mut B) -> Fut, F: FnMut(S1::Response, &mut S2) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<S1::Error> + From<S2::Error>,
{ {
type Response = Res; type Response = Res;
type Error = Err; type Error = Err;
type Future = AndThenApplyFnFuture<A, B, F, Fut, Req, Res, Err>; type Future = AndThenApplyFnFuture<S1, S2, F, Fut, Req, In, Res, Err>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let mut inner = self.srv.borrow_mut(); let mut inner = self.svc.borrow_mut();
let not_ready = inner.0.poll_ready(cx)?.is_pending(); let not_ready = inner.0.poll_ready(cx)?.is_pending();
if inner.1.poll_ready(cx)?.is_pending() || not_ready { if inner.1.poll_ready(cx)?.is_pending() || not_ready {
Poll::Pending Poll::Pending
@ -76,49 +78,48 @@ where
} }
fn call(&mut self, req: Req) -> Self::Future { fn call(&mut self, req: Req) -> Self::Future {
let fut = self.srv.borrow_mut().0.call(req); let fut = self.svc.borrow_mut().0.call(req);
AndThenApplyFnFuture { AndThenApplyFnFuture {
state: State::A(fut, Some(self.srv.clone())), state: State::A(fut, Some(self.svc.clone())),
} }
} }
} }
#[pin_project::pin_project] #[pin_project::pin_project]
pub(crate) struct AndThenApplyFnFuture<A, B, F, Fut, Req, Res, Err> pub(crate) struct AndThenApplyFnFuture<S1, S2, F, Fut, Req, In, Res, Err>
where where
A: Service<Req>, S1: Service<Req>,
B: Service<Result<A::Response, A::Error>>, S2: Service<In>,
F: FnMut(A::Response, &mut B) -> Fut, F: FnMut(S1::Response, &mut S2) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error>, Err: From<S1::Error> + From<S2::Error>,
Err: From<B::Error>,
{ {
#[pin] #[pin]
state: State<A, B, F, Fut, Req, Res, Err>, state: State<S1, S2, F, Fut, Req, In, Res, Err>,
} }
#[pin_project::pin_project(project = StateProj)] #[pin_project::pin_project(project = StateProj)]
enum State<A, B, F, Fut, Req, Res, Err> enum State<S1, S2, F, Fut, Req, In, Res, Err>
where where
A: Service<Req>, S1: Service<Req>,
B: Service<Result<A::Response, A::Error>>, S2: Service<In>,
F: FnMut(A::Response, &mut B) -> Fut, F: FnMut(S1::Response, &mut S2) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error>, Err: From<S1::Error> + From<S2::Error>,
Err: From<B::Error>,
{ {
A(#[pin] A::Future, Option<Rc<RefCell<(A, B, F)>>>), A(#[pin] S1::Future, Option<Rc<RefCell<(S1, S2, F)>>>),
B(#[pin] Fut), B(#[pin] Fut),
Empty, Empty(PhantomData<In>),
} }
impl<A, B, F, Fut, Req, Res, Err> Future for AndThenApplyFnFuture<A, B, F, Fut, Req, Res, Err> impl<S1, S2, F, Fut, Req, In, Res, Err> Future
for AndThenApplyFnFuture<S1, S2, F, Fut, Req, In, Res, Err>
where where
A: Service<Req>, S1: Service<Req>,
B: Service<Result<A::Response, A::Error>>, S2: Service<In>,
F: FnMut(A::Response, &mut B) -> Fut, F: FnMut(S1::Response, &mut S2) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<S1::Error> + From<S2::Error>,
{ {
type Output = Result<Res, Err>; type Output = Result<Res, Err>;
@ -128,8 +129,8 @@ where
match this.state.as_mut().project() { match this.state.as_mut().project() {
StateProj::A(fut, b) => match fut.poll(cx)? { StateProj::A(fut, b) => match fut.poll(cx)? {
Poll::Ready(res) => { Poll::Ready(res) => {
let b = b.take().unwrap(); let b = Option::take(b).unwrap();
this.state.set(State::Empty); this.state.set(State::Empty(PhantomData));
let (_, b, f) = &mut *b.borrow_mut(); let (_, b, f) = &mut *b.borrow_mut();
let fut = f(res, b); let fut = f(res, b);
this.state.set(State::B(fut)); this.state.set(State::B(fut));
@ -138,10 +139,10 @@ where
Poll::Pending => Poll::Pending, Poll::Pending => Poll::Pending,
}, },
StateProj::B(fut) => fut.poll(cx).map(|r| { StateProj::B(fut) => fut.poll(cx).map(|r| {
this.state.set(State::Empty); this.state.set(State::Empty(PhantomData));
r r
}), }),
StateProj::Empty => { StateProj::Empty(_) => {
panic!("future must not be polled after it returned `Poll::Ready`") panic!("future must not be polled after it returned `Poll::Ready`")
} }
} }
@ -149,136 +150,127 @@ where
} }
/// `AndThenApplyFn` service factory /// `AndThenApplyFn` service factory
pub(crate) struct AndThenApplyFnFactory<A, B, F, Req, Fut, Res, Err> { pub(crate) struct AndThenApplyFnFactory<SF1, SF2, F, Fut, Req, In, Res, Err> {
srv: Rc<(A, B, F)>, srv: Rc<(SF1, SF2, F)>,
r: PhantomData<(Req, Fut, Res, Err)>, _phantom: PhantomData<(Fut, Req, In, Res, Err)>,
} }
impl<A, B, F, Fut, Req, Res, Err> AndThenApplyFnFactory<A, B, F, Req, Fut, Res, Err> impl<SF1, SF2, F, Fut, Req, In, Res, Err>
AndThenApplyFnFactory<SF1, SF2, F, Fut, Req, In, Res, Err>
where where
A: ServiceFactory<Req>, SF1: ServiceFactory<Req>,
B: ServiceFactory< SF2: ServiceFactory<In, Config = SF1::Config, InitError = SF1::InitError>,
Result<A::Response, A::Error>, F: FnMut(SF1::Response, &mut SF2::Service) -> Fut + Clone,
Config = A::Config,
InitError = A::InitError,
>,
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<SF1::Error> + From<SF2::Error>,
{ {
/// Create new `ApplyNewService` new service instance /// Create new `ApplyNewService` new service instance
pub(crate) fn new(a: A, b: B, f: F) -> Self { pub(crate) fn new(a: SF1, b: SF2, wrap_fn: F) -> Self {
Self { Self {
srv: Rc::new((a, b, f)), srv: Rc::new((a, b, wrap_fn)),
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<A, B, F, Req, Fut, Res, Err> Clone for AndThenApplyFnFactory<A, B, F, Req, Fut, Res, Err> { impl<SF1, SF2, F, Fut, Req, In, Res, Err> Clone
for AndThenApplyFnFactory<SF1, SF2, F, Fut, Req, In, Res, Err>
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
srv: self.srv.clone(), srv: self.srv.clone(),
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<A, B, F, Req, Fut, Res, Err> ServiceFactory<Req> impl<SF1, SF2, F, Fut, Req, In, Res, Err> ServiceFactory<Req>
for AndThenApplyFnFactory<A, B, F, Req, Fut, Res, Err> for AndThenApplyFnFactory<SF1, SF2, F, Fut, Req, In, Res, Err>
where where
A: ServiceFactory<Req>, SF1: ServiceFactory<Req>,
A::Config: Clone, SF1::Config: Clone,
B: ServiceFactory< SF2: ServiceFactory<In, Config = SF1::Config, InitError = SF1::InitError>,
Result<A::Response, A::Error>, F: FnMut(SF1::Response, &mut SF2::Service) -> Fut + Clone,
Config = A::Config,
InitError = A::InitError,
>,
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<SF1::Error> + From<SF2::Error>,
{ {
type Response = Res; type Response = Res;
type Error = Err; type Error = Err;
type Service = AndThenApplyFn<A::Service, B::Service, F, Fut, Req, Res, Err>; type Service = AndThenApplyFn<SF1::Service, SF2::Service, F, Fut, Req, In, Res, Err>;
type Config = A::Config; type Config = SF1::Config;
type InitError = A::InitError; type InitError = SF1::InitError;
type Future = AndThenApplyFnFactoryResponse<A, B, F, Fut, Req, Res, Err>; type Future = AndThenApplyFnFactoryResponse<SF1, SF2, F, Fut, Req, In, Res, Err>;
fn new_service(&self, cfg: A::Config) -> Self::Future { fn new_service(&self, cfg: SF1::Config) -> Self::Future {
let srv = &*self.srv; let srv = &*self.srv;
AndThenApplyFnFactoryResponse { AndThenApplyFnFactoryResponse {
a: None, s1: None,
b: None, s2: None,
f: srv.2.clone(), wrap_fn: srv.2.clone(),
fut_a: srv.0.new_service(cfg.clone()), fut_s1: srv.0.new_service(cfg.clone()),
fut_b: srv.1.new_service(cfg), fut_s2: srv.1.new_service(cfg),
_phantom: PhantomData,
} }
} }
} }
#[pin_project::pin_project] #[pin_project::pin_project]
pub(crate) struct AndThenApplyFnFactoryResponse<A, B, F, Fut, Req, Res, Err> pub(crate) struct AndThenApplyFnFactoryResponse<SF1, SF2, F, Fut, Req, In, Res, Err>
where where
A: ServiceFactory<Req>, SF1: ServiceFactory<Req>,
B: ServiceFactory< SF2: ServiceFactory<In, Config = SF1::Config, InitError = SF1::InitError>,
Result<A::Response, A::Error>, F: FnMut(SF1::Response, &mut SF2::Service) -> Fut + Clone,
Config = A::Config,
InitError = A::InitError,
>,
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error>, Err: From<SF1::Error>,
Err: From<B::Error>, Err: From<SF2::Error>,
{ {
#[pin] #[pin]
fut_b: B::Future, fut_s1: SF1::Future,
#[pin] #[pin]
fut_a: A::Future, fut_s2: SF2::Future,
f: F, wrap_fn: F,
a: Option<A::Service>, s1: Option<SF1::Service>,
b: Option<B::Service>, s2: Option<SF2::Service>,
_phantom: PhantomData<In>,
} }
impl<A, B, F, Fut, Req, Res, Err> Future impl<SF1, SF2, F, Fut, Req, In, Res, Err> Future
for AndThenApplyFnFactoryResponse<A, B, F, Fut, Req, Res, Err> for AndThenApplyFnFactoryResponse<SF1, SF2, F, Fut, Req, In, Res, Err>
where where
A: ServiceFactory<Req>, SF1: ServiceFactory<Req>,
B: ServiceFactory< SF2: ServiceFactory<In, Config = SF1::Config, InitError = SF1::InitError>,
Result<A::Response, A::Error>, F: FnMut(SF1::Response, &mut SF2::Service) -> Fut + Clone,
Config = A::Config,
InitError = A::InitError,
>,
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<A::Error> + From<B::Error>, Err: From<SF1::Error> + From<SF2::Error>,
{ {
type Output = type Output = Result<
Result<AndThenApplyFn<A::Service, B::Service, F, Fut, Req, Res, Err>, A::InitError>; AndThenApplyFn<SF1::Service, SF2::Service, F, Fut, Req, In, Res, Err>,
SF1::InitError,
>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();
if this.a.is_none() { if this.s1.is_none() {
if let Poll::Ready(service) = this.fut_a.poll(cx)? { if let Poll::Ready(service) = this.fut_s1.poll(cx)? {
*this.a = Some(service); *this.s1 = Some(service);
} }
} }
if this.b.is_none() { if this.s2.is_none() {
if let Poll::Ready(service) = this.fut_b.poll(cx)? { if let Poll::Ready(service) = this.fut_s2.poll(cx)? {
*this.b = Some(service); *this.s2 = Some(service);
} }
} }
if this.a.is_some() && this.b.is_some() { if this.s1.is_some() && this.s2.is_some() {
Poll::Ready(Ok(AndThenApplyFn { Poll::Ready(Ok(AndThenApplyFn {
srv: Rc::new(RefCell::new(( svc: Rc::new(RefCell::new((
this.a.take().unwrap(), Option::take(this.s1).unwrap(),
this.b.take().unwrap(), Option::take(this.s2).unwrap(),
this.f.clone(), this.wrap_fn.clone(),
))), ))),
r: PhantomData, _phantom: PhantomData,
})) }))
} else { } else {
Poll::Pending Poll::Pending
@ -296,29 +288,29 @@ mod tests {
#[derive(Clone)] #[derive(Clone)]
struct Srv; struct Srv;
impl Service<()> for Srv {
impl Service<u8> for Srv {
type Response = (); type Response = ();
type Error = (); type Error = ();
type Future = Ready<Result<(), ()>>; type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
#[allow(clippy::unit_arg)] fn call(&mut self, req: u8) -> Self::Future {
fn call(&mut self, req: ()) -> Self::Future { let _ = req;
ok(req) ok(())
} }
} }
#[actix_rt::test] #[actix_rt::test]
async fn test_service() { async fn test_service() {
let mut srv = pipeline(|| async { Ok(2) }) let mut srv = pipeline(ok).and_then_apply_fn(Srv, |req: &'static str, s| {
.and_then_apply_fn(Srv, |req: &'static str, s| { s.call(1).map_ok(move |res| (req, res))
s.call(()).map_ok(move |res| (req, res))
}); });
let res = lazy(|cx| srv.poll_ready(cx)).await; let res = lazy(|cx| srv.poll_ready(cx)).await;
assert_eq!(res, Poll::Ready(Ok(()))); assert!(res.is_ready());
let res = srv.call("srv").await; let res = srv.call("srv").await;
assert!(res.is_ok()); assert!(res.is_ok());
@ -329,11 +321,11 @@ mod tests {
async fn test_service_factory() { async fn test_service_factory() {
let new_srv = pipeline_factory(|| ok::<_, ()>(fn_service(ok))).and_then_apply_fn( let new_srv = pipeline_factory(|| ok::<_, ()>(fn_service(ok))).and_then_apply_fn(
|| ok(Srv), || ok(Srv),
|req: &'static str, s| s.call(()).map_ok(move |res| (req, res)), |req: &'static str, s| s.call(1).map_ok(move |res| (req, res)),
); );
let mut srv = new_srv.new_service(()).await.unwrap(); let mut srv = new_srv.new_service(()).await.unwrap();
let res = lazy(|cx| srv.poll_ready(cx)).await; let res = lazy(|cx| srv.poll_ready(cx)).await;
assert_eq!(res, Poll::Ready(Ok(()))); assert!(res.is_ready());
let res = srv.call("srv").await; let res = srv.call("srv").await;
assert!(res.is_ok()); assert!(res.is_ok());

View File

@ -1,208 +1,209 @@
use std::future::Future; use std::{
use std::marker::PhantomData; future::Future,
use std::pin::Pin; marker::PhantomData,
use std::task::{Context, Poll}; pin::Pin,
task::{Context, Poll},
};
use futures_util::ready;
use super::{IntoService, IntoServiceFactory, Service, ServiceFactory}; use super::{IntoService, IntoServiceFactory, Service, ServiceFactory};
/// Apply transform function to a service. /// Apply transform function to a service.
pub fn apply_fn<T, Req, F, R, In, Out, Err, U>( ///
/// The In and Out type params refer to the request and response types for the wrapped service.
pub fn apply_fn<U, S, F, Fut, Req, In, Res, Err>(
service: U, service: U,
f: F, wrap_fn: F,
) -> Apply<T, Req, F, R, In, Out, Err> ) -> Apply<S, F, Req, In, Res, Err>
where where
T: Service<Req, Error = Err>, U: IntoService<S, In>,
F: FnMut(In, &mut T) -> R, S: Service<In, Error = Err>,
R: Future<Output = Result<Out, Err>>, F: FnMut(Req, &mut S) -> Fut,
U: IntoService<T, Req>, Fut: Future<Output = Result<Res, Err>>,
{ {
Apply::new(service.into_service(), f) Apply::new(service.into_service(), wrap_fn)
} }
/// Service factory that produces `apply_fn` service. /// Service factory that produces `apply_fn` service.
pub fn apply_fn_factory<T, Req, F, R, In, Out, Err, U>( ///
/// The In and Out type params refer to the request and response types for the wrapped service.
pub fn apply_fn_factory<U, SF, F, Fut, Req, In, Res, Err>(
service: U, service: U,
f: F, f: F,
) -> ApplyServiceFactory<T, Req, F, R, In, Out, Err> ) -> ApplyFactory<SF, F, Req, In, Res, Err>
where where
T: ServiceFactory<Req, Error = Err>, U: IntoServiceFactory<SF, In>,
F: FnMut(In, &mut T::Service) -> R + Clone, SF: ServiceFactory<In, Error = Err>,
R: Future<Output = Result<Out, Err>>, F: FnMut(Req, &mut SF::Service) -> Fut + Clone,
U: IntoServiceFactory<T, Req>, Fut: Future<Output = Result<Res, Err>>,
{ {
ApplyServiceFactory::new(service.into_factory(), f) ApplyFactory::new(service.into_factory(), f)
} }
/// `Apply` service combinator /// `Apply` service combinator.
pub struct Apply<T, Req, F, R, In, Out, Err> ///
/// The In and Out type params refer to the request and response types for the wrapped service.
pub struct Apply<S, F, Req, In, Res, Err>
where where
T: Service<Req, Error = Err>, S: Service<In, Error = Err>,
{ {
service: T, service: S,
f: F, wrap_fn: F,
r: PhantomData<(In, Out, R)>, _phantom: PhantomData<(Req, In, Res, Err)>,
} }
impl<T, Req, F, R, In, Out, Err> Apply<T, Req, F, R, In, Out, Err> impl<S, F, Fut, Req, In, Res, Err> Apply<S, F, Req, In, Res, Err>
where where
T: Service<Req, Error = Err>, S: Service<In, Error = Err>,
F: FnMut(In, &mut T) -> R, F: FnMut(Req, &mut S) -> Fut,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
/// Create new `Apply` combinator /// Create new `Apply` combinator
fn new(service: T, f: F) -> Self { fn new(service: S, wrap_fn: F) -> Self {
Self { Self {
service, service,
f, wrap_fn,
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<T, Req, F, R, In, Out, Err> Clone for Apply<T, Req, F, R, In, Out, Err> impl<S, F, Fut, Req, In, Res, Err> Clone for Apply<S, F, Req, In, Res, Err>
where where
T: Service<Req, Error = Err> + Clone, S: Service<In, Error = Err> + Clone,
F: FnMut(In, &mut T) -> R + Clone, F: FnMut(Req, &mut S) -> Fut + Clone,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Apply { Apply {
service: self.service.clone(), service: self.service.clone(),
f: self.f.clone(), wrap_fn: self.wrap_fn.clone(),
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<T, Req, F, R, In, Out, Err> Service<Req> for Apply<T, Req, F, R, In, Out, Err> impl<S, F, Fut, Req, In, Res, Err> Service<Req> for Apply<S, F, Req, In, Res, Err>
where where
T: Service<Req, Error = Err>, S: Service<In, Error = Err>,
F: FnMut(In, &mut T) -> R, F: FnMut(Req, &mut S) -> Fut,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
// type Request = In; type Response = Res;
type Response = Out;
type Error = Err; type Error = Err;
type Future = R; type Future = Fut;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(futures_util::ready!(self.service.poll_ready(cx))) Poll::Ready(ready!(self.service.poll_ready(cx)))
} }
fn call(&mut self, req: In) -> Self::Future { fn call(&mut self, req: Req) -> Self::Future {
(self.f)(req, &mut self.service) (self.wrap_fn)(req, &mut self.service)
} }
} }
/// `apply()` service factory /// `ApplyFactory` service factory combinator.
pub struct ApplyServiceFactory<T, Req, F, R, In, Out, Err> pub struct ApplyFactory<SF, F, Req, In, Res, Err> {
where factory: SF,
T: ServiceFactory<Req, Error = Err>, wrap_fn: F,
F: FnMut(In, &mut T::Service) -> R + Clone, _phantom: PhantomData<(Req, In, Res, Err)>,
R: Future<Output = Result<Out, Err>>,
{
service: T,
f: F,
r: PhantomData<(R, In, Out)>,
} }
impl<T, Req, F, R, In, Out, Err> ApplyServiceFactory<T, Req, F, R, In, Out, Err> impl<SF, F, Fut, Req, In, Res, Err> ApplyFactory<SF, F, Req, In, Res, Err>
where where
T: ServiceFactory<Req, Error = Err>, SF: ServiceFactory<In, Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone, F: FnMut(Req, &mut SF::Service) -> Fut + Clone,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
/// Create new `ApplyNewService` new service instance /// Create new `ApplyFactory` new service instance
fn new(service: T, f: F) -> Self { fn new(factory: SF, wrap_fn: F) -> Self {
Self { Self {
f, factory,
service, wrap_fn,
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<T, Req, F, R, In, Out, Err> Clone for ApplyServiceFactory<T, Req, F, R, In, Out, Err> impl<SF, F, Fut, Req, In, Res, Err> Clone for ApplyFactory<SF, F, Req, In, Res, Err>
where where
T: ServiceFactory<Req, Error = Err> + Clone, SF: ServiceFactory<In, Error = Err> + Clone,
F: FnMut(In, &mut T::Service) -> R + Clone, F: FnMut(Req, &mut SF::Service) -> Fut + Clone,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
service: self.service.clone(), factory: self.factory.clone(),
f: self.f.clone(), wrap_fn: self.wrap_fn.clone(),
r: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<T, Req, F, R, In, Out, Err> ServiceFactory<Req> impl<SF, F, Fut, Req, In, Res, Err> ServiceFactory<Req>
for ApplyServiceFactory<T, Req, F, R, In, Out, Err> for ApplyFactory<SF, F, Req, In, Res, Err>
where where
T: ServiceFactory<Req, Error = Err>, SF: ServiceFactory<In, Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone, F: FnMut(Req, &mut SF::Service) -> Fut + Clone,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
// type Request = In; type Response = Res;
type Response = Out;
type Error = Err; type Error = Err;
type Config = T::Config; type Config = SF::Config;
type Service = Apply<T::Service, Req, F, R, In, Out, Err>; type Service = Apply<SF::Service, F, Req, In, Res, Err>;
type InitError = T::InitError; type InitError = SF::InitError;
type Future = ApplyServiceFactoryResponse<T,Req, F, R, In, Out, Err>; type Future = ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>;
fn new_service(&self, cfg: T::Config) -> Self::Future { fn new_service(&self, cfg: SF::Config) -> Self::Future {
ApplyServiceFactoryResponse::new(self.service.new_service(cfg), self.f.clone()) let svc = self.factory.new_service(cfg);
ApplyServiceFactoryResponse::new(svc, self.wrap_fn.clone())
} }
} }
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct ApplyServiceFactoryResponse<T, Req, F, R, In, Out, Err> pub struct ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
where where
T: ServiceFactory<Req, Error = Err>, SF: ServiceFactory<In, Error = Err>,
F: FnMut(In, &mut T::Service) -> R, F: FnMut(Req, &mut SF::Service) -> Fut,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
#[pin] #[pin]
fut: T::Future, fut: SF::Future,
f: Option<F>, wrap_fn: Option<F>,
r: PhantomData<(In, Out)>, _phantom: PhantomData<(Req, Res)>,
} }
impl<T, Req, F, R, In, Out, Err> ApplyServiceFactoryResponse<T, Req, F, R, In, Out, Err> impl<SF, F, Fut, Req, In, Res, Err> ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
where where
T: ServiceFactory<Req, Error = Err>, SF: ServiceFactory<In, Error = Err>,
F: FnMut(In, &mut T::Service) -> R, F: FnMut(Req, &mut SF::Service) -> Fut,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
fn new(fut: T::Future, f: F) -> Self { fn new(fut: SF::Future, wrap_fn: F) -> Self {
Self { Self {
f: Some(f),
fut, fut,
r: PhantomData, wrap_fn: Some(wrap_fn),
_phantom: PhantomData,
} }
} }
} }
impl<T, Req, F, R, In, Out, Err> Future impl<SF, F, Fut, Req, In, Res, Err> Future
for ApplyServiceFactoryResponse<T, Req, F, R, In, Out, Err> for ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
where where
T: ServiceFactory<Req, Error = Err>, SF: ServiceFactory<In, Error = Err>,
F: FnMut(In, &mut T::Service) -> R, F: FnMut(Req, &mut SF::Service) -> Fut,
R: Future<Output = Result<Out, Err>>, Fut: Future<Output = Result<Res, Err>>,
{ {
type Output = Result<Apply<T::Service, Req, F, R, In, Out, Err>, T::InitError>; type Output = Result<Apply<SF::Service, F, Req, In, Res, Err>, SF::InitError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();
if let Poll::Ready(svc) = this.fut.poll(cx)? { let svc = ready!(this.fut.poll(cx))?;
Poll::Ready(Ok(Apply::new(svc, this.f.take().unwrap()))) Poll::Ready(Ok(Apply::new(svc, Option::take(this.wrap_fn).unwrap())))
} else {
Poll::Pending
}
} }
} }

View File

@ -68,7 +68,7 @@ where
S: Service<Req>, S: Service<Req>,
{ {
srv: Rc<RefCell<(T, F)>>, srv: Rc<RefCell<(T, F)>>,
_t: PhantomData<(C, R, S)>, _t: PhantomData<(C, Req, R, S)>,
} }
impl<F, C, Req, T, R, S, E> Clone for ApplyConfigService<F, C, Req, T, R, S, E> impl<F, C, Req, T, R, S, E> Clone for ApplyConfigService<F, C, Req, T, R, S, E>
@ -116,7 +116,7 @@ where
S: Service<Req>, S: Service<Req>,
{ {
srv: Rc<RefCell<(T, F)>>, srv: Rc<RefCell<(T, F)>>,
_t: PhantomData<(C, R, S)>, _t: PhantomData<(C, Req, R, S)>,
} }
impl<F, C, Req, T, R, S> Clone for ApplyConfigServiceFactory<F, C, Req, T, R, S> impl<F, C, Req, T, R, S> Clone for ApplyConfigServiceFactory<F, C, Req, T, R, S>

View File

@ -1,6 +1,6 @@
use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::{future::Future, marker::PhantomData};
use futures_util::future::FutureExt; use futures_util::future::FutureExt;
@ -36,9 +36,10 @@ where
pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error> pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error>
where where
S: Service<Req> + 'static, S: Service<Req> + 'static,
Req: 'static,
S::Future: 'static, S::Future: 'static,
{ {
Box::new(ServiceWrapper(service)) Box::new(ServiceWrapper(service, PhantomData))
} }
type Inner<C, Req, Res, Err, InitErr> = Box< type Inner<C, Req, Res, Err, InitErr> = Box<
@ -74,9 +75,12 @@ where
} }
} }
struct FactoryWrapper<C, T: ServiceFactory<Req>, Req> { struct FactoryWrapper<C, T, Req>
where
T: ServiceFactory<Req>,
{
factory: T, factory: T,
_t: std::marker::PhantomData<C>, _t: PhantomData<(C, Req)>,
} }
impl<C, T, Req, Res, Err, InitErr> ServiceFactory<Req> for FactoryWrapper<C, T, Req> impl<C, T, Req, Res, Err, InitErr> ServiceFactory<Req> for FactoryWrapper<C, T, Req>
@ -106,15 +110,16 @@ where
} }
} }
struct ServiceWrapper<S: Service<Req>, Req>(S); struct ServiceWrapper<S: Service<Req>, Req>(S, PhantomData<Req>);
impl<S, Req> ServiceWrapper<S, Req> impl<S, Req> ServiceWrapper<S, Req>
where where
S: Service<Req> + 'static, S: Service<Req> + 'static,
Req: 'static,
S::Future: 'static, S::Future: 'static,
{ {
fn boxed(service: S) -> BoxService<Req, S::Response, S::Error> { fn boxed(service: S) -> BoxService<Req, S::Response, S::Error> {
Box::new(ServiceWrapper(service)) Box::new(ServiceWrapper(service, PhantomData))
} }
} }

View File

@ -55,7 +55,7 @@ where
/// ``` /// ```
pub fn fn_factory<F, Cfg, Srv, Req, Fut, Err>( pub fn fn_factory<F, Cfg, Srv, Req, Fut, Err>(
f: F, f: F,
) -> FnServiceNoConfig<F, Cfg, Srv, Fut, Req, Err> ) -> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
where where
Srv: Service<Req>, Srv: Service<Req>,
F: Fn() -> Fut, F: Fn() -> Fut,
@ -247,7 +247,7 @@ where
Srv: Service<Req>, Srv: Service<Req>,
{ {
f: F, f: F,
_t: PhantomData<(Fut, Cfg, Srv, Err)>, _t: PhantomData<(Fut, Cfg, Req, Srv, Err)>,
} }
impl<F, Fut, Cfg, Srv, Req, Err> FnServiceConfig<F, Fut, Cfg, Srv, Req, Err> impl<F, Fut, Cfg, Srv, Req, Err> FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
@ -303,7 +303,7 @@ where
Fut: Future<Output = Result<Srv, Err>>, Fut: Future<Output = Result<Srv, Err>>,
{ {
f: F, f: F,
_t: PhantomData<Cfg>, _t: PhantomData<(Cfg, Req)>,
} }
impl<F, Cfg, Srv, Req, Fut, Err> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err> impl<F, Cfg, Srv, Req, Fut, Err> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>

View File

@ -303,52 +303,52 @@ where
} }
/// Trait for types that can be converted to a `Service` /// Trait for types that can be converted to a `Service`
pub trait IntoService<T, Req> pub trait IntoService<S, Req>
where where
T: Service<Req>, S: Service<Req>,
{ {
/// Convert to a `Service` /// Convert to a `Service`
fn into_service(self) -> T; fn into_service(self) -> S;
} }
/// Trait for types that can be converted to a `ServiceFactory` /// Trait for types that can be converted to a `ServiceFactory`
pub trait IntoServiceFactory<T, Req> pub trait IntoServiceFactory<SF, Req>
where where
T: ServiceFactory<Req>, SF: ServiceFactory<Req>,
{ {
/// Convert `Self` to a `ServiceFactory` /// Convert `Self` to a `ServiceFactory`
fn into_factory(self) -> T; fn into_factory(self) -> SF;
} }
impl<T, Req> IntoService<T, Req> for T impl<S, Req> IntoService<S, Req> for S
where where
T: Service<Req>, S: Service<Req>,
{ {
fn into_service(self) -> T { fn into_service(self) -> S {
self self
} }
} }
impl<T, Req> IntoServiceFactory<T, Req> for T impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where where
T: ServiceFactory<Req>, SF: ServiceFactory<Req>,
{ {
fn into_factory(self) -> T { fn into_factory(self) -> SF {
self self
} }
} }
/// Convert object of type `T` to a service `S` /// Convert object of type `T` to a service `S`
pub fn into_service<T, S, Req>(tp: T) -> S pub fn into_service<U, S, Req>(tp: U) -> S
where where
U: IntoService<S, Req>,
S: Service<Req>, S: Service<Req>,
T: IntoService<S, Req>,
{ {
tp.into_service() tp.into_service()
} }
pub mod dev { pub mod dev {
pub use crate::apply::{Apply, ApplyServiceFactory}; pub use crate::apply::{Apply, ApplyFactory};
pub use crate::fn_service::{ pub use crate::fn_service::{
FnService, FnServiceConfig, FnServiceFactory, FnServiceNoConfig, FnService, FnServiceConfig, FnServiceFactory, FnServiceNoConfig,
}; };

View File

@ -104,7 +104,7 @@ where
pub struct MapServiceFactory<A, F, Req, Res> { pub struct MapServiceFactory<A, F, Req, Res> {
a: A, a: A,
f: F, f: F,
r: PhantomData<Res>, r: PhantomData<(Res, Req)>,
} }
impl<A, F, Req, Res> MapServiceFactory<A, F, Req, Res> { impl<A, F, Req, Res> MapServiceFactory<A, F, Req, Res> {

View File

@ -6,119 +6,123 @@ use super::{IntoServiceFactory, ServiceFactory};
/// ///
/// Note that this function consumes the receiving service factory and returns /// Note that this function consumes the receiving service factory and returns
/// a wrapped version of it. /// a wrapped version of it.
pub fn map_config<T, U, F, C, Req>(factory: U, f: F) -> MapConfig<T, Req, F, C> pub fn map_config<U, SF, S, Req, F, Cfg>(factory: U, f: F) -> MapConfig<SF, Req, F, Cfg>
where where
T: ServiceFactory<Req>, U: IntoServiceFactory<SF, Req>,
U: IntoServiceFactory<T, Req>, SF: ServiceFactory<Req>,
F: Fn(C) -> T::Config, F: Fn(Cfg) -> SF::Config,
{ {
MapConfig::new(factory.into_factory(), f) MapConfig::new(factory.into_factory(), f)
} }
/// Replace config with unit /// Replace config with unit.
pub fn unit_config<T, U, C, Req>(factory: U) -> UnitConfig<T, C, Req> pub fn unit_config<U, SF, Cfg, Req>(factory: U) -> UnitConfig<SF, Cfg, Req>
where where
T: ServiceFactory<Req, Config = ()>, U: IntoServiceFactory<SF, Req>,
U: IntoServiceFactory<T, Req>, SF: ServiceFactory<Req, Config = ()>,
{ {
UnitConfig::new(factory.into_factory()) UnitConfig::new(factory.into_factory())
} }
/// `map_config()` adapter service factory /// `map_config()` adapter service factory
pub struct MapConfig<A, Req, F, C> { pub struct MapConfig<SF, Req, F, Cfg> {
a: A, factory: SF,
f: F, cfg_mapper: F,
e: PhantomData<(C, Req)>, e: PhantomData<(Cfg, Req)>,
} }
impl<T, F, C, Req> MapConfig<T, F, C, Req> { impl<SF, Req, F, Cfg> MapConfig<SF, Req, F, Cfg> {
/// Create new `MapConfig` combinator /// Create new `MapConfig` combinator
pub(crate) fn new(a: T, f: F) -> Self pub(crate) fn new(factory: SF, cfg_mapper: F) -> Self
where where
T: ServiceFactory<Req>, SF: ServiceFactory<Req>,
F: Fn(C) -> T::Config, F: Fn(Cfg) -> SF::Config,
{ {
Self { Self {
a, factory,
f, cfg_mapper,
e: PhantomData, e: PhantomData,
} }
} }
} }
impl<T, Req, F, C> Clone for MapConfig<T, Req, F, C> impl<SF, Req, F, Cfg> Clone for MapConfig<SF, Req, F, Cfg>
where where
T: Clone, SF: Clone,
F: Clone, F: Clone,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
a: self.a.clone(), factory: self.factory.clone(),
f: self.f.clone(), cfg_mapper: self.cfg_mapper.clone(),
e: PhantomData, e: PhantomData,
} }
} }
} }
impl<T, Req, F, C> ServiceFactory<Req> for MapConfig<T, Req, F, C> impl<SF, Req, F, Cfg> ServiceFactory<Req> for MapConfig<SF, Req, F, Cfg>
where where
T: ServiceFactory<Req>, SF: ServiceFactory<Req>,
F: Fn(C) -> T::Config, F: Fn(Cfg) -> SF::Config,
{ {
type Response = T::Response; type Response = SF::Response;
type Error = T::Error; type Error = SF::Error;
type Config = C; type Config = Cfg;
type Service = T::Service; type Service = SF::Service;
type InitError = T::InitError; type InitError = SF::InitError;
type Future = T::Future; type Future = SF::Future;
fn new_service(&self, cfg: C) -> Self::Future { fn new_service(&self, cfg: Self::Config) -> Self::Future {
self.a.new_service((self.f)(cfg)) let mapped_cfg = (self.cfg_mapper)(cfg);
self.factory.new_service(mapped_cfg)
} }
} }
/// `unit_config()` config combinator /// `unit_config()` config combinator
pub struct UnitConfig<T, C, Req> { pub struct UnitConfig<SF, Cfg, Req> {
a: T, factory: SF,
e: PhantomData<(C, Req)>, _phantom: PhantomData<(Cfg, Req)>,
} }
impl<T, C, Req> UnitConfig<T, C, Req> impl<SF, Cfg, Req> UnitConfig<SF, Cfg, Req>
where where
T: ServiceFactory<Req, Config = ()>, SF: ServiceFactory<Req, Config = ()>,
{ {
/// Create new `UnitConfig` combinator /// Create new `UnitConfig` combinator
pub(crate) fn new(a: T) -> Self { pub(crate) fn new(factory: SF) -> Self {
Self { a, e: PhantomData } Self {
factory,
_phantom: PhantomData,
}
} }
} }
impl<T, C, Req> Clone for UnitConfig<T, C, Req> impl<SF, Cfg, Req> Clone for UnitConfig<SF, Cfg, Req>
where where
T: Clone, SF: Clone,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
a: self.a.clone(), factory: self.factory.clone(),
e: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<T, C, Req> ServiceFactory<Req> for UnitConfig<T, C, Req> impl<SF, Cfg, Req> ServiceFactory<Req> for UnitConfig<SF, Cfg, Req>
where where
T: ServiceFactory<Req, Config = ()>, SF: ServiceFactory<Req, Config = ()>,
{ {
type Response = T::Response; type Response = SF::Response;
type Error = T::Error; type Error = SF::Error;
type Config = C; type Config = Cfg;
type Service = T::Service; type Service = SF::Service;
type InitError = T::InitError; type InitError = SF::InitError;
type Future = T::Future; type Future = SF::Future;
fn new_service(&self, _: C) -> Self::Future { fn new_service(&self, _: Cfg) -> Self::Future {
self.a.new_service(()) self.factory.new_service(())
} }
} }

View File

@ -12,7 +12,7 @@ use super::{Service, ServiceFactory};
pub struct MapErr<S, Req, F, E> { pub struct MapErr<S, Req, F, E> {
service: S, service: S,
f: F, f: F,
_t: PhantomData<E>, _t: PhantomData<(E, Req)>,
} }
impl<S, Req, F, E> MapErr<S, Req, F, E> { impl<S, Req, F, E> MapErr<S, Req, F, E> {
@ -107,7 +107,7 @@ where
{ {
a: A, a: A,
f: F, f: F,
e: PhantomData<E>, e: PhantomData<(E, Req)>,
} }
impl<A, Req, F, E> MapErrServiceFactory<A, Req, F, E> impl<A, Req, F, E> MapErrServiceFactory<A, Req, F, E>

View File

@ -12,7 +12,7 @@ pub struct MapInitErr<A, F, Req, Err> {
e: PhantomData<(Req, Err)>, e: PhantomData<(Req, Err)>,
} }
impl<A, Req, F, Err> MapInitErr<A, Req, F, Err> impl<A, F, Req, Err> MapInitErr<A, F, Req, Err>
where where
A: ServiceFactory<Req>, A: ServiceFactory<Req>,
F: Fn(A::InitError) -> Err, F: Fn(A::InitError) -> Err,
@ -41,7 +41,7 @@ where
} }
} }
impl<A, Req, F, E> ServiceFactory<Req> for MapInitErr<A, Req, F, E> impl<A, F, Req, E> ServiceFactory<Req> for MapInitErr<A, F, Req, E>
where where
A: ServiceFactory<Req>, A: ServiceFactory<Req>,
F: Fn(A::InitError) -> E + Clone, F: Fn(A::InitError) -> E + Clone,
@ -52,7 +52,7 @@ where
type Config = A::Config; type Config = A::Config;
type Service = A::Service; type Service = A::Service;
type InitError = E; type InitError = E;
type Future = MapInitErrFuture<A, Req, F, E>; type Future = MapInitErrFuture<A, F, Req, E>;
fn new_service(&self, cfg: A::Config) -> Self::Future { fn new_service(&self, cfg: A::Config) -> Self::Future {
MapInitErrFuture::new(self.a.new_service(cfg), self.f.clone()) MapInitErrFuture::new(self.a.new_service(cfg), self.f.clone())
@ -60,7 +60,7 @@ where
} }
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct MapInitErrFuture<A, Req, F, E> pub struct MapInitErrFuture<A, F, Req, E>
where where
A: ServiceFactory<Req>, A: ServiceFactory<Req>,
F: Fn(A::InitError) -> E, F: Fn(A::InitError) -> E,
@ -70,7 +70,7 @@ where
fut: A::Future, fut: A::Future,
} }
impl<A, Req, F, E> MapInitErrFuture<A, Req, F, E> impl<A, F, Req, E> MapInitErrFuture<A, F, Req, E>
where where
A: ServiceFactory<Req>, A: ServiceFactory<Req>,
F: Fn(A::InitError) -> E, F: Fn(A::InitError) -> E,
@ -80,7 +80,7 @@ where
} }
} }
impl<A, Req, F, E> Future for MapInitErrFuture<A, Req, F, E> impl<A, F, Req, E> Future for MapInitErrFuture<A, F, Req, E>
where where
A: ServiceFactory<Req>, A: ServiceFactory<Req>,
F: Fn(A::InitError) -> E, F: Fn(A::InitError) -> E,

View File

@ -10,10 +10,10 @@ use crate::then::{ThenService, ThenServiceFactory};
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory}; use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
/// Construct new pipeline with one service in pipeline chain. /// Construct new pipeline with one service in pipeline chain.
pub fn pipeline<F, T, Req>(service: F) -> Pipeline<T, Req> pub fn pipeline<U, S, Req>(service: U) -> Pipeline<S, Req>
where where
F: IntoService<T, Req>, U: IntoService<S, Req>,
T: Service<Req>, S: Service<Req>,
{ {
Pipeline { Pipeline {
service: service.into_service(), service: service.into_service(),
@ -22,10 +22,10 @@ where
} }
/// Construct new pipeline factory with one service factory. /// Construct new pipeline factory with one service factory.
pub fn pipeline_factory<T, F, Req>(factory: F) -> PipelineFactory<T, Req> pub fn pipeline_factory<U, SF, Req>(factory: U) -> PipelineFactory<SF, Req>
where where
T: ServiceFactory<Req>, U: IntoServiceFactory<SF, Req>,
F: IntoServiceFactory<T, Req>, SF: ServiceFactory<Req>,
{ {
PipelineFactory { PipelineFactory {
factory: factory.into_factory(), factory: factory.into_factory(),
@ -34,12 +34,15 @@ where
} }
/// Pipeline service - pipeline allows to compose multiple service into one service. /// Pipeline service - pipeline allows to compose multiple service into one service.
pub struct Pipeline<T, Req> { pub struct Pipeline<S, Req> {
service: T, service: S,
_phantom: PhantomData<Req>, _phantom: PhantomData<Req>,
} }
impl<T: Service<Req>, Req> Pipeline<T, Req> { impl<S, Req> Pipeline<S, Req>
where
S: Service<Req>,
{
/// Call another service after call to this one has resolved successfully. /// Call another service after call to this one has resolved successfully.
/// ///
/// This function can be used to chain two services together and ensure that /// This function can be used to chain two services together and ensure that
@ -52,11 +55,11 @@ impl<T: Service<Req>, Req> Pipeline<T, Req> {
pub fn and_then<F, U>( pub fn and_then<F, U>(
self, self,
service: F, service: F,
) -> Pipeline<impl Service<Req, Response = U::Response, Error = T::Error> + Clone, Req> ) -> Pipeline<impl Service<Req, Response = U::Response, Error = S::Error> + Clone, Req>
where where
Self: Sized, Self: Sized,
F: IntoService<U, Req>, F: IntoService<U, S::Response>,
U: Service<T::Response, Error = T::Error>, U: Service<S::Response, Error = S::Error>,
{ {
Pipeline { Pipeline {
service: AndThenService::new(self.service, service.into_service()), service: AndThenService::new(self.service, service.into_service()),
@ -64,25 +67,24 @@ impl<T: Service<Req>, Req> Pipeline<T, Req> {
} }
} }
/// Apply function to specified service and use it as a next service in /// Apply function to specified service and use it as a next service in chain.
/// chain.
/// ///
/// Short version of `pipeline_factory(...).and_then(apply_fn_factory(...))` /// Short version of `pipeline_factory(...).and_then(apply_fn(...))`
pub fn and_then_apply_fn<U, I, F, Fut, Res, Err>( pub fn and_then_apply_fn<U, S1, F, Fut, In, Res, Err>(
self, self,
service: I, service: U,
f: F, wrap_fn: F,
) -> Pipeline<impl Service<Req, Response = Res, Error = Err> + Clone, Req> ) -> Pipeline<impl Service<Req, Response = Res, Error = Err> + Clone, Req>
where where
Self: Sized, Self: Sized,
I: IntoService<U, Req>, U: IntoService<S1, In>,
U: Service<Req>, S1: Service<In>,
F: FnMut(T::Response, &mut U) -> Fut, F: FnMut(S::Response, &mut S1) -> Fut,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<T::Error> + From<U::Error>, Err: From<S::Error> + From<S1::Error>,
{ {
Pipeline { Pipeline {
service: AndThenApplyFn::new(self.service, service.into_service(), f), service: AndThenApplyFn::new(self.service, service.into_service(), wrap_fn),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
@ -95,11 +97,11 @@ impl<T: Service<Req>, Req> Pipeline<T, Req> {
pub fn then<F, U>( pub fn then<F, U>(
self, self,
service: F, service: F,
) -> Pipeline<impl Service<Req, Response = U::Response, Error = T::Error> + Clone, Req> ) -> Pipeline<impl Service<Req, Response = U::Response, Error = S::Error> + Clone, Req>
where where
Self: Sized, Self: Sized,
F: IntoService<U, Req>, F: IntoService<U, Result<S::Response, S::Error>>,
U: Service<Result<T::Response, T::Error>, Error = T::Error>, U: Service<Result<S::Response, S::Error>, Error = S::Error>,
{ {
Pipeline { Pipeline {
service: ThenService::new(self.service, service.into_service()), service: ThenService::new(self.service, service.into_service()),
@ -116,10 +118,10 @@ impl<T: Service<Req>, Req> Pipeline<T, Req> {
/// Note that this function consumes the receiving service and returns a /// Note that this function consumes the receiving service and returns a
/// wrapped version of it, similar to the existing `map` methods in the /// wrapped version of it, similar to the existing `map` methods in the
/// standard library. /// standard library.
pub fn map<F, R>(self, f: F) -> Pipeline<Map<T, F, Req, R>, Req> pub fn map<F, R>(self, f: F) -> Pipeline<Map<S, F, Req, R>, Req>
where where
Self: Sized, Self: Sized,
F: FnMut(T::Response) -> R, F: FnMut(S::Response) -> R,
{ {
Pipeline { Pipeline {
service: Map::new(self.service, f), service: Map::new(self.service, f),
@ -135,10 +137,10 @@ impl<T: Service<Req>, Req> Pipeline<T, Req> {
/// ///
/// Note that this function consumes the receiving service and returns a /// Note that this function consumes the receiving service and returns a
/// wrapped version of it. /// wrapped version of it.
pub fn map_err<F, E>(self, f: F) -> Pipeline<MapErr<T, Req, F, E>, Req> pub fn map_err<F, E>(self, f: F) -> Pipeline<MapErr<S, Req, F, E>, Req>
where where
Self: Sized, Self: Sized,
F: Fn(T::Error) -> E, F: Fn(S::Error) -> E,
{ {
Pipeline { Pipeline {
service: MapErr::new(self.service, f), service: MapErr::new(self.service, f),
@ -176,40 +178,39 @@ impl<T: Service<Req>, Req> Service<Req> for Pipeline<T, Req> {
} }
/// Pipeline factory /// Pipeline factory
pub struct PipelineFactory<T, Req> { pub struct PipelineFactory<SF, Req> {
factory: T, factory: SF,
_phantom: PhantomData<Req>, _phantom: PhantomData<Req>,
} }
impl<T: ServiceFactory<Req>, Req> PipelineFactory<T, Req> { impl<SF, Req> PipelineFactory<SF, Req>
where
SF: ServiceFactory<Req>,
{
/// Call another service after call to this one has resolved successfully. /// Call another service after call to this one has resolved successfully.
pub fn and_then<F, U>( pub fn and_then<F, U>(
self, self,
factory: F, factory: F,
) -> PipelineFactory< ) -> PipelineFactory<
impl ServiceFactory< impl ServiceFactory<
Request = T::Request, Req,
Response = U::Response, Response = U::Response,
Error = T::Error, Error = SF::Error,
Config = T::Config, Config = SF::Config,
InitError = T::InitError, InitError = SF::InitError,
Service = impl Service< Service = impl Service<Req, Response = U::Response, Error = SF::Error> + Clone,
Request = T::Request,
Response = U::Response,
Error = T::Error,
> + Clone,
> + Clone, > + Clone,
Req, Req,
> >
where where
Self: Sized, Self: Sized,
T::Config: Clone, SF::Config: Clone,
F: IntoServiceFactory<U, Req>, F: IntoServiceFactory<U, SF::Response>,
U: ServiceFactory< U: ServiceFactory<
T::Response, SF::Response,
Config = T::Config, Config = SF::Config,
Error = T::Error, Error = SF::Error,
InitError = T::InitError, InitError = SF::InitError,
>, >,
{ {
PipelineFactory { PipelineFactory {
@ -218,36 +219,35 @@ impl<T: ServiceFactory<Req>, Req> PipelineFactory<T, Req> {
} }
} }
/// Apply function to specified service and use it as a next service in /// Apply function to specified service and use it as a next service in chain.
/// chain.
/// ///
/// Short version of `pipeline_factory(...).and_then(apply_fn_factory(...))` /// Short version of `pipeline_factory(...).and_then(apply_fn_factory(...))`
pub fn and_then_apply_fn<U, I, F, Fut, Res, Err>( pub fn and_then_apply_fn<U, SF1, Fut, F, In, Res, Err>(
self, self,
factory: I, factory: U,
f: F, wrap_fn: F,
) -> PipelineFactory< ) -> PipelineFactory<
impl ServiceFactory< impl ServiceFactory<
Request = T::Request, Req,
Response = Res, Response = Res,
Error = Err, Error = Err,
Config = T::Config, Config = SF::Config,
InitError = T::InitError, InitError = SF::InitError,
Service = impl Service<Request = T::Request, Response = Res, Error = Err> + Clone, Service = impl Service<Req, Response = Res, Error = Err> + Clone,
> + Clone, > + Clone,
Req, Req,
> >
where where
Self: Sized, Self: Sized,
T::Config: Clone, SF::Config: Clone,
I: IntoServiceFactory<U, Req>, U: IntoServiceFactory<SF1, In>,
U: ServiceFactory<Req, Config = T::Config, InitError = T::InitError>, SF1: ServiceFactory<In, Config = SF::Config, InitError = SF::InitError>,
F: FnMut(T::Response, &mut U::Service) -> Fut + Clone, F: FnMut(SF::Response, &mut SF1::Service) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>, Fut: Future<Output = Result<Res, Err>>,
Err: From<T::Error> + From<U::Error>, Err: From<SF::Error> + From<SF1::Error>,
{ {
PipelineFactory { PipelineFactory {
factory: AndThenApplyFnFactory::new(self.factory, factory.into_factory(), f), factory: AndThenApplyFnFactory::new(self.factory, factory.into_factory(), wrap_fn),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
@ -263,28 +263,24 @@ impl<T: ServiceFactory<Req>, Req> PipelineFactory<T, Req> {
factory: F, factory: F,
) -> PipelineFactory< ) -> PipelineFactory<
impl ServiceFactory< impl ServiceFactory<
Request = T::Request, Req,
Response = U::Response, Response = U::Response,
Error = T::Error, Error = SF::Error,
Config = T::Config, Config = SF::Config,
InitError = T::InitError, InitError = SF::InitError,
Service = impl Service< Service = impl Service<Req, Response = U::Response, Error = SF::Error> + Clone,
Request = T::Request,
Response = U::Response,
Error = T::Error,
> + Clone,
> + Clone, > + Clone,
Req, Req,
> >
where where
Self: Sized, Self: Sized,
T::Config: Clone, SF::Config: Clone,
F: IntoServiceFactory<U, Req>, F: IntoServiceFactory<U, Result<SF::Response, SF::Error>>,
U: ServiceFactory< U: ServiceFactory<
Result<T::Response, T::Error>, Result<SF::Response, SF::Error>,
Config = T::Config, Config = SF::Config,
Error = T::Error, Error = SF::Error,
InitError = T::InitError, InitError = SF::InitError,
>, >,
{ {
PipelineFactory { PipelineFactory {
@ -295,10 +291,10 @@ impl<T: ServiceFactory<Req>, Req> PipelineFactory<T, Req> {
/// Map this service's output to a different type, returning a new service /// Map this service's output to a different type, returning a new service
/// of the resulting type. /// of the resulting type.
pub fn map<F, R>(self, f: F) -> PipelineFactory<MapServiceFactory<T, F, Req, R>, Req> pub fn map<F, R>(self, f: F) -> PipelineFactory<MapServiceFactory<SF, F, Req, R>, Req>
where where
Self: Sized, Self: Sized,
F: FnMut(T::Response) -> R + Clone, F: FnMut(SF::Response) -> R + Clone,
{ {
PipelineFactory { PipelineFactory {
factory: MapServiceFactory::new(self.factory, f), factory: MapServiceFactory::new(self.factory, f),
@ -307,10 +303,13 @@ impl<T: ServiceFactory<Req>, Req> PipelineFactory<T, Req> {
} }
/// Map this service's error to a different error, returning a new service. /// Map this service's error to a different error, returning a new service.
pub fn map_err<F, E>(self, f: F) -> PipelineFactory<MapErrServiceFactory<T, Req, F, E>, Req> pub fn map_err<F, E>(
self,
f: F,
) -> PipelineFactory<MapErrServiceFactory<SF, Req, F, E>, Req>
where where
Self: Sized, Self: Sized,
F: Fn(T::Error) -> E + Clone, F: Fn(SF::Error) -> E + Clone,
{ {
PipelineFactory { PipelineFactory {
factory: MapErrServiceFactory::new(self.factory, f), factory: MapErrServiceFactory::new(self.factory, f),
@ -319,10 +318,10 @@ impl<T: ServiceFactory<Req>, Req> PipelineFactory<T, Req> {
} }
/// Map this factory's init error to a different error, returning a new service. /// Map this factory's init error to a different error, returning a new service.
pub fn map_init_err<F, E>(self, f: F) -> PipelineFactory<MapInitErr<T, F, Req, E>, Req> pub fn map_init_err<F, E>(self, f: F) -> PipelineFactory<MapInitErr<SF, F, Req, E>, Req>
where where
Self: Sized, Self: Sized,
F: Fn(T::InitError) -> E + Clone, F: Fn(SF::InitError) -> E + Clone,
{ {
PipelineFactory { PipelineFactory {
factory: MapInitErr::new(self.factory, f), factory: MapInitErr::new(self.factory, f),