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

View File

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

View File

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

View File

@ -68,7 +68,7 @@ where
S: Service<Req>,
{
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>
@ -116,7 +116,7 @@ where
S: Service<Req>,
{
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>

View File

@ -1,6 +1,6 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::{future::Future, marker::PhantomData};
use futures_util::future::FutureExt;
@ -36,9 +36,10 @@ where
pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error>
where
S: Service<Req> + 'static,
Req: 'static,
S::Future: 'static,
{
Box::new(ServiceWrapper(service))
Box::new(ServiceWrapper(service, PhantomData))
}
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,
_t: std::marker::PhantomData<C>,
_t: PhantomData<(C, 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>
where
S: Service<Req> + 'static,
Req: 'static,
S::Future: 'static,
{
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>(
f: F,
) -> FnServiceNoConfig<F, Cfg, Srv, Fut, Req, Err>
) -> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
where
Srv: Service<Req>,
F: Fn() -> Fut,
@ -247,7 +247,7 @@ where
Srv: Service<Req>,
{
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>
@ -303,7 +303,7 @@ where
Fut: Future<Output = Result<Srv, Err>>,
{
f: F,
_t: PhantomData<Cfg>,
_t: PhantomData<(Cfg, Req)>,
}
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`
pub trait IntoService<T, Req>
pub trait IntoService<S, Req>
where
T: Service<Req>,
S: Service<Req>,
{
/// Convert to a `Service`
fn into_service(self) -> T;
fn into_service(self) -> S;
}
/// Trait for types that can be converted to a `ServiceFactory`
pub trait IntoServiceFactory<T, Req>
pub trait IntoServiceFactory<SF, Req>
where
T: ServiceFactory<Req>,
SF: ServiceFactory<Req>,
{
/// 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
T: Service<Req>,
S: Service<Req>,
{
fn into_service(self) -> T {
fn into_service(self) -> S {
self
}
}
impl<T, Req> IntoServiceFactory<T, Req> for T
impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where
T: ServiceFactory<Req>,
SF: ServiceFactory<Req>,
{
fn into_factory(self) -> T {
fn into_factory(self) -> SF {
self
}
}
/// 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
U: IntoService<S, Req>,
S: Service<Req>,
T: IntoService<S, Req>,
{
tp.into_service()
}
pub mod dev {
pub use crate::apply::{Apply, ApplyServiceFactory};
pub use crate::apply::{Apply, ApplyFactory};
pub use crate::fn_service::{
FnService, FnServiceConfig, FnServiceFactory, FnServiceNoConfig,
};

View File

@ -104,7 +104,7 @@ where
pub struct MapServiceFactory<A, F, Req, Res> {
a: A,
f: F,
r: PhantomData<Res>,
r: PhantomData<(Res, Req)>,
}
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
/// 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
T: ServiceFactory<Req>,
U: IntoServiceFactory<T, Req>,
F: Fn(C) -> T::Config,
U: IntoServiceFactory<SF, Req>,
SF: ServiceFactory<Req>,
F: Fn(Cfg) -> SF::Config,
{
MapConfig::new(factory.into_factory(), f)
}
/// Replace config with unit
pub fn unit_config<T, U, C, Req>(factory: U) -> UnitConfig<T, C, Req>
/// Replace config with unit.
pub fn unit_config<U, SF, Cfg, Req>(factory: U) -> UnitConfig<SF, Cfg, Req>
where
T: ServiceFactory<Req, Config = ()>,
U: IntoServiceFactory<T, Req>,
U: IntoServiceFactory<SF, Req>,
SF: ServiceFactory<Req, Config = ()>,
{
UnitConfig::new(factory.into_factory())
}
/// `map_config()` adapter service factory
pub struct MapConfig<A, Req, F, C> {
a: A,
f: F,
e: PhantomData<(C, Req)>,
pub struct MapConfig<SF, Req, F, Cfg> {
factory: SF,
cfg_mapper: F,
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
pub(crate) fn new(a: T, f: F) -> Self
pub(crate) fn new(factory: SF, cfg_mapper: F) -> Self
where
T: ServiceFactory<Req>,
F: Fn(C) -> T::Config,
SF: ServiceFactory<Req>,
F: Fn(Cfg) -> SF::Config,
{
Self {
a,
f,
factory,
cfg_mapper,
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
T: Clone,
SF: Clone,
F: Clone,
{
fn clone(&self) -> Self {
Self {
a: self.a.clone(),
f: self.f.clone(),
factory: self.factory.clone(),
cfg_mapper: self.cfg_mapper.clone(),
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
T: ServiceFactory<Req>,
F: Fn(C) -> T::Config,
SF: ServiceFactory<Req>,
F: Fn(Cfg) -> SF::Config,
{
type Response = T::Response;
type Error = T::Error;
type Response = SF::Response;
type Error = SF::Error;
type Config = C;
type Service = T::Service;
type InitError = T::InitError;
type Future = T::Future;
type Config = Cfg;
type Service = SF::Service;
type InitError = SF::InitError;
type Future = SF::Future;
fn new_service(&self, cfg: C) -> Self::Future {
self.a.new_service((self.f)(cfg))
fn new_service(&self, cfg: Self::Config) -> Self::Future {
let mapped_cfg = (self.cfg_mapper)(cfg);
self.factory.new_service(mapped_cfg)
}
}
/// `unit_config()` config combinator
pub struct UnitConfig<T, C, Req> {
a: T,
e: PhantomData<(C, Req)>,
pub struct UnitConfig<SF, Cfg, Req> {
factory: SF,
_phantom: PhantomData<(Cfg, Req)>,
}
impl<T, C, Req> UnitConfig<T, C, Req>
impl<SF, Cfg, Req> UnitConfig<SF, Cfg, Req>
where
T: ServiceFactory<Req, Config = ()>,
SF: ServiceFactory<Req, Config = ()>,
{
/// Create new `UnitConfig` combinator
pub(crate) fn new(a: T) -> Self {
Self { a, e: PhantomData }
}
}
impl<T, C, Req> Clone for UnitConfig<T, C, Req>
where
T: Clone,
{
fn clone(&self) -> Self {
pub(crate) fn new(factory: SF) -> Self {
Self {
a: self.a.clone(),
e: PhantomData,
factory,
_phantom: PhantomData,
}
}
}
impl<T, C, Req> ServiceFactory<Req> for UnitConfig<T, C, Req>
impl<SF, Cfg, Req> Clone for UnitConfig<SF, Cfg, Req>
where
T: ServiceFactory<Req, Config = ()>,
SF: Clone,
{
type Response = T::Response;
type Error = T::Error;
type Config = C;
type Service = T::Service;
type InitError = T::InitError;
type Future = T::Future;
fn new_service(&self, _: C) -> Self::Future {
self.a.new_service(())
fn clone(&self) -> Self {
Self {
factory: self.factory.clone(),
_phantom: PhantomData,
}
}
}
impl<SF, Cfg, Req> ServiceFactory<Req> for UnitConfig<SF, Cfg, Req>
where
SF: ServiceFactory<Req, Config = ()>,
{
type Response = SF::Response;
type Error = SF::Error;
type Config = Cfg;
type Service = SF::Service;
type InitError = SF::InitError;
type Future = SF::Future;
fn new_service(&self, _: Cfg) -> Self::Future {
self.factory.new_service(())
}
}

View File

@ -12,7 +12,7 @@ use super::{Service, ServiceFactory};
pub struct MapErr<S, Req, F, E> {
service: S,
f: F,
_t: PhantomData<E>,
_t: PhantomData<(E, Req)>,
}
impl<S, Req, F, E> MapErr<S, Req, F, E> {
@ -107,7 +107,7 @@ where
{
a: A,
f: F,
e: PhantomData<E>,
e: PhantomData<(E, Req)>,
}
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)>,
}
impl<A, Req, F, Err> MapInitErr<A, Req, F, Err>
impl<A, F, Req, Err> MapInitErr<A, F, Req, Err>
where
A: ServiceFactory<Req>,
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
A: ServiceFactory<Req>,
F: Fn(A::InitError) -> E + Clone,
@ -52,7 +52,7 @@ where
type Config = A::Config;
type Service = A::Service;
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 {
MapInitErrFuture::new(self.a.new_service(cfg), self.f.clone())
@ -60,7 +60,7 @@ where
}
#[pin_project::pin_project]
pub struct MapInitErrFuture<A, Req, F, E>
pub struct MapInitErrFuture<A, F, Req, E>
where
A: ServiceFactory<Req>,
F: Fn(A::InitError) -> E,
@ -70,7 +70,7 @@ where
fut: A::Future,
}
impl<A, Req, F, E> MapInitErrFuture<A, Req, F, E>
impl<A, F, Req, E> MapInitErrFuture<A, F, Req, E>
where
A: ServiceFactory<Req>,
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
A: ServiceFactory<Req>,
F: Fn(A::InitError) -> E,

View File

@ -10,10 +10,10 @@ use crate::then::{ThenService, ThenServiceFactory};
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
/// 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
F: IntoService<T, Req>,
T: Service<Req>,
U: IntoService<S, Req>,
S: Service<Req>,
{
Pipeline {
service: service.into_service(),
@ -22,10 +22,10 @@ where
}
/// 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
T: ServiceFactory<Req>,
F: IntoServiceFactory<T, Req>,
U: IntoServiceFactory<SF, Req>,
SF: ServiceFactory<Req>,
{
PipelineFactory {
factory: factory.into_factory(),
@ -34,12 +34,15 @@ where
}
/// Pipeline service - pipeline allows to compose multiple service into one service.
pub struct Pipeline<T, Req> {
service: T,
pub struct Pipeline<S, Req> {
service: S,
_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.
///
/// 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>(
self,
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
Self: Sized,
F: IntoService<U, Req>,
U: Service<T::Response, Error = T::Error>,
F: IntoService<U, S::Response>,
U: Service<S::Response, Error = S::Error>,
{
Pipeline {
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
/// chain.
/// Apply function to specified service and use it as a next service in chain.
///
/// Short version of `pipeline_factory(...).and_then(apply_fn_factory(...))`
pub fn and_then_apply_fn<U, I, F, Fut, Res, Err>(
/// Short version of `pipeline_factory(...).and_then(apply_fn(...))`
pub fn and_then_apply_fn<U, S1, F, Fut, In, Res, Err>(
self,
service: I,
f: F,
service: U,
wrap_fn: F,
) -> Pipeline<impl Service<Req, Response = Res, Error = Err> + Clone, Req>
where
Self: Sized,
I: IntoService<U, Req>,
U: Service<Req>,
F: FnMut(T::Response, &mut U) -> Fut,
U: IntoService<S1, In>,
S1: Service<In>,
F: FnMut(S::Response, &mut S1) -> Fut,
Fut: Future<Output = Result<Res, Err>>,
Err: From<T::Error> + From<U::Error>,
Err: From<S::Error> + From<S1::Error>,
{
Pipeline {
service: AndThenApplyFn::new(self.service, service.into_service(), f),
service: AndThenApplyFn::new(self.service, service.into_service(), wrap_fn),
_phantom: PhantomData,
}
}
@ -95,11 +97,11 @@ impl<T: Service<Req>, Req> Pipeline<T, Req> {
pub fn then<F, U>(
self,
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
Self: Sized,
F: IntoService<U, Req>,
U: Service<Result<T::Response, T::Error>, Error = T::Error>,
F: IntoService<U, Result<S::Response, S::Error>>,
U: Service<Result<S::Response, S::Error>, Error = S::Error>,
{
Pipeline {
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
/// wrapped version of it, similar to the existing `map` methods in the
/// 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
Self: Sized,
F: FnMut(T::Response) -> R,
F: FnMut(S::Response) -> R,
{
Pipeline {
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
/// 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
Self: Sized,
F: Fn(T::Error) -> E,
F: Fn(S::Error) -> E,
{
Pipeline {
service: MapErr::new(self.service, f),
@ -176,40 +178,39 @@ impl<T: Service<Req>, Req> Service<Req> for Pipeline<T, Req> {
}
/// Pipeline factory
pub struct PipelineFactory<T, Req> {
factory: T,
pub struct PipelineFactory<SF, Req> {
factory: SF,
_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.
pub fn and_then<F, U>(
self,
factory: F,
) -> PipelineFactory<
impl ServiceFactory<
Request = T::Request,
Req,
Response = U::Response,
Error = T::Error,
Config = T::Config,
InitError = T::InitError,
Service = impl Service<
Request = T::Request,
Response = U::Response,
Error = T::Error,
> + Clone,
Error = SF::Error,
Config = SF::Config,
InitError = SF::InitError,
Service = impl Service<Req, Response = U::Response, Error = SF::Error> + Clone,
> + Clone,
Req,
>
where
Self: Sized,
T::Config: Clone,
F: IntoServiceFactory<U, Req>,
SF::Config: Clone,
F: IntoServiceFactory<U, SF::Response>,
U: ServiceFactory<
T::Response,
Config = T::Config,
Error = T::Error,
InitError = T::InitError,
SF::Response,
Config = SF::Config,
Error = SF::Error,
InitError = SF::InitError,
>,
{
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
/// chain.
/// Apply function to specified service and use it as a next service in chain.
///
/// 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,
factory: I,
f: F,
factory: U,
wrap_fn: F,
) -> PipelineFactory<
impl ServiceFactory<
Request = T::Request,
Req,
Response = Res,
Error = Err,
Config = T::Config,
InitError = T::InitError,
Service = impl Service<Request = T::Request, Response = Res, Error = Err> + Clone,
Config = SF::Config,
InitError = SF::InitError,
Service = impl Service<Req, Response = Res, Error = Err> + Clone,
> + Clone,
Req,
>
where
Self: Sized,
T::Config: Clone,
I: IntoServiceFactory<U, Req>,
U: ServiceFactory<Req, Config = T::Config, InitError = T::InitError>,
F: FnMut(T::Response, &mut U::Service) -> Fut + Clone,
SF::Config: Clone,
U: IntoServiceFactory<SF1, In>,
SF1: ServiceFactory<In, Config = SF::Config, InitError = SF::InitError>,
F: FnMut(SF::Response, &mut SF1::Service) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>,
Err: From<T::Error> + From<U::Error>,
Err: From<SF::Error> + From<SF1::Error>,
{
PipelineFactory {
factory: AndThenApplyFnFactory::new(self.factory, factory.into_factory(), f),
factory: AndThenApplyFnFactory::new(self.factory, factory.into_factory(), wrap_fn),
_phantom: PhantomData,
}
}
@ -263,28 +263,24 @@ impl<T: ServiceFactory<Req>, Req> PipelineFactory<T, Req> {
factory: F,
) -> PipelineFactory<
impl ServiceFactory<
Request = T::Request,
Req,
Response = U::Response,
Error = T::Error,
Config = T::Config,
InitError = T::InitError,
Service = impl Service<
Request = T::Request,
Response = U::Response,
Error = T::Error,
> + Clone,
Error = SF::Error,
Config = SF::Config,
InitError = SF::InitError,
Service = impl Service<Req, Response = U::Response, Error = SF::Error> + Clone,
> + Clone,
Req,
>
where
Self: Sized,
T::Config: Clone,
F: IntoServiceFactory<U, Req>,
SF::Config: Clone,
F: IntoServiceFactory<U, Result<SF::Response, SF::Error>>,
U: ServiceFactory<
Result<T::Response, T::Error>,
Config = T::Config,
Error = T::Error,
InitError = T::InitError,
Result<SF::Response, SF::Error>,
Config = SF::Config,
Error = SF::Error,
InitError = SF::InitError,
>,
{
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
/// 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
Self: Sized,
F: FnMut(T::Response) -> R + Clone,
F: FnMut(SF::Response) -> R + Clone,
{
PipelineFactory {
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.
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
Self: Sized,
F: Fn(T::Error) -> E + Clone,
F: Fn(SF::Error) -> E + Clone,
{
PipelineFactory {
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.
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
Self: Sized,
F: Fn(T::InitError) -> E + Clone,
F: Fn(SF::InitError) -> E + Clone,
{
PipelineFactory {
factory: MapInitErr::new(self.factory, f),