mirror of https://github.com/fafhrd91/actix-net
migrate over to pin-project-lite
This commit is contained in:
parent
663dfd35de
commit
87bca22cc7
|
@ -17,8 +17,9 @@ name = "actix_service"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures-util = "0.3.1"
|
pin-project-lite = "0.2"
|
||||||
pin-project = "1.0.0"
|
futures-util = { version = "0.3.7", default-features = false }
|
||||||
|
futures-core = { version = "0.3.7", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "1.0.0"
|
actix-rt = "1.0.0"
|
||||||
|
|
|
@ -7,6 +7,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use super::{Service, ServiceFactory};
|
use super::{Service, ServiceFactory};
|
||||||
|
|
||||||
/// Service for the `and_then` combinator, chaining a computation onto the end
|
/// Service for the `and_then` combinator, chaining a computation onto the end
|
||||||
|
@ -53,30 +55,43 @@ where
|
||||||
|
|
||||||
fn call(&mut self, req: Req) -> Self::Future {
|
fn call(&mut self, req: Req) -> Self::Future {
|
||||||
AndThenServiceResponse {
|
AndThenServiceResponse {
|
||||||
state: State::A(self.0.borrow_mut().0.call(req), Some(self.0.clone())),
|
state: State::A {
|
||||||
|
fut: self.0.borrow_mut().0.call(req),
|
||||||
|
b: Some(self.0.clone()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub(crate) struct AndThenServiceResponse<A, B, Req>
|
pub(crate) struct AndThenServiceResponse<A, B, Req>
|
||||||
where
|
where
|
||||||
A: Service<Req>,
|
A: Service<Req>,
|
||||||
B: Service<A::Response, Error = A::Error>,
|
B: Service<A::Response, Error = A::Error>,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
state: State<A, B, Req>,
|
state: State<A, B, Req>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project(project = StateProj)]
|
pin_project! {
|
||||||
enum State<A, B, Req>
|
#[project = StateProj]
|
||||||
where
|
enum State<A, B, Req>
|
||||||
A: Service<Req>,
|
where
|
||||||
B: Service<A::Response, Error = A::Error>,
|
A: Service<Req>,
|
||||||
{
|
B: Service<A::Response, Error = A::Error>,
|
||||||
A(#[pin] A::Future, Option<Rc<RefCell<(A, B)>>>),
|
{
|
||||||
B(#[pin] B::Future),
|
A {
|
||||||
Empty,
|
#[pin]
|
||||||
|
fut: A::Future,
|
||||||
|
b: Option<Rc<RefCell<(A, B)>>>,
|
||||||
|
},
|
||||||
|
B {
|
||||||
|
#[pin]
|
||||||
|
fut: B::Future,
|
||||||
|
},
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, Req> Future for AndThenServiceResponse<A, B, Req>
|
impl<A, B, Req> Future for AndThenServiceResponse<A, B, Req>
|
||||||
|
@ -90,17 +105,17 @@ where
|
||||||
let mut this = self.as_mut().project();
|
let mut this = self.as_mut().project();
|
||||||
|
|
||||||
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 = b.take().unwrap();
|
||||||
this.state.set(State::Empty); // drop fut A
|
this.state.set(State::Empty); // drop fut A
|
||||||
let fut = b.borrow_mut().1.call(res);
|
let fut = b.borrow_mut().1.call(res);
|
||||||
this.state.set(State::B(fut));
|
this.state.set(State::B { fut });
|
||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
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);
|
||||||
r
|
r
|
||||||
}),
|
}),
|
||||||
|
@ -194,19 +209,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub(crate) struct AndThenServiceFactoryResponse<A, B, Req>
|
pub(crate) struct AndThenServiceFactoryResponse<A, B, Req>
|
||||||
where
|
where
|
||||||
A: ServiceFactory<Req>,
|
A: ServiceFactory<Req>,
|
||||||
B: ServiceFactory<A::Response>,
|
B: ServiceFactory<A::Response>,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
fut_a: A::Future,
|
fut_a: A::Future,
|
||||||
#[pin]
|
#[pin]
|
||||||
fut_b: B::Future,
|
fut_b: B::Future,
|
||||||
|
|
||||||
a: Option<A::Service>,
|
a: Option<A::Service>,
|
||||||
b: Option<B::Service>,
|
b: Option<B::Service>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, Req> AndThenServiceFactoryResponse<A, B, Req>
|
impl<A, B, Req> AndThenServiceFactoryResponse<A, B, Req>
|
||||||
|
|
|
@ -1,334 +0,0 @@
|
||||||
use alloc::rc::Rc;
|
|
||||||
use core::{
|
|
||||||
cell::RefCell,
|
|
||||||
future::Future,
|
|
||||||
marker::PhantomData,
|
|
||||||
pin::Pin,
|
|
||||||
task::{Context, Poll},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{Service, ServiceFactory};
|
|
||||||
|
|
||||||
/// `Apply` service combinator
|
|
||||||
pub(crate) struct AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
S1: Service<Req>,
|
|
||||||
S2: Service<In>,
|
|
||||||
F: FnMut(S1::Response, &mut S2) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S1::Error> + From<S2::Error>,
|
|
||||||
{
|
|
||||||
svc: Rc<RefCell<(S1, S2, F)>>,
|
|
||||||
_phantom: PhantomData<(Fut, Req, In, Res, Err)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S1, S2, F, Fut, Req, In, Res, Err> AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
S1: Service<Req>,
|
|
||||||
S2: Service<In>,
|
|
||||||
F: FnMut(S1::Response, &mut S2) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S1::Error> + From<S2::Error>,
|
|
||||||
{
|
|
||||||
/// Create new `Apply` combinator
|
|
||||||
pub(crate) fn new(a: S1, b: S2, wrap_fn: F) -> Self {
|
|
||||||
Self {
|
|
||||||
svc: Rc::new(RefCell::new((a, b, wrap_fn))),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S1, S2, F, Fut, Req, In, Res, Err> Clone
|
|
||||||
for AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
S1: Service<Req>,
|
|
||||||
S2: Service<In>,
|
|
||||||
F: FnMut(S1::Response, &mut S2) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S1::Error> + From<S2::Error>,
|
|
||||||
{
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
AndThenApplyFn {
|
|
||||||
svc: self.svc.clone(),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S1, S2, F, Fut, Req, In, Res, Err> Service<Req>
|
|
||||||
for AndThenApplyFn<S1, S2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
S1: Service<Req>,
|
|
||||||
S2: Service<In>,
|
|
||||||
F: FnMut(S1::Response, &mut S2) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S1::Error> + From<S2::Error>,
|
|
||||||
{
|
|
||||||
type Response = Res;
|
|
||||||
type Error = 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.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
|
|
||||||
} else {
|
|
||||||
Poll::Ready(Ok(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: Req) -> Self::Future {
|
|
||||||
let fut = self.svc.borrow_mut().0.call(req);
|
|
||||||
AndThenApplyFnFuture {
|
|
||||||
state: State::A(fut, Some(self.svc.clone())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
|
||||||
pub(crate) struct AndThenApplyFnFuture<S1, S2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
S1: Service<Req>,
|
|
||||||
S2: Service<In>,
|
|
||||||
F: FnMut(S1::Response, &mut S2) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S1::Error> + From<S2::Error>,
|
|
||||||
{
|
|
||||||
#[pin]
|
|
||||||
state: State<S1, S2, F, Fut, Req, In, Res, Err>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pin_project::pin_project(project = StateProj)]
|
|
||||||
enum State<S1, S2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
S1: Service<Req>,
|
|
||||||
S2: Service<In>,
|
|
||||||
F: FnMut(S1::Response, &mut S2) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S1::Error> + From<S2::Error>,
|
|
||||||
{
|
|
||||||
A(#[pin] S1::Future, Option<Rc<RefCell<(S1, S2, F)>>>),
|
|
||||||
B(#[pin] Fut),
|
|
||||||
Empty(PhantomData<In>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S1, S2, F, Fut, Req, In, Res, Err> Future
|
|
||||||
for AndThenApplyFnFuture<S1, S2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
S1: Service<Req>,
|
|
||||||
S2: Service<In>,
|
|
||||||
F: FnMut(S1::Response, &mut S2) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S1::Error> + From<S2::Error>,
|
|
||||||
{
|
|
||||||
type Output = Result<Res, Err>;
|
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
let mut this = self.as_mut().project();
|
|
||||||
|
|
||||||
match this.state.as_mut().project() {
|
|
||||||
StateProj::A(fut, b) => match fut.poll(cx)? {
|
|
||||||
Poll::Ready(res) => {
|
|
||||||
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));
|
|
||||||
self.poll(cx)
|
|
||||||
}
|
|
||||||
Poll::Pending => Poll::Pending,
|
|
||||||
},
|
|
||||||
StateProj::B(fut) => fut.poll(cx).map(|r| {
|
|
||||||
this.state.set(State::Empty(PhantomData));
|
|
||||||
r
|
|
||||||
}),
|
|
||||||
StateProj::Empty(_) => {
|
|
||||||
panic!("future must not be polled after it returned `Poll::Ready`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `AndThenApplyFn` service factory
|
|
||||||
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<SF1, SF2, F, Fut, Req, In, Res, Err>
|
|
||||||
AndThenApplyFnFactory<SF1, SF2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
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<SF1::Error> + From<SF2::Error>,
|
|
||||||
{
|
|
||||||
/// Create new `ApplyNewService` new service instance
|
|
||||||
pub(crate) fn new(a: SF1, b: SF2, wrap_fn: F) -> Self {
|
|
||||||
Self {
|
|
||||||
srv: Rc::new((a, b, wrap_fn)),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SF1, SF2, F, Fut, Req, In, Res, Err> ServiceFactory<Req>
|
|
||||||
for AndThenApplyFnFactory<SF1, SF2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
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<SF1::Error> + From<SF2::Error>,
|
|
||||||
{
|
|
||||||
type Response = Res;
|
|
||||||
type Error = 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: SF1::Config) -> Self::Future {
|
|
||||||
let srv = &*self.srv;
|
|
||||||
AndThenApplyFnFactoryResponse {
|
|
||||||
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<SF1, SF2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
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<SF1::Error>,
|
|
||||||
Err: From<SF2::Error>,
|
|
||||||
{
|
|
||||||
#[pin]
|
|
||||||
fut_s1: SF1::Future,
|
|
||||||
#[pin]
|
|
||||||
fut_s2: SF2::Future,
|
|
||||||
wrap_fn: F,
|
|
||||||
s1: Option<SF1::Service>,
|
|
||||||
s2: Option<SF2::Service>,
|
|
||||||
_phantom: PhantomData<In>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SF1, SF2, F, Fut, Req, In, Res, Err> Future
|
|
||||||
for AndThenApplyFnFactoryResponse<SF1, SF2, F, Fut, Req, In, Res, Err>
|
|
||||||
where
|
|
||||||
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<SF1::Error> + From<SF2::Error>,
|
|
||||||
{
|
|
||||||
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.s1.is_none() {
|
|
||||||
if let Poll::Ready(service) = this.fut_s1.poll(cx)? {
|
|
||||||
*this.s1 = Some(service);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if this.s2.is_none() {
|
|
||||||
if let Poll::Ready(service) = this.fut_s2.poll(cx)? {
|
|
||||||
*this.s2 = Some(service);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if this.s1.is_some() && this.s2.is_some() {
|
|
||||||
Poll::Ready(Ok(AndThenApplyFn {
|
|
||||||
svc: Rc::new(RefCell::new((
|
|
||||||
Option::take(this.s1).unwrap(),
|
|
||||||
Option::take(this.s2).unwrap(),
|
|
||||||
this.wrap_fn.clone(),
|
|
||||||
))),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use futures_util::future::{lazy, ok, Ready, TryFutureExt};
|
|
||||||
|
|
||||||
use crate::{fn_service, pipeline, pipeline_factory, Service, ServiceFactory};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Srv;
|
|
||||||
|
|
||||||
impl Service<u8> for Srv {
|
|
||||||
type Response = ();
|
|
||||||
type Error = ();
|
|
||||||
type Future = Ready<Result<Self::Response, Self::Error>>;
|
|
||||||
|
|
||||||
crate::always_ready!();
|
|
||||||
|
|
||||||
fn call(&mut self, req: u8) -> Self::Future {
|
|
||||||
let _ = req;
|
|
||||||
ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn test_service() {
|
|
||||||
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!(res.is_ready());
|
|
||||||
|
|
||||||
let res = srv.call("srv").await;
|
|
||||||
assert!(res.is_ok());
|
|
||||||
assert_eq!(res.unwrap(), ("srv", ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
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(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!(res.is_ready());
|
|
||||||
|
|
||||||
let res = srv.call("srv").await;
|
|
||||||
assert!(res.is_ok());
|
|
||||||
assert_eq!(res.unwrap(), ("srv", ()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,9 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures_util::ready;
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use futures_core::ready;
|
||||||
|
|
||||||
use super::{IntoService, IntoServiceFactory, Service, ServiceFactory};
|
use super::{IntoService, IntoServiceFactory, Service, ServiceFactory};
|
||||||
|
|
||||||
|
@ -160,17 +162,18 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
|
pub struct ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
|
||||||
where
|
where
|
||||||
SF: ServiceFactory<In, Error = Err>,
|
SF: ServiceFactory<In, Error = Err>,
|
||||||
F: FnMut(Req, &mut SF::Service) -> Fut,
|
F: FnMut(Req, &mut SF::Service) -> Fut,
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
Fut: Future<Output = Result<Res, Err>>,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: SF::Future,
|
fut: SF::Future,
|
||||||
wrap_fn: Option<F>,
|
wrap_fn: Option<F>,
|
||||||
_phantom: PhantomData<(Req, Res)>,
|
_phantom: PhantomData<(Req, Res)>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SF, F, Fut, Req, In, Res, Err> ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
|
impl<SF, F, Fut, Req, In, Res, Err> ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
|
||||||
|
|
|
@ -7,6 +7,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use crate::{Service, ServiceFactory};
|
use crate::{Service, ServiceFactory};
|
||||||
|
|
||||||
/// Convert `Fn(Config, &mut Service1) -> Future<Service2>` fn to a service factory.
|
/// Convert `Fn(Config, &mut Service1) -> Future<Service2>` fn to a service factory.
|
||||||
|
@ -158,37 +160,42 @@ where
|
||||||
ApplyConfigServiceFactoryResponse {
|
ApplyConfigServiceFactoryResponse {
|
||||||
cfg: Some(cfg),
|
cfg: Some(cfg),
|
||||||
store: self.srv.clone(),
|
store: self.srv.clone(),
|
||||||
state: State::A(self.srv.borrow().0.new_service(())),
|
state: State::A {
|
||||||
|
fut: self.srv.borrow().0.new_service(()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
struct ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
|
struct ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
|
||||||
where
|
where
|
||||||
SF: ServiceFactory<Req, Config = ()>,
|
SF: ServiceFactory<Req, Config = ()>,
|
||||||
SF::InitError: From<SF::Error>,
|
SF::InitError: From<SF::Error>,
|
||||||
F: FnMut(Cfg, &mut SF::Service) -> Fut,
|
F: FnMut(Cfg, &mut SF::Service) -> Fut,
|
||||||
Fut: Future<Output = Result<S, SF::InitError>>,
|
Fut: Future<Output = Result<S, SF::InitError>>,
|
||||||
S: Service<Req>,
|
S: Service<Req>,
|
||||||
{
|
{
|
||||||
cfg: Option<Cfg>,
|
cfg: Option<Cfg>,
|
||||||
store: Rc<RefCell<(SF, F)>>,
|
store: Rc<RefCell<(SF, F)>>,
|
||||||
#[pin]
|
#[pin]
|
||||||
state: State<SF, Fut, S, Req>,
|
state: State<SF, Fut, S, Req>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project(project = StateProj)]
|
pin_project! {
|
||||||
enum State<SF, Fut, S, Req>
|
#[project = StateProj]
|
||||||
where
|
enum State<SF, Fut, S, Req>
|
||||||
SF: ServiceFactory<Req, Config = ()>,
|
where
|
||||||
SF::InitError: From<SF::Error>,
|
SF: ServiceFactory<Req, Config = ()>,
|
||||||
Fut: Future<Output = Result<S, SF::InitError>>,
|
SF::InitError: From<SF::Error>,
|
||||||
S: Service<Req>,
|
Fut: Future<Output = Result<S, SF::InitError>>,
|
||||||
{
|
S: Service<Req>,
|
||||||
A(#[pin] SF::Future),
|
{
|
||||||
B(SF::Service),
|
A { #[pin] fut: SF::Future },
|
||||||
C(#[pin] Fut),
|
B { svc: SF::Service },
|
||||||
|
C { #[pin] fut: Fut },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SF, Req, F, Cfg, Fut, S> Future
|
impl<SF, Req, F, Cfg, Fut, S> Future
|
||||||
|
@ -206,25 +213,25 @@ where
|
||||||
let mut this = self.as_mut().project();
|
let mut this = self.as_mut().project();
|
||||||
|
|
||||||
match this.state.as_mut().project() {
|
match this.state.as_mut().project() {
|
||||||
StateProj::A(fut) => match fut.poll(cx)? {
|
StateProj::A { fut } => match fut.poll(cx)? {
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
Poll::Ready(srv) => {
|
Poll::Ready(svc) => {
|
||||||
this.state.set(State::B(srv));
|
this.state.set(State::B { svc });
|
||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StateProj::B(srv) => match srv.poll_ready(cx)? {
|
StateProj::B { svc } => match svc.poll_ready(cx)? {
|
||||||
Poll::Ready(_) => {
|
Poll::Ready(_) => {
|
||||||
{
|
{
|
||||||
let (_, f) = &mut *this.store.borrow_mut();
|
let (_, f) = &mut *this.store.borrow_mut();
|
||||||
let fut = f(this.cfg.take().unwrap(), srv);
|
let fut = f(this.cfg.take().unwrap(), svc);
|
||||||
this.state.set(State::C(fut));
|
this.state.set(State::C { fut });
|
||||||
}
|
}
|
||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
},
|
},
|
||||||
StateProj::C(fut) => fut.poll(cx),
|
StateProj::C { fut } => fut.poll(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ use core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
mod and_then;
|
mod and_then;
|
||||||
mod and_then_apply_fn;
|
|
||||||
mod apply;
|
mod apply;
|
||||||
mod apply_cfg;
|
mod apply_cfg;
|
||||||
pub mod boxed;
|
pub mod boxed;
|
||||||
|
|
|
@ -5,6 +5,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use super::{Service, ServiceFactory};
|
use super::{Service, ServiceFactory};
|
||||||
|
|
||||||
/// Service for the `map` combinator, changing the type of a service's response.
|
/// Service for the `map` combinator, changing the type of a service's response.
|
||||||
|
@ -61,15 +63,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct MapFuture<A, F, Req, Res>
|
pub struct MapFuture<A, F, Req, Res>
|
||||||
where
|
where
|
||||||
A: Service<Req>,
|
A: Service<Req>,
|
||||||
F: FnMut(A::Response) -> Res,
|
F: FnMut(A::Response) -> Res,
|
||||||
{
|
{
|
||||||
f: F,
|
f: F,
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: A::Future,
|
fut: A::Future,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, F, Req, Res> MapFuture<A, F, Req, Res>
|
impl<A, F, Req, Res> MapFuture<A, F, Req, Res>
|
||||||
|
@ -154,15 +157,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct MapServiceFuture<A, F, Req, Res>
|
pub struct MapServiceFuture<A, F, Req, Res>
|
||||||
where
|
where
|
||||||
A: ServiceFactory<Req>,
|
A: ServiceFactory<Req>,
|
||||||
F: FnMut(A::Response) -> Res,
|
F: FnMut(A::Response) -> Res,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: A::Future,
|
fut: A::Future,
|
||||||
f: Option<F>,
|
f: Option<F>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, F, Req, Res> MapServiceFuture<A, F, Req, Res>
|
impl<A, F, Req, Res> MapServiceFuture<A, F, Req, Res>
|
||||||
|
|
|
@ -5,6 +5,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use super::{Service, ServiceFactory};
|
use super::{Service, ServiceFactory};
|
||||||
|
|
||||||
/// Service for the `map_err` combinator, changing the type of a service's
|
/// Service for the `map_err` combinator, changing the type of a service's
|
||||||
|
@ -64,15 +66,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct MapErrFuture<A, Req, F, E>
|
pub struct MapErrFuture<A, Req, F, E>
|
||||||
where
|
where
|
||||||
A: Service<Req>,
|
A: Service<Req>,
|
||||||
F: Fn(A::Error) -> E,
|
F: Fn(A::Error) -> E,
|
||||||
{
|
{
|
||||||
f: F,
|
f: F,
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: A::Future,
|
fut: A::Future,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, Req, F, E> MapErrFuture<A, Req, F, E>
|
impl<A, Req, F, E> MapErrFuture<A, Req, F, E>
|
||||||
|
@ -159,15 +162,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct MapErrServiceFuture<A, Req, F, E>
|
pub struct MapErrServiceFuture<A, Req, F, E>
|
||||||
where
|
where
|
||||||
A: ServiceFactory<Req>,
|
A: ServiceFactory<Req>,
|
||||||
F: Fn(A::Error) -> E,
|
F: Fn(A::Error) -> E,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: A::Future,
|
fut: A::Future,
|
||||||
f: F,
|
f: F,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, Req, F, E> MapErrServiceFuture<A, Req, F, E>
|
impl<A, Req, F, E> MapErrServiceFuture<A, Req, F, E>
|
||||||
|
|
|
@ -5,6 +5,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use super::ServiceFactory;
|
use super::ServiceFactory;
|
||||||
|
|
||||||
/// `MapInitErr` service combinator
|
/// `MapInitErr` service combinator
|
||||||
|
@ -61,15 +63,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct MapInitErrFuture<A, F, Req, 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,
|
||||||
{
|
{
|
||||||
f: F,
|
f: F,
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: A::Future,
|
fut: A::Future,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, F, Req, E> MapInitErrFuture<A, F, Req, E>
|
impl<A, F, Req, E> MapInitErrFuture<A, F, Req, E>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
use core::{
|
use core::{
|
||||||
future::Future,
|
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::and_then::{AndThenService, AndThenServiceFactory};
|
use crate::and_then::{AndThenService, AndThenServiceFactory};
|
||||||
use crate::and_then_apply_fn::{AndThenApplyFn, AndThenApplyFnFactory};
|
|
||||||
use crate::map::{Map, MapServiceFactory};
|
use crate::map::{Map, MapServiceFactory};
|
||||||
use crate::map_err::{MapErr, MapErrServiceFactory};
|
use crate::map_err::{MapErr, MapErrServiceFactory};
|
||||||
use crate::map_init_err::MapInitErr;
|
use crate::map_init_err::MapInitErr;
|
||||||
|
@ -70,28 +68,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply function to specified service and use it as a next service in chain.
|
|
||||||
///
|
|
||||||
/// Short version of `pipeline_factory(...).and_then(apply_fn(...))`
|
|
||||||
pub fn and_then_apply_fn<I, S1, F, Fut, In, Res, Err>(
|
|
||||||
self,
|
|
||||||
service: I,
|
|
||||||
wrap_fn: F,
|
|
||||||
) -> Pipeline<impl Service<Req, Response = Res, Error = Err> + Clone, Req>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
I: IntoService<S1, In>,
|
|
||||||
S1: Service<In>,
|
|
||||||
F: FnMut(S::Response, &mut S1) -> Fut,
|
|
||||||
Fut: Future<Output = Result<Res, Err>>,
|
|
||||||
Err: From<S::Error> + From<S1::Error>,
|
|
||||||
{
|
|
||||||
Pipeline {
|
|
||||||
service: AndThenApplyFn::new(self.service, service.into_service(), wrap_fn),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Chain on a computation for when a call to the service finished,
|
/// Chain on a computation for when a call to the service finished,
|
||||||
/// passing the result of the call to the next service `U`.
|
/// passing the result of the call to the next service `U`.
|
||||||
///
|
///
|
||||||
|
@ -222,39 +198,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<I, SF1, Fut, F, In, Res, Err>(
|
|
||||||
self,
|
|
||||||
factory: I,
|
|
||||||
wrap_fn: F,
|
|
||||||
) -> PipelineFactory<
|
|
||||||
impl ServiceFactory<
|
|
||||||
Req,
|
|
||||||
Response = Res,
|
|
||||||
Error = Err,
|
|
||||||
Config = SF::Config,
|
|
||||||
InitError = SF::InitError,
|
|
||||||
Service = impl Service<Req, Response = Res, Error = Err> + Clone,
|
|
||||||
> + Clone,
|
|
||||||
Req,
|
|
||||||
>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
SF::Config: Clone,
|
|
||||||
I: 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<SF::Error> + From<SF1::Error>,
|
|
||||||
{
|
|
||||||
PipelineFactory {
|
|
||||||
factory: AndThenApplyFnFactory::new(self.factory, factory.into_factory(), wrap_fn),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create `NewService` to chain on a computation for when a call to the
|
/// Create `NewService` to chain on a computation for when a call to the
|
||||||
/// service finished, passing the result of the call to the next
|
/// service finished, passing the result of the call to the next
|
||||||
/// service `U`.
|
/// service `U`.
|
||||||
|
|
|
@ -7,6 +7,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use super::{Service, ServiceFactory};
|
use super::{Service, ServiceFactory};
|
||||||
|
|
||||||
/// Service for the `then` combinator, chaining a computation onto the end of
|
/// Service for the `then` combinator, chaining a computation onto the end of
|
||||||
|
@ -53,30 +55,36 @@ where
|
||||||
|
|
||||||
fn call(&mut self, req: Req) -> Self::Future {
|
fn call(&mut self, req: Req) -> Self::Future {
|
||||||
ThenServiceResponse {
|
ThenServiceResponse {
|
||||||
state: State::A(self.0.borrow_mut().0.call(req), Some(self.0.clone())),
|
state: State::A {
|
||||||
|
fut: self.0.borrow_mut().0.call(req),
|
||||||
|
b: Some(self.0.clone()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub(crate) struct ThenServiceResponse<A, B, Req>
|
pub(crate) struct ThenServiceResponse<A, B, Req>
|
||||||
where
|
where
|
||||||
A: Service<Req>,
|
A: Service<Req>,
|
||||||
B: Service<Result<A::Response, A::Error>>,
|
B: Service<Result<A::Response, A::Error>>,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
state: State<A, B, Req>,
|
state: State<A, B, Req>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project(project = StateProj)]
|
pin_project! {
|
||||||
enum State<A, B, Req>
|
#[project = StateProj]
|
||||||
where
|
enum State<A, B, Req>
|
||||||
A: Service<Req>,
|
where
|
||||||
B: Service<Result<A::Response, A::Error>>,
|
A: Service<Req>,
|
||||||
{
|
B: Service<Result<A::Response, A::Error>>,
|
||||||
A(#[pin] A::Future, Option<Rc<RefCell<(A, B)>>>),
|
{
|
||||||
B(#[pin] B::Future),
|
A { #[pin] fut: A::Future, b: Option<Rc<RefCell<(A, B)>>> },
|
||||||
Empty,
|
B { #[pin] fut: B::Future },
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, Req> Future for ThenServiceResponse<A, B, Req>
|
impl<A, B, Req> Future for ThenServiceResponse<A, B, Req>
|
||||||
|
@ -90,17 +98,17 @@ where
|
||||||
let mut this = self.as_mut().project();
|
let mut this = self.as_mut().project();
|
||||||
|
|
||||||
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 = b.take().unwrap();
|
||||||
this.state.set(State::Empty); // drop fut A
|
this.state.set(State::Empty); // drop fut A
|
||||||
let fut = b.borrow_mut().1.call(res);
|
let fut = b.borrow_mut().1.call(res);
|
||||||
this.state.set(State::B(fut));
|
this.state.set(State::B { fut });
|
||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
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);
|
||||||
r
|
r
|
||||||
}),
|
}),
|
||||||
|
@ -162,23 +170,24 @@ impl<A, B, Req> Clone for ThenServiceFactory<A, B, Req> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub(crate) struct ThenServiceFactoryResponse<A, B, Req>
|
pub(crate) struct ThenServiceFactoryResponse<A, B, Req>
|
||||||
where
|
where
|
||||||
A: ServiceFactory<Req>,
|
A: ServiceFactory<Req>,
|
||||||
B: ServiceFactory<
|
B: ServiceFactory<
|
||||||
Result<A::Response, A::Error>,
|
Result<A::Response, A::Error>,
|
||||||
Config = A::Config,
|
Config = A::Config,
|
||||||
Error = A::Error,
|
Error = A::Error,
|
||||||
InitError = A::InitError,
|
InitError = A::InitError,
|
||||||
>,
|
>,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
fut_b: B::Future,
|
fut_b: B::Future,
|
||||||
#[pin]
|
#[pin]
|
||||||
fut_a: A::Future,
|
fut_a: A::Future,
|
||||||
a: Option<A::Service>,
|
a: Option<A::Service>,
|
||||||
b: Option<B::Service>,
|
b: Option<B::Service>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, Req> ThenServiceFactoryResponse<A, B, Req>
|
impl<A, B, Req> ThenServiceFactoryResponse<A, B, Req>
|
||||||
|
|
|
@ -6,6 +6,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use crate::transform_err::TransformMapInitErr;
|
use crate::transform_err::TransformMapInitErr;
|
||||||
use crate::{IntoServiceFactory, Service, ServiceFactory};
|
use crate::{IntoServiceFactory, Service, ServiceFactory};
|
||||||
|
|
||||||
|
@ -187,30 +189,35 @@ where
|
||||||
fn new_service(&self, cfg: S::Config) -> Self::Future {
|
fn new_service(&self, cfg: S::Config) -> Self::Future {
|
||||||
ApplyTransformFuture {
|
ApplyTransformFuture {
|
||||||
store: self.0.clone(),
|
store: self.0.clone(),
|
||||||
state: ApplyTransformFutureState::A(self.0.as_ref().1.new_service(cfg)),
|
state: ApplyTransformFutureState::A {
|
||||||
|
fut: self.0.as_ref().1.new_service(cfg),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct ApplyTransformFuture<T, S, Req>
|
pub struct ApplyTransformFuture<T, S, Req>
|
||||||
where
|
where
|
||||||
S: ServiceFactory<Req>,
|
S: ServiceFactory<Req>,
|
||||||
T: Transform<S::Service, Req, InitError = S::InitError>,
|
T: Transform<S::Service, Req, InitError = S::InitError>,
|
||||||
{
|
{
|
||||||
store: Rc<(T, S)>,
|
store: Rc<(T, S)>,
|
||||||
#[pin]
|
#[pin]
|
||||||
state: ApplyTransformFutureState<T, S, Req>,
|
state: ApplyTransformFutureState<T, S, Req>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project(project = ApplyTransformFutureStateProj)]
|
pin_project! {
|
||||||
pub enum ApplyTransformFutureState<T, S, Req>
|
#[project = ApplyTransformFutureStateProj]
|
||||||
where
|
pub enum ApplyTransformFutureState<T, S, Req>
|
||||||
S: ServiceFactory<Req>,
|
where
|
||||||
T: Transform<S::Service, Req, InitError = S::InitError>,
|
S: ServiceFactory<Req>,
|
||||||
{
|
T: Transform<S::Service, Req, InitError = S::InitError>,
|
||||||
A(#[pin] S::Future),
|
{
|
||||||
B(#[pin] T::Future),
|
A { #[pin] fut: S::Future },
|
||||||
|
B { #[pin] fut: T::Future },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S, Req> Future for ApplyTransformFuture<T, S, Req>
|
impl<T, S, Req> Future for ApplyTransformFuture<T, S, Req>
|
||||||
|
@ -224,15 +231,15 @@ where
|
||||||
let mut this = self.as_mut().project();
|
let mut this = self.as_mut().project();
|
||||||
|
|
||||||
match this.state.as_mut().project() {
|
match this.state.as_mut().project() {
|
||||||
ApplyTransformFutureStateProj::A(fut) => match fut.poll(cx)? {
|
ApplyTransformFutureStateProj::A { fut } => match fut.poll(cx)? {
|
||||||
Poll::Ready(srv) => {
|
Poll::Ready(srv) => {
|
||||||
let fut = this.store.0.new_transform(srv);
|
let fut = this.store.0.new_transform(srv);
|
||||||
this.state.set(ApplyTransformFutureState::B(fut));
|
this.state.set(ApplyTransformFutureState::B { fut });
|
||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
},
|
},
|
||||||
ApplyTransformFutureStateProj::B(fut) => fut.poll(cx),
|
ApplyTransformFutureStateProj::B { fut } => fut.poll(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ use core::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use super::Transform;
|
use super::Transform;
|
||||||
|
|
||||||
/// Transform for the `map_init_err` combinator, changing the type of a new
|
/// Transform for the `map_init_err` combinator, changing the type of a new
|
||||||
|
@ -65,15 +67,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
pin_project! {
|
||||||
pub struct TransformMapInitErrFuture<T, S, F, E, Req>
|
pub struct TransformMapInitErrFuture<T, S, F, E, Req>
|
||||||
where
|
where
|
||||||
T: Transform<S, Req>,
|
T: Transform<S, Req>,
|
||||||
F: Fn(T::InitError) -> E,
|
F: Fn(T::InitError) -> E,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: T::Future,
|
fut: T::Future,
|
||||||
f: F,
|
f: F,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S, F, E, Req> Future for TransformMapInitErrFuture<T, S, F, E, Req>
|
impl<T, S, F, E, Req> Future for TransformMapInitErrFuture<T, S, F, E, Req>
|
||||||
|
|
Loading…
Reference in New Issue