1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-06-28 21:10:37 +02:00

Migrate actix-net to std::future (#64)

* Migrate actix-codec, actix-rt, and actix-threadpool to std::future

* update to latest tokio alpha and futures-rs

* Migrate actix-service to std::future,

This is a squash of ~8 commits, since it included a lot of experimentation. To see the commits,
look into the semtexzv/std-future-service-tmp branch.

* update futures-rs and tokio

* Migrate actix-threadpool to std::future (#59)

* Migrate actix-threadpool to std::future

* Cosmetic refactor

- turn log::error! into log::warn! as it doesn't throw any error
- add Clone and Copy impls for Cancelled making it cheap to operate with
- apply rustfmt

* Bump up crate version to 0.2.0 and pre-fill its changelog

* Disable patching 'actix-threadpool' crate in global workspace as unnecessary

* Revert patching and fix 'actix-rt'

* Migrate actix-rt to std::future (#47)

* remove Pin from Service::poll_ready(); simplify combinators api; make code compile

* disable tests

* update travis config

* refactor naming

* drop IntoFuture trait

* Migrate actix-server to std::future (#50)

Still not finished, this is more WIP, this is an aggregation of several commits, which
can be found in semtexzv/std-future-server-tmp branch

* update actix-server

* rename Factor to ServiceFactory

* start server worker in start mehtod

* update actix-utils

* remove IntoTransform trait

* Migrate actix-server::ssl::nativetls to std futures (#61)

* Refactor 'nativetls' module

* Migrate 'actix-server-config' to std futures

- remove "uds" feature
- disable features by default

* Switch NativeTlsAcceptor to use 'tokio-tls' crate

* Bikeshed features names and remove unnecessary dependencies for 'actix-server-config' crate

* update openssl impl

* migrate actix-connect to std::future

* migrate actix-ioframe to std::future

* update version to alpha.1

* fix boxed service

* migrate server rustls support

* migratte openssl and rustls connecttors

* store the thread's handle with arbiter (#62)

* update ssl connect tests

* restore service tests

* update readme
This commit is contained in:
Nikolay Kim
2019-11-14 18:38:24 +06:00
committed by GitHub
parent 9fa2a36b4e
commit 13049b80ca
92 changed files with 4273 additions and 4165 deletions

View File

@ -1,6 +1,10 @@
use futures::{Async, Future, Poll};
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use super::{IntoNewService, NewService, Service};
use pin_project::pin_project;
use super::{Service, ServiceFactory};
use crate::cell::Cell;
/// Service for the `and_then` combinator, chaining a computation onto the end
@ -45,12 +49,12 @@ where
type Error = A::Error;
type Future = AndThenFuture<A, B>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
let not_ready = self.a.poll_ready()?.is_not_ready();
if self.b.get_mut().poll_ready()?.is_not_ready() || not_ready {
Ok(Async::NotReady)
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let not_ready = !self.a.poll_ready(cx)?.is_ready();
if !self.b.get_mut().poll_ready(cx)?.is_ready() || not_ready {
Poll::Pending
} else {
Ok(Async::Ready(()))
Poll::Ready(Ok(()))
}
}
@ -59,13 +63,16 @@ where
}
}
#[pin_project]
pub struct AndThenFuture<A, B>
where
A: Service,
B: Service<Request = A::Response, Error = A::Error>,
{
b: Cell<B>,
#[pin]
fut_b: Option<B::Future>,
#[pin]
fut_a: Option<A::Future>,
}
@ -88,22 +95,33 @@ where
A: Service,
B: Service<Request = A::Response, Error = A::Error>,
{
type Item = B::Response;
type Error = A::Error;
type Output = Result<B::Response, A::Error>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut_b {
return fut.poll();
}
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
match self.fut_a.as_mut().expect("Bug in actix-service").poll() {
Ok(Async::Ready(resp)) => {
let _ = self.fut_a.take();
self.fut_b = Some(self.b.get_mut().call(resp));
self.poll()
loop {
let mut fut_a = this.fut_a.as_mut();
let mut fut_b = this.fut_b.as_mut();
if let Some(fut) = fut_b.as_mut().as_pin_mut() {
return fut.poll(cx);
}
match fut_a
.as_mut()
.as_pin_mut()
.expect("Bug in actix-service")
.poll(cx)
{
Poll::Ready(Ok(resp)) => {
fut_a.set(None);
let new_fut = this.b.get_mut().call(resp);
fut_b.set(Some(new_fut));
}
Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),
Poll::Pending => return Poll::Pending,
}
Ok(Async::NotReady) => Ok(Async::NotReady),
Err(err) => Err(err),
}
}
}
@ -111,8 +129,8 @@ where
/// `AndThenNewService` new service combinator
pub struct AndThenNewService<A, B>
where
A: NewService,
B: NewService,
A: ServiceFactory,
B: ServiceFactory,
{
a: A,
b: B,
@ -120,8 +138,8 @@ where
impl<A, B> AndThenNewService<A, B>
where
A: NewService,
B: NewService<
A: ServiceFactory,
B: ServiceFactory<
Config = A::Config,
Request = A::Response,
Error = A::Error,
@ -129,18 +147,15 @@ where
>,
{
/// Create new `AndThen` combinator
pub fn new<F: IntoNewService<B>>(a: A, f: F) -> Self {
Self {
a,
b: f.into_new_service(),
}
pub fn new(a: A, b: B) -> Self {
Self { a, b }
}
}
impl<A, B> NewService for AndThenNewService<A, B>
impl<A, B> ServiceFactory for AndThenNewService<A, B>
where
A: NewService,
B: NewService<
A: ServiceFactory,
B: ServiceFactory<
Config = A::Config,
Request = A::Response,
Error = A::Error,
@ -163,8 +178,8 @@ where
impl<A, B> Clone for AndThenNewService<A, B>
where
A: NewService + Clone,
B: NewService + Clone,
A: ServiceFactory + Clone,
B: ServiceFactory + Clone,
{
fn clone(&self) -> Self {
Self {
@ -174,21 +189,25 @@ where
}
}
#[pin_project]
pub struct AndThenNewServiceFuture<A, B>
where
A: NewService,
B: NewService<Request = A::Response>,
A: ServiceFactory,
B: ServiceFactory<Request = A::Response>,
{
#[pin]
fut_b: B::Future,
#[pin]
fut_a: A::Future,
a: Option<A::Service>,
b: Option<B::Service>,
}
impl<A, B> AndThenNewServiceFuture<A, B>
where
A: NewService,
B: NewService<Request = A::Response>,
A: ServiceFactory,
B: ServiceFactory<Request = A::Response>,
{
fn new(fut_a: A::Future, fut_b: B::Future) -> Self {
AndThenNewServiceFuture {
@ -202,56 +221,55 @@ where
impl<A, B> Future for AndThenNewServiceFuture<A, B>
where
A: NewService,
B: NewService<Request = A::Response, Error = A::Error, InitError = A::InitError>,
A: ServiceFactory,
B: ServiceFactory<Request = A::Response, Error = A::Error, InitError = A::InitError>,
{
type Item = AndThen<A::Service, B::Service>;
type Error = A::InitError;
type Output = Result<AndThen<A::Service, B::Service>, A::InitError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.a.is_none() {
if let Async::Ready(service) = self.fut_a.poll()? {
self.a = Some(service);
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 self.b.is_none() {
if let Async::Ready(service) = self.fut_b.poll()? {
self.b = Some(service);
if this.b.is_none() {
if let Poll::Ready(service) = this.fut_b.poll(cx)? {
*this.b = Some(service);
}
}
if self.a.is_some() && self.b.is_some() {
Ok(Async::Ready(AndThen::new(
self.a.take().unwrap(),
self.b.take().unwrap(),
if this.a.is_some() && this.b.is_some() {
Poll::Ready(Ok(AndThen::new(
this.a.take().unwrap(),
this.b.take().unwrap(),
)))
} else {
Ok(Async::NotReady)
Poll::Pending
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{ok, FutureResult};
use futures::{Async, Poll};
use std::cell::Cell;
use std::rc::Rc;
use std::task::{Context, Poll};
use super::*;
use crate::{NewService, Service, ServiceExt};
use futures::future::{lazy, ok, ready, Ready};
use crate::{factory_fn, pipeline, pipeline_factory, Service, ServiceFactory};
struct Srv1(Rc<Cell<usize>>);
impl Service for Srv1 {
type Request = &'static str;
type Response = &'static str;
type Error = ();
type Future = FutureResult<Self::Response, ()>;
type Future = Ready<Result<Self::Response, ()>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.0.set(self.0.get() + 1);
Ok(Async::Ready(()))
Poll::Ready(Ok(()))
}
fn call(&mut self, req: &'static str) -> Self::Future {
@ -266,11 +284,11 @@ mod tests {
type Request = &'static str;
type Response = (&'static str, &'static str);
type Error = ();
type Future = FutureResult<Self::Response, ()>;
type Future = Ready<Result<Self::Response, ()>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
self.0.set(self.0.get() + 1);
Ok(Async::Ready(()))
Poll::Ready(Ok(()))
}
fn call(&mut self, req: &'static str) -> Self::Future {
@ -278,39 +296,35 @@ mod tests {
}
}
#[test]
fn test_poll_ready() {
#[tokio::test]
async fn test_poll_ready() {
let cnt = Rc::new(Cell::new(0));
let mut srv = Srv1(cnt.clone()).and_then(Srv2(cnt.clone()));
let res = srv.poll_ready();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(()));
let mut srv = pipeline(Srv1(cnt.clone())).and_then(Srv2(cnt.clone()));
let res = lazy(|cx| srv.poll_ready(cx)).await;
assert_eq!(res, Poll::Ready(Ok(())));
assert_eq!(cnt.get(), 2);
}
#[test]
fn test_call() {
#[tokio::test]
async fn test_call() {
let cnt = Rc::new(Cell::new(0));
let mut srv = Srv1(cnt.clone()).and_then(Srv2(cnt));
let res = srv.call("srv1").poll();
let mut srv = pipeline(Srv1(cnt.clone())).and_then(Srv2(cnt));
let res = srv.call("srv1").await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv1", "srv2")));
assert_eq!(res.unwrap(), (("srv1", "srv2")));
}
#[test]
fn test_new_service() {
#[tokio::test]
async fn test_new_service() {
let cnt = Rc::new(Cell::new(0));
let cnt2 = cnt.clone();
let blank = move || Ok::<_, ()>(Srv1(cnt2.clone()));
let new_srv = blank
.into_new_service()
.and_then(move || Ok(Srv2(cnt.clone())));
if let Async::Ready(mut srv) = new_srv.new_service(&()).poll().unwrap() {
let res = srv.call("srv1").poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv1", "srv2")));
} else {
panic!()
}
let new_srv =
pipeline_factory(factory_fn(move || ready(Ok::<_, ()>(Srv1(cnt2.clone())))))
.and_then(move || ready(Ok(Srv2(cnt.clone()))));
let mut srv = new_srv.new_service(&()).await.unwrap();
let res = srv.call("srv1").await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), ("srv1", "srv2"));
}
}

View File

@ -1,186 +0,0 @@
use std::rc::Rc;
use futures::{Async, Future, Poll};
use crate::and_then::AndThen;
use crate::from_err::FromErr;
use crate::{NewService, Transform};
/// `Apply` new service combinator
pub struct AndThenTransform<T, A, B> {
a: A,
b: B,
t: Rc<T>,
}
impl<T, A, B> AndThenTransform<T, A, B>
where
A: NewService,
B: NewService<Config = A::Config, InitError = A::InitError>,
T: Transform<B::Service, Request = A::Response, InitError = A::InitError>,
T::Error: From<A::Error>,
{
/// Create new `ApplyNewService` new service instance
pub fn new(t: T, a: A, b: B) -> Self {
Self {
a,
b,
t: Rc::new(t),
}
}
}
impl<T, A, B> Clone for AndThenTransform<T, A, B>
where
A: Clone,
B: Clone,
{
fn clone(&self) -> Self {
Self {
a: self.a.clone(),
b: self.b.clone(),
t: self.t.clone(),
}
}
}
impl<T, A, B> NewService for AndThenTransform<T, A, B>
where
A: NewService,
B: NewService<Config = A::Config, InitError = A::InitError>,
T: Transform<B::Service, Request = A::Response, InitError = A::InitError>,
T::Error: From<A::Error>,
{
type Request = A::Request;
type Response = T::Response;
type Error = T::Error;
type Config = A::Config;
type InitError = T::InitError;
type Service = AndThen<FromErr<A::Service, T::Error>, T::Transform>;
type Future = AndThenTransformFuture<T, A, B>;
fn new_service(&self, cfg: &A::Config) -> Self::Future {
AndThenTransformFuture {
a: None,
t: None,
t_cell: self.t.clone(),
fut_a: self.a.new_service(cfg),
fut_b: self.b.new_service(cfg),
fut_t: None,
}
}
}
pub struct AndThenTransformFuture<T, A, B>
where
A: NewService,
B: NewService<InitError = A::InitError>,
T: Transform<B::Service, Request = A::Response, InitError = A::InitError>,
T::Error: From<A::Error>,
{
fut_a: A::Future,
fut_b: B::Future,
fut_t: Option<T::Future>,
a: Option<A::Service>,
t: Option<T::Transform>,
t_cell: Rc<T>,
}
impl<T, A, B> Future for AndThenTransformFuture<T, A, B>
where
A: NewService,
B: NewService<InitError = A::InitError>,
T: Transform<B::Service, Request = A::Response, InitError = A::InitError>,
T::Error: From<A::Error>,
{
type Item = AndThen<FromErr<A::Service, T::Error>, T::Transform>;
type Error = T::InitError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.fut_t.is_none() {
if let Async::Ready(service) = self.fut_b.poll()? {
self.fut_t = Some(self.t_cell.new_transform(service));
}
}
if self.a.is_none() {
if let Async::Ready(service) = self.fut_a.poll()? {
self.a = Some(service);
}
}
if let Some(ref mut fut) = self.fut_t {
if let Async::Ready(transform) = fut.poll()? {
self.t = Some(transform);
}
}
if self.a.is_some() && self.t.is_some() {
Ok(Async::Ready(AndThen::new(
FromErr::new(self.a.take().unwrap()),
self.t.take().unwrap(),
)))
} else {
Ok(Async::NotReady)
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{ok, FutureResult};
use futures::{Async, Future, Poll};
use crate::{IntoNewService, IntoService, NewService, Service, ServiceExt};
#[derive(Clone)]
struct Srv;
impl Service for Srv {
type Request = ();
type Response = ();
type Error = ();
type Future = FutureResult<(), ()>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, _: ()) -> Self::Future {
ok(())
}
}
#[test]
fn test_apply() {
let blank = |req| Ok(req);
let mut srv = blank
.into_service()
.apply_fn(Srv, |req: &'static str, srv: &mut Srv| {
srv.call(()).map(move |res| (req, res))
});
assert!(srv.poll_ready().is_ok());
let res = srv.call("srv").poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv", ())));
}
#[test]
fn test_new_service() {
let blank = || Ok::<_, ()>((|req| Ok(req)).into_service());
let new_srv = blank.into_new_service().apply(
|req: &'static str, srv: &mut Srv| srv.call(()).map(move |res| (req, res)),
|| Ok(Srv),
);
if let Async::Ready(mut srv) = new_srv.new_service(&()).poll().unwrap() {
assert!(srv.poll_ready().is_ok());
let res = srv.call("srv").poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv", ())));
} else {
panic!()
}
}
}

View File

@ -1,307 +0,0 @@
use std::marker::PhantomData;
use futures::{Async, Future, IntoFuture, Poll};
use super::{IntoNewService, IntoService, NewService, Service};
use crate::cell::Cell;
/// `Apply` service combinator
pub struct AndThenApply<A, B, F, Out>
where
A: Service,
B: Service<Error = A::Error>,
F: FnMut(A::Response, &mut B) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
a: A,
b: Cell<B>,
f: Cell<F>,
r: PhantomData<(Out,)>,
}
impl<A, B, F, Out> AndThenApply<A, B, F, Out>
where
A: Service,
B: Service<Error = A::Error>,
F: FnMut(A::Response, &mut B) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
/// Create new `Apply` combinator
pub fn new<A1: IntoService<A>, B1: IntoService<B>>(a: A1, b: B1, f: F) -> Self {
Self {
f: Cell::new(f),
a: a.into_service(),
b: Cell::new(b.into_service()),
r: PhantomData,
}
}
}
impl<A, B, F, Out> Clone for AndThenApply<A, B, F, Out>
where
A: Service + Clone,
B: Service<Error = A::Error>,
F: FnMut(A::Response, &mut B) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
fn clone(&self) -> Self {
AndThenApply {
a: self.a.clone(),
b: self.b.clone(),
f: self.f.clone(),
r: PhantomData,
}
}
}
impl<A, B, F, Out> Service for AndThenApply<A, B, F, Out>
where
A: Service,
B: Service<Error = A::Error>,
F: FnMut(A::Response, &mut B) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
type Request = A::Request;
type Response = Out::Item;
type Error = A::Error;
type Future = AndThenApplyFuture<A, B, F, Out>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
let not_ready = self.a.poll_ready()?.is_not_ready();
if self.b.get_mut().poll_ready()?.is_not_ready() || not_ready {
Ok(Async::NotReady)
} else {
Ok(Async::Ready(()))
}
}
fn call(&mut self, req: A::Request) -> Self::Future {
AndThenApplyFuture {
b: self.b.clone(),
f: self.f.clone(),
fut_b: None,
fut_a: Some(self.a.call(req)),
}
}
}
pub struct AndThenApplyFuture<A, B, F, Out>
where
A: Service,
B: Service<Error = A::Error>,
F: FnMut(A::Response, &mut B) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
b: Cell<B>,
f: Cell<F>,
fut_a: Option<A::Future>,
fut_b: Option<Out::Future>,
}
impl<A, B, F, Out> Future for AndThenApplyFuture<A, B, F, Out>
where
A: Service,
B: Service<Error = A::Error>,
F: FnMut(A::Response, &mut B) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
type Item = Out::Item;
type Error = A::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut_b {
return fut.poll().map_err(|e| e.into());
}
match self.fut_a.as_mut().expect("Bug in actix-service").poll() {
Ok(Async::Ready(resp)) => {
let _ = self.fut_a.take();
self.fut_b =
Some((&mut *self.f.get_mut())(resp, self.b.get_mut()).into_future());
self.poll()
}
Ok(Async::NotReady) => Ok(Async::NotReady),
Err(err) => Err(err),
}
}
}
/// `ApplyNewService` new service combinator
pub struct AndThenApplyNewService<A, B, F, Out> {
a: A,
b: B,
f: Cell<F>,
r: PhantomData<Out>,
}
impl<A, B, F, Out> AndThenApplyNewService<A, B, F, Out>
where
A: NewService,
B: NewService<Config = A::Config, Error = A::Error, InitError = A::InitError>,
F: FnMut(A::Response, &mut B::Service) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
/// Create new `ApplyNewService` new service instance
pub fn new<A1: IntoNewService<A>, B1: IntoNewService<B>>(a: A1, b: B1, f: F) -> Self {
Self {
f: Cell::new(f),
a: a.into_new_service(),
b: b.into_new_service(),
r: PhantomData,
}
}
}
impl<A, B, F, Out> Clone for AndThenApplyNewService<A, B, F, Out>
where
A: Clone,
B: Clone,
{
fn clone(&self) -> Self {
Self {
a: self.a.clone(),
b: self.b.clone(),
f: self.f.clone(),
r: PhantomData,
}
}
}
impl<A, B, F, Out> NewService for AndThenApplyNewService<A, B, F, Out>
where
A: NewService,
B: NewService<Config = A::Config, Error = A::Error, InitError = A::InitError>,
F: FnMut(A::Response, &mut B::Service) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
type Request = A::Request;
type Response = Out::Item;
type Error = A::Error;
type Service = AndThenApply<A::Service, B::Service, F, Out>;
type Config = A::Config;
type InitError = A::InitError;
type Future = AndThenApplyNewServiceFuture<A, B, F, Out>;
fn new_service(&self, cfg: &A::Config) -> Self::Future {
AndThenApplyNewServiceFuture {
a: None,
b: None,
f: self.f.clone(),
fut_a: self.a.new_service(cfg).into_future(),
fut_b: self.b.new_service(cfg).into_future(),
}
}
}
pub struct AndThenApplyNewServiceFuture<A, B, F, Out>
where
A: NewService,
B: NewService<Error = A::Error, InitError = A::InitError>,
F: FnMut(A::Response, &mut B::Service) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
fut_b: B::Future,
fut_a: A::Future,
f: Cell<F>,
a: Option<A::Service>,
b: Option<B::Service>,
}
impl<A, B, F, Out> Future for AndThenApplyNewServiceFuture<A, B, F, Out>
where
A: NewService,
B: NewService<Error = A::Error, InitError = A::InitError>,
F: FnMut(A::Response, &mut B::Service) -> Out,
Out: IntoFuture,
Out::Error: Into<A::Error>,
{
type Item = AndThenApply<A::Service, B::Service, F, Out>;
type Error = A::InitError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.a.is_none() {
if let Async::Ready(service) = self.fut_a.poll()? {
self.a = Some(service);
}
}
if self.b.is_none() {
if let Async::Ready(service) = self.fut_b.poll()? {
self.b = Some(service);
}
}
if self.a.is_some() && self.b.is_some() {
Ok(Async::Ready(AndThenApply {
f: self.f.clone(),
a: self.a.take().unwrap(),
b: Cell::new(self.b.take().unwrap()),
r: PhantomData,
}))
} else {
Ok(Async::NotReady)
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{ok, FutureResult};
use futures::{Async, Future, Poll};
use crate::blank::{Blank, BlankNewService};
use crate::{NewService, Service, ServiceExt};
#[derive(Clone)]
struct Srv;
impl Service for Srv {
type Request = ();
type Response = ();
type Error = ();
type Future = FutureResult<(), ()>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, _: ()) -> Self::Future {
ok(())
}
}
#[test]
fn test_call() {
let mut srv = Blank::new().apply_fn(Srv, |req: &'static str, srv| {
srv.call(()).map(move |res| (req, res))
});
assert!(srv.poll_ready().is_ok());
let res = srv.call("srv").poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv", ())));
}
#[test]
fn test_new_service() {
let new_srv = BlankNewService::new_unit().apply_fn(
|| Ok(Srv),
|req: &'static str, srv| srv.call(()).map(move |res| (req, res)),
);
if let Async::Ready(mut srv) = new_srv.new_service(&()).poll().unwrap() {
assert!(srv.poll_ready().is_ok());
let res = srv.call("srv").poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv", ())));
} else {
panic!()
}
}
}

View File

@ -1,175 +1,158 @@
use pin_project::pin_project;
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::{Async, Future, IntoFuture, Poll};
use super::{IntoNewService, IntoService, NewService, Service};
use super::{IntoService, IntoServiceFactory, Service, ServiceFactory};
/// Apply tranform function to a service
pub fn apply_fn<T, F, In, Out, U>(service: U, f: F) -> Apply<T, F, In, Out>
pub fn apply_fn<T, F, R, In, Out, Err, U>(
service: U,
f: F,
) -> impl Service<Request = In, Response = Out, Error = Err>
where
T: Service,
F: FnMut(In, &mut T) -> Out,
Out: IntoFuture,
Out::Error: From<T::Error>,
T: Service<Error = Err>,
F: FnMut(In, &mut T) -> R,
R: Future<Output = Result<Out, Err>>,
U: IntoService<T>,
{
Apply::new(service.into_service(), f)
}
/// Create factory for `apply` service.
pub fn new_apply_fn<T, F, In, Out, U>(service: U, f: F) -> ApplyNewService<T, F, In, Out>
pub fn apply_fn_factory<T, F, R, In, Out, Err, U>(
service: U,
f: F,
) -> impl ServiceFactory<
Config = T::Config,
Request = In,
Response = Out,
Error = Err,
InitError = T::InitError,
>
where
T: NewService,
F: FnMut(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
Out::Error: From<T::Error>,
U: IntoNewService<T>,
T: ServiceFactory<Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone,
R: Future<Output = Result<Out, Err>>,
U: IntoServiceFactory<T>,
{
ApplyNewService::new(service.into_new_service(), f)
ApplyNewService::new(service.into_factory(), f)
}
#[doc(hidden)]
/// `Apply` service combinator
pub struct Apply<T, F, In, Out>
#[pin_project]
struct Apply<T, F, R, In, Out, Err>
where
T: Service,
T: Service<Error = Err>,
{
#[pin]
service: T,
f: F,
r: PhantomData<(In, Out)>,
r: PhantomData<(In, Out, R)>,
}
impl<T, F, In, Out> Apply<T, F, In, Out>
impl<T, F, R, In, Out, Err> Apply<T, F, R, In, Out, Err>
where
T: Service,
F: FnMut(In, &mut T) -> Out,
Out: IntoFuture,
Out::Error: From<T::Error>,
T: Service<Error = Err>,
F: FnMut(In, &mut T) -> R,
R: Future<Output = Result<Out, Err>>,
{
/// Create new `Apply` combinator
pub(crate) fn new<I: IntoService<T>>(service: I, f: F) -> Self {
fn new(service: T, f: F) -> Self {
Self {
service: service.into_service(),
service,
f,
r: PhantomData,
}
}
}
impl<T, F, In, Out> Clone for Apply<T, F, In, Out>
impl<T, F, R, In, Out, Err> Service for Apply<T, F, R, In, Out, Err>
where
T: Service + Clone,
F: Clone,
{
fn clone(&self) -> Self {
Apply {
service: self.service.clone(),
f: self.f.clone(),
r: PhantomData,
}
}
}
impl<T, F, In, Out> Service for Apply<T, F, In, Out>
where
T: Service,
F: FnMut(In, &mut T) -> Out,
Out: IntoFuture,
Out::Error: From<T::Error>,
T: Service<Error = Err>,
F: FnMut(In, &mut T) -> R,
R: Future<Output = Result<Out, Err>>,
{
type Request = In;
type Response = Out::Item;
type Error = Out::Error;
type Future = Out::Future;
type Response = Out;
type Error = Err;
type Future = R;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready().map_err(|e| e.into())
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(futures::ready!(self.service.poll_ready(ctx)))
}
fn call(&mut self, req: In) -> Self::Future {
(self.f)(req, &mut self.service).into_future()
(self.f)(req, &mut self.service)
}
}
/// `ApplyNewService` new service combinator
pub struct ApplyNewService<T, F, In, Out>
struct ApplyNewService<T, F, R, In, Out, Err>
where
T: NewService,
T: ServiceFactory<Error = Err>,
{
service: T,
f: F,
r: PhantomData<(In, Out)>,
r: PhantomData<(R, In, Out)>,
}
impl<T, F, In, Out> ApplyNewService<T, F, In, Out>
impl<T, F, R, In, Out, Err> ApplyNewService<T, F, R, In, Out, Err>
where
T: NewService,
F: FnMut(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
Out::Error: From<T::Error>,
T: ServiceFactory<Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone,
R: Future<Output = Result<Out, Err>>,
{
/// Create new `ApplyNewService` new service instance
pub(crate) fn new<F1: IntoNewService<T>>(service: F1, f: F) -> Self {
fn new(service: T, f: F) -> Self {
Self {
f,
service: service.into_new_service(),
service,
r: PhantomData,
}
}
}
impl<T, F, In, Out> Clone for ApplyNewService<T, F, In, Out>
impl<T, F, R, In, Out, Err> ServiceFactory for ApplyNewService<T, F, R, In, Out, Err>
where
T: NewService + Clone,
F: FnMut(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
{
fn clone(&self) -> Self {
Self {
service: self.service.clone(),
f: self.f.clone(),
r: PhantomData,
}
}
}
impl<T, F, In, Out> NewService for ApplyNewService<T, F, In, Out>
where
T: NewService,
F: FnMut(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
Out::Error: From<T::Error>,
T: ServiceFactory<Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone,
R: Future<Output = Result<Out, Err>>,
{
type Request = In;
type Response = Out::Item;
type Error = Out::Error;
type Response = Out;
type Error = Err;
type Config = T::Config;
type Service = Apply<T::Service, F, In, Out>;
type Service = Apply<T::Service, F, R, In, Out, Err>;
type InitError = T::InitError;
type Future = ApplyNewServiceFuture<T, F, In, Out>;
type Future = ApplyNewServiceFuture<T, F, R, In, Out, Err>;
fn new_service(&self, cfg: &T::Config) -> Self::Future {
ApplyNewServiceFuture::new(self.service.new_service(cfg), self.f.clone())
}
}
pub struct ApplyNewServiceFuture<T, F, In, Out>
#[pin_project]
struct ApplyNewServiceFuture<T, F, R, In, Out, Err>
where
T: NewService,
F: FnMut(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
T: ServiceFactory<Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone,
R: Future<Output = Result<Out, Err>>,
{
#[pin]
fut: T::Future,
f: Option<F>,
r: PhantomData<(In, Out)>,
}
impl<T, F, In, Out> ApplyNewServiceFuture<T, F, In, Out>
impl<T, F, R, In, Out, Err> ApplyNewServiceFuture<T, F, R, In, Out, Err>
where
T: NewService,
F: FnMut(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
T: ServiceFactory<Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone,
R: Future<Output = Result<Out, Err>>,
{
fn new(fut: T::Future, f: F) -> Self {
ApplyNewServiceFuture {
@ -180,43 +163,44 @@ where
}
}
impl<T, F, In, Out> Future for ApplyNewServiceFuture<T, F, In, Out>
impl<T, F, R, In, Out, Err> Future for ApplyNewServiceFuture<T, F, R, In, Out, Err>
where
T: NewService,
F: FnMut(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
Out::Error: From<T::Error>,
T: ServiceFactory<Error = Err>,
F: FnMut(In, &mut T::Service) -> R + Clone,
R: Future<Output = Result<Out, Err>>,
{
type Item = Apply<T::Service, F, In, Out>;
type Error = T::InitError;
type Output = Result<Apply<T::Service, F, R, In, Out, Err>, T::InitError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Async::Ready(service) = self.fut.poll()? {
Ok(Async::Ready(Apply::new(service, self.f.take().unwrap())))
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 {
Ok(Async::NotReady)
Poll::Pending
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{ok, FutureResult};
use futures::{Async, Future, Poll};
use std::task::{Context, Poll};
use futures::future::{lazy, ok, Ready};
use super::*;
use crate::{IntoService, NewService, Service, ServiceExt};
use crate::{pipeline, pipeline_factory, Service, ServiceFactory};
#[derive(Clone)]
struct Srv;
impl Service for Srv {
type Request = ();
type Response = ();
type Error = ();
type Future = FutureResult<(), ()>;
type Future = Ready<Result<(), ()>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _: ()) -> Self::Future {
@ -224,34 +208,42 @@ mod tests {
}
}
#[test]
fn test_call() {
let blank = |req| Ok(req);
#[tokio::test]
async fn test_call() {
let mut srv = pipeline(apply_fn(Srv, |req: &'static str, srv| {
let fut = srv.call(());
async move {
let res = fut.await.unwrap();
Ok((req, res))
}
}));
let mut srv = blank
.into_service()
.apply_fn(Srv, |req: &'static str, srv| {
srv.call(()).map(move |res| (req, res))
});
assert!(srv.poll_ready().is_ok());
let res = srv.call("srv").poll();
assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
let res = srv.call("srv").await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv", ())));
assert_eq!(res.unwrap(), (("srv", ())));
}
#[test]
fn test_new_service() {
let new_srv = ApplyNewService::new(
|| Ok::<_, ()>(Srv),
|req: &'static str, srv| srv.call(()).map(move |res| (req, res)),
);
if let Async::Ready(mut srv) = new_srv.new_service(&()).poll().unwrap() {
assert!(srv.poll_ready().is_ok());
let res = srv.call("srv").poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv", ())));
} else {
panic!()
}
#[tokio::test]
async fn test_new_service() {
let new_srv = pipeline_factory(apply_fn_factory(
|| ok::<_, ()>(Srv),
|req: &'static str, srv| {
let fut = srv.call(());
async move {
let res = fut.await.unwrap();
Ok((req, res))
}
},
));
let mut srv = new_srv.new_service(&()).await.unwrap();
assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
let res = srv.call("srv").await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), (("srv", ())));
}
}

View File

@ -1,43 +1,45 @@
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::future::Future;
use futures::{try_ready, Async, IntoFuture, Poll};
use futures::ready;
use pin_project::pin_project;
use crate::cell::Cell;
use crate::{IntoService, NewService, Service};
use crate::{IntoService, Service, ServiceFactory};
/// Convert `Fn(&Config, &mut Service) -> Future<Service>` fn to a NewService
pub fn apply_cfg<F, C, T, R, S>(
pub fn apply_cfg<F, C, T, R, S, E>(
srv: T,
f: F,
) -> impl NewService<
) -> impl ServiceFactory<
Config = C,
Request = S::Request,
Response = S::Response,
Error = S::Error,
Service = S,
InitError = R::Error,
InitError = E,
> + Clone
where
F: FnMut(&C, &mut T) -> R,
T: Service,
R: IntoFuture,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
ApplyConfigService {
f: Cell::new(f),
srv: Cell::new(srv.into_service()),
srv: Cell::new(srv),
_t: PhantomData,
}
}
/// Convert `Fn(&Config, &mut Service) -> Future<Service>` fn to a NewService
/// Service get constructor from NewService.
pub fn new_apply_cfg<F, C, T, R, S>(
pub fn apply_cfg_factory<F, C, T, R, S>(
srv: T,
f: F,
) -> impl NewService<
) -> impl ServiceFactory<
Config = C,
Request = S::Request,
Response = S::Response,
@ -48,10 +50,9 @@ pub fn new_apply_cfg<F, C, T, R, S>(
where
C: Clone,
F: FnMut(&C, &mut T::Service) -> R,
T: NewService<Config = ()>,
T: ServiceFactory<Config = ()>,
T::InitError: From<T::Error>,
R: IntoFuture<Error = T::InitError>,
R::Item: IntoService<S>,
R: Future<Output = Result<S, T::InitError>>,
S: Service,
{
ApplyConfigNewService {
@ -61,26 +62,26 @@ where
}
}
/// Convert `Fn(&Config) -> Future<Service>` fn to NewService
struct ApplyConfigService<F, C, T, R, S>
/// Convert `Fn(&Config) -> Future<Service>` fn to NewService\
#[pin_project]
struct ApplyConfigService<F, C, T, R, S, E>
where
F: FnMut(&C, &mut T) -> R,
T: Service,
R: IntoFuture,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
f: Cell<F>,
#[pin]
srv: Cell<T>,
_t: PhantomData<(C, R, S)>,
}
impl<F, C, T, R, S> Clone for ApplyConfigService<F, C, T, R, S>
impl<F, C, T, R, S, E> Clone for ApplyConfigService<F, C, T, R, S, E>
where
F: FnMut(&C, &mut T) -> R,
T: Service,
R: IntoFuture,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
fn clone(&self) -> Self {
@ -92,12 +93,11 @@ where
}
}
impl<F, C, T, R, S> NewService for ApplyConfigService<F, C, T, R, S>
impl<F, C, T, R, S, E> ServiceFactory for ApplyConfigService<F, C, T, R, S, E>
where
F: FnMut(&C, &mut T) -> R,
T: Service,
R: IntoFuture,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
type Config = C;
@ -106,39 +106,37 @@ where
type Error = S::Error;
type Service = S;
type InitError = R::Error;
type Future = FnNewServiceConfigFut<R, S>;
type InitError = E;
type Future = FnNewServiceConfigFut<R, S, E>;
fn new_service(&self, cfg: &C) -> Self::Future {
FnNewServiceConfigFut {
fut: unsafe { (self.f.get_mut_unsafe())(cfg, self.srv.get_mut_unsafe()) }
.into_future(),
fut: unsafe { (self.f.get_mut_unsafe())(cfg, self.srv.get_mut_unsafe()) },
_t: PhantomData,
}
}
}
struct FnNewServiceConfigFut<R, S>
#[pin_project]
struct FnNewServiceConfigFut<R, S, E>
where
R: IntoFuture,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
fut: R::Future,
#[pin]
fut: R,
_t: PhantomData<(S,)>,
}
impl<R, S> Future for FnNewServiceConfigFut<R, S>
impl<R, S, E> Future for FnNewServiceConfigFut<R, S, E>
where
R: IntoFuture,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
type Item = S;
type Error = R::Error;
type Output = Result<S, E>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
Ok(Async::Ready(try_ready!(self.fut.poll()).into_service()))
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready(Ok(ready!(self.project().fut.poll(cx))?.into_service()))
}
}
@ -147,9 +145,8 @@ struct ApplyConfigNewService<F, C, T, R, S>
where
C: Clone,
F: FnMut(&C, &mut T::Service) -> R,
T: NewService<Config = ()>,
R: IntoFuture<Error = T::InitError>,
R::Item: IntoService<S>,
T: ServiceFactory<Config = ()>,
R: Future<Output = Result<S, T::InitError>>,
S: Service,
{
f: Cell<F>,
@ -161,9 +158,8 @@ impl<F, C, T, R, S> Clone for ApplyConfigNewService<F, C, T, R, S>
where
C: Clone,
F: FnMut(&C, &mut T::Service) -> R,
T: NewService<Config = ()>,
R: IntoFuture<Error = T::InitError>,
R::Item: IntoService<S>,
T: ServiceFactory<Config = ()>,
R: Future<Output = Result<S, T::InitError>>,
S: Service,
{
fn clone(&self) -> Self {
@ -175,14 +171,13 @@ where
}
}
impl<F, C, T, R, S> NewService for ApplyConfigNewService<F, C, T, R, S>
impl<F, C, T, R, S> ServiceFactory for ApplyConfigNewService<F, C, T, R, S>
where
C: Clone,
F: FnMut(&C, &mut T::Service) -> R,
T: NewService<Config = ()>,
T: ServiceFactory<Config = ()>,
T::InitError: From<T::Error>,
R: IntoFuture<Error = T::InitError>,
R::Item: IntoService<S>,
R: Future<Output = Result<S, T::InitError>>,
S: Service,
{
type Config = C;
@ -191,7 +186,7 @@ where
type Error = S::Error;
type Service = S;
type InitError = R::Error;
type InitError = T::InitError;
type Future = ApplyConfigNewServiceFut<F, C, T, R, S>;
fn new_service(&self, cfg: &C) -> Self::Future {
@ -206,21 +201,23 @@ where
}
}
#[pin_project]
struct ApplyConfigNewServiceFut<F, C, T, R, S>
where
C: Clone,
F: FnMut(&C, &mut T::Service) -> R,
T: NewService<Config = ()>,
T: ServiceFactory<Config = ()>,
T::InitError: From<T::Error>,
R: IntoFuture<Error = T::InitError>,
R::Item: IntoService<S>,
R: Future<Output = Result<S, T::InitError>>,
S: Service,
{
cfg: C,
f: Cell<F>,
srv: Option<T::Service>,
#[pin]
srv_fut: Option<T::Future>,
fut: Option<R::Future>,
#[pin]
fut: Option<R>,
_t: PhantomData<(S,)>,
}
@ -228,39 +225,40 @@ impl<F, C, T, R, S> Future for ApplyConfigNewServiceFut<F, C, T, R, S>
where
C: Clone,
F: FnMut(&C, &mut T::Service) -> R,
T: NewService<Config = ()>,
T: ServiceFactory<Config = ()>,
T::InitError: From<T::Error>,
R: IntoFuture<Error = T::InitError>,
R::Item: IntoService<S>,
R: Future<Output = Result<S, T::InitError>>,
S: Service,
{
type Item = S;
type Error = R::Error;
type Output = Result<S, T::InitError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.srv_fut {
match fut.poll()? {
Async::NotReady => return Ok(Async::NotReady),
Async::Ready(srv) => {
let _ = self.srv_fut.take();
self.srv = Some(srv);
return self.poll();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
'poll: loop {
if let Some(fut) = this.srv_fut.as_mut().as_pin_mut() {
match fut.poll(cx)? {
Poll::Pending => return Poll::Pending,
Poll::Ready(srv) => {
this.srv_fut.set(None);
*this.srv = Some(srv);
continue 'poll;
}
}
}
}
if let Some(ref mut fut) = self.fut {
Ok(Async::Ready(try_ready!(fut.poll()).into_service()))
} else if let Some(ref mut srv) = self.srv {
match srv.poll_ready()? {
Async::NotReady => Ok(Async::NotReady),
Async::Ready(_) => {
self.fut = Some(self.f.get_mut()(&self.cfg, srv).into_future());
return self.poll();
if let Some(fut) = this.fut.as_mut().as_pin_mut() {
return Poll::Ready(Ok(ready!(fut.poll(cx))?.into_service()));
} else if let Some(ref mut srv) = this.srv {
match srv.poll_ready(cx)? {
Poll::Ready(_) => {
this.fut.set(Some(this.f.get_mut()(&this.cfg, srv)));
continue 'poll;
}
Poll::Pending => return Poll::Pending,
}
} else {
return Poll::Pending;
}
} else {
Ok(Async::NotReady)
}
}
}

View File

@ -1,84 +0,0 @@
use std::marker::PhantomData;
use futures::future::{ok, FutureResult};
use futures::{Async, Poll};
use super::{NewService, Service};
/// Empty service
#[derive(Clone)]
pub struct Blank<R, E> {
_t: PhantomData<(R, E)>,
}
impl<R, E> Blank<R, E> {
pub fn err<E1>(self) -> Blank<R, E1> {
Blank { _t: PhantomData }
}
}
impl<R> Blank<R, ()> {
#[allow(clippy::new_ret_no_self)]
pub fn new<E>() -> Blank<R, E> {
Blank { _t: PhantomData }
}
}
impl<R, E> Default for Blank<R, E> {
fn default() -> Blank<R, E> {
Blank { _t: PhantomData }
}
}
impl<R, E> Service for Blank<R, E> {
type Request = R;
type Response = R;
type Error = E;
type Future = FutureResult<R, E>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, req: R) -> Self::Future {
ok(req)
}
}
/// Empty service factory
pub struct BlankNewService<R, E1, E2 = ()> {
_t: PhantomData<(R, E1, E2)>,
}
impl<R, E1, E2> BlankNewService<R, E1, E2> {
pub fn new() -> BlankNewService<R, E1, E2> {
BlankNewService { _t: PhantomData }
}
}
impl<R, E1> BlankNewService<R, E1, ()> {
pub fn new_unit() -> BlankNewService<R, E1, ()> {
BlankNewService { _t: PhantomData }
}
}
impl<R, E1, E2> Default for BlankNewService<R, E1, E2> {
fn default() -> BlankNewService<R, E1, E2> {
Self::new()
}
}
impl<R, E1, E2> NewService for BlankNewService<R, E1, E2> {
type Request = R;
type Response = R;
type Error = E1;
type Config = ();
type Service = Blank<R, E1>;
type InitError = E2;
type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self, _: &()) -> Self::Future {
ok(Blank::default())
}
}

View File

@ -1,7 +1,8 @@
use futures::future::{err, ok, Either, FutureResult};
use futures::{Async, Future, IntoFuture, Poll};
use std::task::{Context, Poll};
use crate::{NewService, Service};
use futures::future::{FutureExt, LocalBoxFuture};
use crate::{Service, ServiceFactory};
pub type BoxedService<Req, Res, Err> = Box<
dyn Service<
@ -12,17 +13,16 @@ pub type BoxedService<Req, Res, Err> = Box<
>,
>;
pub type BoxedServiceResponse<Res, Err> =
Either<FutureResult<Res, Err>, Box<dyn Future<Item = Res, Error = Err>>>;
pub type BoxedServiceResponse<Res, Err> = LocalBoxFuture<'static, Result<Res, Err>>;
pub struct BoxedNewService<C, Req, Res, Err, InitErr>(Inner<C, Req, Res, Err, InitErr>);
/// Create boxed new service
pub fn new_service<T>(
service: T,
pub fn factory<T>(
factory: T,
) -> BoxedNewService<T::Config, T::Request, T::Response, T::Error, T::InitError>
where
T: NewService + 'static,
T: ServiceFactory + 'static,
T::Request: 'static,
T::Response: 'static,
T::Service: 'static,
@ -30,8 +30,8 @@ where
T::Error: 'static,
T::InitError: 'static,
{
BoxedNewService(Box::new(NewServiceWrapper {
service,
BoxedNewService(Box::new(FactoryWrapper {
factory,
_t: std::marker::PhantomData,
}))
}
@ -46,18 +46,18 @@ where
}
type Inner<C, Req, Res, Err, InitErr> = Box<
dyn NewService<
dyn ServiceFactory<
Config = C,
Request = Req,
Response = Res,
Error = Err,
InitError = InitErr,
Service = BoxedService<Req, Res, Err>,
Future = Box<dyn Future<Item = BoxedService<Req, Res, Err>, Error = InitErr>>,
Future = LocalBoxFuture<'static, Result<BoxedService<Req, Res, Err>, InitErr>>,
>,
>;
impl<C, Req, Res, Err, InitErr> NewService for BoxedNewService<C, Req, Res, Err, InitErr>
impl<C, Req, Res, Err, InitErr> ServiceFactory for BoxedNewService<C, Req, Res, Err, InitErr>
where
Req: 'static,
Res: 'static,
@ -70,25 +70,32 @@ where
type InitError = InitErr;
type Config = C;
type Service = BoxedService<Req, Res, Err>;
type Future = Box<dyn Future<Item = Self::Service, Error = Self::InitError>>;
type Future = LocalBoxFuture<'static, Result<Self::Service, InitErr>>;
fn new_service(&self, cfg: &C) -> Self::Future {
self.0.new_service(cfg)
}
}
struct NewServiceWrapper<C, T: NewService> {
service: T,
struct FactoryWrapper<C, T: ServiceFactory> {
factory: T,
_t: std::marker::PhantomData<C>,
}
impl<C, T, Req, Res, Err, InitErr> NewService for NewServiceWrapper<C, T>
impl<C, T, Req, Res, Err, InitErr> ServiceFactory for FactoryWrapper<C, T>
where
Req: 'static,
Res: 'static,
Err: 'static,
InitErr: 'static,
T: NewService<Config = C, Request = Req, Response = Res, Error = Err, InitError = InitErr>,
T: ServiceFactory<
Config = C,
Request = Req,
Response = Res,
Error = Err,
InitError = InitErr,
>,
T::Future: 'static,
T::Service: 'static,
<T::Service as Service>::Future: 'static,
@ -99,15 +106,13 @@ where
type InitError = InitErr;
type Config = C;
type Service = BoxedService<Req, Res, Err>;
type Future = Box<dyn Future<Item = Self::Service, Error = Self::InitError>>;
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>;
fn new_service(&self, cfg: &C) -> Self::Future {
Box::new(
self.service
.new_service(cfg)
.into_future()
.map(ServiceWrapper::boxed),
)
self.factory
.new_service(cfg)
.map(|res| res.map(ServiceWrapper::boxed))
.boxed_local()
}
}
@ -131,21 +136,13 @@ where
type Request = Req;
type Response = Res;
type Error = Err;
type Future = Either<
FutureResult<Self::Response, Self::Error>,
Box<dyn Future<Item = Self::Response, Error = Self::Error>>,
>;
type Future = LocalBoxFuture<'static, Result<Res, Err>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.0.poll_ready()
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.0.poll_ready(ctx)
}
fn call(&mut self, req: Self::Request) -> Self::Future {
let mut fut = self.0.call(req);
match fut.poll() {
Ok(Async::Ready(res)) => Either::A(ok(res)),
Err(e) => Either::A(err(e)),
Ok(Async::NotReady) => Either::B(Box::new(fut)),
}
self.0.call(req).boxed_local()
}
}

View File

@ -1,4 +1,4 @@
//! Custom cell impl
//! Custom cell impl, internal use only
use std::{cell::UnsafeCell, fmt, rc::Rc};
pub(crate) struct Cell<T> {

View File

@ -1,248 +1,245 @@
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::future::{ok, Future, FutureResult};
use futures::{try_ready, Async, IntoFuture, Poll};
use futures::future::{ok, Ready};
use pin_project::pin_project;
use crate::{IntoNewService, IntoService, NewService, Service};
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
/// Create `NewService` for function that can act as a Service
pub fn service_fn<F, Req, Out, Cfg>(f: F) -> NewServiceFn<F, Req, Out, Cfg>
/// Create `ServiceFactory` for function that can act as a `Service`
pub fn service_fn<F, Fut, Req, Res, Err, Cfg>(
f: F,
) -> impl ServiceFactory<Config = Cfg, Request = Req, Response = Res, Error = Err, InitError = ()>
+ Clone
where
F: FnMut(Req) -> Out + Clone,
Out: IntoFuture,
F: FnMut(Req) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>,
{
NewServiceFn::new(f)
}
/// Create `NewService` for function that can produce services
pub fn new_service_fn<F, C, R, S, E>(f: F) -> FnNewServiceNoConfig<F, C, R, S, E>
pub fn service_fn2<F, Fut, Req, Res, Err>(
f: F,
) -> impl Service<Request = Req, Response = Res, Error = Err>
where
F: FnMut(Req) -> Fut,
Fut: Future<Output = Result<Res, Err>>,
{
ServiceFn::new(f)
}
/// Create `ServiceFactory` for function that can produce services
pub fn factory_fn<S, F, Cfg, Fut, Err>(
f: F,
) -> impl ServiceFactory<
Config = Cfg,
Service = S,
Request = S::Request,
Response = S::Response,
Error = S::Error,
InitError = Err,
Future = Fut,
>
where
F: Fn() -> R,
R: IntoFuture<Item = S, Error = E>,
R::Item: IntoService<S>,
S: Service,
F: Fn() -> Fut,
Fut: Future<Output = Result<S, Err>>,
{
FnNewServiceNoConfig::new(f)
}
/// Create `NewService` for function that can produce services with configuration
pub fn new_service_cfg<F, C, R, S, E>(f: F) -> FnNewServiceConfig<F, C, R, S, E>
/// Create `ServiceFactory` for function that can produce services with configuration
pub fn factory_fn_cfg<F, Fut, Cfg, Srv, Err>(
f: F,
) -> impl ServiceFactory<
Config = Cfg,
Service = Srv,
Request = Srv::Request,
Response = Srv::Response,
Error = Srv::Error,
InitError = Err,
>
where
F: Fn(&C) -> R,
R: IntoFuture<Error = E>,
R::Item: IntoService<S>,
S: Service,
F: Fn(&Cfg) -> Fut,
Fut: Future<Output = Result<Srv, Err>>,
Srv: Service,
{
FnNewServiceConfig::new(f)
}
pub struct ServiceFn<F, Req, Out>
pub struct ServiceFn<F, Fut, Req, Res, Err>
where
F: FnMut(Req) -> Out,
Out: IntoFuture,
F: FnMut(Req) -> Fut,
Fut: Future<Output = Result<Res, Err>>,
{
f: F,
_t: PhantomData<Req>,
}
impl<F, Req, Out> ServiceFn<F, Req, Out>
impl<F, Fut, Req, Res, Err> ServiceFn<F, Fut, Req, Res, Err>
where
F: FnMut(Req) -> Out,
Out: IntoFuture,
F: FnMut(Req) -> Fut,
Fut: Future<Output = Result<Res, Err>>,
{
pub(crate) fn new(f: F) -> Self {
ServiceFn { f, _t: PhantomData }
}
}
impl<F, Req, Out> Clone for ServiceFn<F, Req, Out>
impl<F, Fut, Req, Res, Err> Clone for ServiceFn<F, Fut, Req, Res, Err>
where
F: FnMut(Req) -> Out + Clone,
Out: IntoFuture,
F: FnMut(Req) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>,
{
fn clone(&self) -> Self {
ServiceFn::new(self.f.clone())
}
}
impl<F, Req, Out> Service for ServiceFn<F, Req, Out>
impl<F, Fut, Req, Res, Err> Service for ServiceFn<F, Fut, Req, Res, Err>
where
F: FnMut(Req) -> Out,
Out: IntoFuture,
F: FnMut(Req) -> Fut,
Fut: Future<Output = Result<Res, Err>>,
{
type Request = Req;
type Response = Out::Item;
type Error = Out::Error;
type Future = Out::Future;
type Response = Res;
type Error = Err;
type Future = Fut;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Req) -> Self::Future {
(self.f)(req).into_future()
(self.f)(req)
}
}
impl<F, Req, Out> IntoService<ServiceFn<F, Req, Out>> for F
impl<F, Fut, Req, Res, Err> IntoService<ServiceFn<F, Fut, Req, Res, Err>> for F
where
F: FnMut(Req) -> Out,
Out: IntoFuture,
F: FnMut(Req) -> Fut,
Fut: Future<Output = Result<Res, Err>>,
{
fn into_service(self) -> ServiceFn<F, Req, Out> {
fn into_service(self) -> ServiceFn<F, Fut, Req, Res, Err> {
ServiceFn::new(self)
}
}
pub struct NewServiceFn<F, Req, Out, Cfg>
struct NewServiceFn<F, Fut, Req, Res, Err, Cfg>
where
F: FnMut(Req) -> Out,
Out: IntoFuture,
F: FnMut(Req) -> Fut,
Fut: Future<Output = Result<Res, Err>>,
{
f: F,
_t: PhantomData<(Req, Cfg)>,
}
impl<F, Req, Out, Cfg> NewServiceFn<F, Req, Out, Cfg>
impl<F, Fut, Req, Res, Err, Cfg> NewServiceFn<F, Fut, Req, Res, Err, Cfg>
where
F: FnMut(Req) -> Out + Clone,
Out: IntoFuture,
F: FnMut(Req) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>,
{
pub(crate) fn new(f: F) -> Self {
fn new(f: F) -> Self {
NewServiceFn { f, _t: PhantomData }
}
}
impl<F, Req, Out, Cfg> Clone for NewServiceFn<F, Req, Out, Cfg>
impl<F, Fut, Req, Res, Err, Cfg> Clone for NewServiceFn<F, Fut, Req, Res, Err, Cfg>
where
F: FnMut(Req) -> Out + Clone,
Out: IntoFuture,
F: FnMut(Req) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>,
{
fn clone(&self) -> Self {
NewServiceFn::new(self.f.clone())
}
}
impl<F, Req, Out, Cfg> NewService for NewServiceFn<F, Req, Out, Cfg>
impl<F, Fut, Req, Res, Err, Cfg> ServiceFactory for NewServiceFn<F, Fut, Req, Res, Err, Cfg>
where
F: FnMut(Req) -> Out + Clone,
Out: IntoFuture,
F: FnMut(Req) -> Fut + Clone,
Fut: Future<Output = Result<Res, Err>>,
{
type Request = Req;
type Response = Out::Item;
type Error = Out::Error;
type Response = Res;
type Error = Err;
type Config = Cfg;
type Service = ServiceFn<F, Req, Out>;
type Service = ServiceFn<F, Fut, Req, Res, Err>;
type InitError = ();
type Future = FutureResult<Self::Service, Self::InitError>;
type Future = Ready<Result<Self::Service, Self::InitError>>;
fn new_service(&self, _: &Cfg) -> Self::Future {
ok(ServiceFn::new(self.f.clone()))
}
}
impl<F, Req, Out, Cfg> IntoService<ServiceFn<F, Req, Out>> for NewServiceFn<F, Req, Out, Cfg>
where
F: FnMut(Req) -> Out + Clone,
Out: IntoFuture,
{
fn into_service(self) -> ServiceFn<F, Req, Out> {
ServiceFn::new(self.f.clone())
}
}
impl<F, Req, Out, Cfg> IntoNewService<NewServiceFn<F, Req, Out, Cfg>> for F
where
F: Fn(Req) -> Out + Clone,
Out: IntoFuture,
{
fn into_new_service(self) -> NewServiceFn<F, Req, Out, Cfg> {
NewServiceFn::new(self)
}
}
/// Convert `Fn(&Config) -> Future<Service>` fn to NewService
pub struct FnNewServiceConfig<F, C, R, S, E>
struct FnNewServiceConfig<F, Fut, Cfg, Srv, Err>
where
F: Fn(&C) -> R,
R: IntoFuture<Error = E>,
R::Item: IntoService<S>,
S: Service,
F: Fn(&Cfg) -> Fut,
Fut: Future<Output = Result<Srv, Err>>,
Srv: Service,
{
f: F,
_t: PhantomData<(C, R, S, E)>,
_t: PhantomData<(Fut, Cfg, Srv, Err)>,
}
impl<F, C, R, S, E> FnNewServiceConfig<F, C, R, S, E>
impl<F, Fut, Cfg, Srv, Err> FnNewServiceConfig<F, Fut, Cfg, Srv, Err>
where
F: Fn(&C) -> R,
R: IntoFuture<Error = E>,
R::Item: IntoService<S>,
S: Service,
F: Fn(&Cfg) -> Fut,
Fut: Future<Output = Result<Srv, Err>>,
Srv: Service,
{
pub fn new(f: F) -> Self {
FnNewServiceConfig { f, _t: PhantomData }
}
}
impl<F, C, R, S, E> NewService for FnNewServiceConfig<F, C, R, S, E>
impl<F, Fut, Cfg, Srv, Err> ServiceFactory for FnNewServiceConfig<F, Fut, Cfg, Srv, Err>
where
F: Fn(&C) -> R,
R: IntoFuture<Error = E>,
R::Item: IntoService<S>,
S: Service,
F: Fn(&Cfg) -> Fut,
Fut: Future<Output = Result<Srv, Err>>,
Srv: Service,
{
type Request = S::Request;
type Response = S::Response;
type Error = S::Error;
type Request = Srv::Request;
type Response = Srv::Response;
type Error = Srv::Error;
type Config = C;
type Service = S;
type InitError = E;
type Future = FnNewServiceConfigFut<R, S, E>;
type Config = Cfg;
type Service = Srv;
type InitError = Err;
type Future = FnNewServiceConfigFut<Fut, Srv, Err>;
fn new_service(&self, cfg: &C) -> Self::Future {
fn new_service(&self, cfg: &Cfg) -> Self::Future {
FnNewServiceConfigFut {
fut: (self.f)(cfg).into_future(),
fut: (self.f)(cfg),
_t: PhantomData,
}
}
}
pub struct FnNewServiceConfigFut<R, S, E>
#[pin_project]
struct FnNewServiceConfigFut<R, S, E>
where
R: IntoFuture<Error = E>,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
fut: R::Future,
#[pin]
fut: R,
_t: PhantomData<(S,)>,
}
impl<R, S, E> Future for FnNewServiceConfigFut<R, S, E>
where
R: IntoFuture<Error = E>,
R::Item: IntoService<S>,
R: Future<Output = Result<S, E>>,
S: Service,
{
type Item = S;
type Error = R::Error;
type Output = Result<S, E>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
Ok(Async::Ready(try_ready!(self.fut.poll()).into_service()))
}
}
impl<F, C, R, S, E> Clone for FnNewServiceConfig<F, C, R, S, E>
where
F: Fn(&C) -> R + Clone,
R: IntoFuture<Error = E>,
R::Item: IntoService<S>,
S: Service,
{
fn clone(&self) -> Self {
Self::new(self.f.clone())
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready(Ok(futures::ready!(self.project().fut.poll(cx))?))
}
}
@ -250,7 +247,7 @@ where
pub struct FnNewServiceNoConfig<F, C, R, S, E>
where
F: Fn() -> R,
R: IntoFuture<Item = S, Error = E>,
R: Future<Output = Result<S, E>>,
S: Service,
{
f: F,
@ -260,18 +257,18 @@ where
impl<F, C, R, S, E> FnNewServiceNoConfig<F, C, R, S, E>
where
F: Fn() -> R,
R: IntoFuture<Item = S, Error = E>,
R: Future<Output = Result<S, E>>,
S: Service,
{
pub fn new(f: F) -> Self {
fn new(f: F) -> Self {
FnNewServiceNoConfig { f, _t: PhantomData }
}
}
impl<F, C, R, S, E> NewService for FnNewServiceNoConfig<F, C, R, S, E>
impl<F, C, R, S, E> ServiceFactory for FnNewServiceNoConfig<F, C, R, S, E>
where
F: Fn() -> R,
R: IntoFuture<Item = S, Error = E>,
R: Future<Output = Result<S, E>>,
S: Service,
{
type Request = S::Request;
@ -280,17 +277,17 @@ where
type Service = S;
type Config = C;
type InitError = E;
type Future = R::Future;
type Future = R;
fn new_service(&self, _: &C) -> Self::Future {
(self.f)().into_future()
(self.f)()
}
}
impl<F, C, R, S, E> Clone for FnNewServiceNoConfig<F, C, R, S, E>
where
F: Fn() -> R + Clone,
R: IntoFuture<Item = S, Error = E>,
R: Future<Output = Result<S, E>>,
S: Service,
{
fn clone(&self) -> Self {
@ -298,13 +295,13 @@ where
}
}
impl<F, C, R, S, E> IntoNewService<FnNewServiceNoConfig<F, C, R, S, E>> for F
impl<F, C, R, S, E> IntoServiceFactory<FnNewServiceNoConfig<F, C, R, S, E>> for F
where
F: Fn() -> R,
R: IntoFuture<Item = S, Error = E>,
R: Future<Output = Result<S, E>>,
S: Service,
{
fn into_new_service(self) -> FnNewServiceNoConfig<F, C, R, S, E> {
fn into_factory(self) -> FnNewServiceNoConfig<F, C, R, S, E> {
FnNewServiceNoConfig::new(self)
}
}

View File

@ -1,80 +0,0 @@
use std::marker::PhantomData;
use futures::future::{ok, FutureResult};
use futures::IntoFuture;
use crate::apply::Apply;
use crate::{IntoTransform, Service, Transform};
/// Use function as transform service
pub fn transform_fn<F, S, In, Out, Err>(
f: F,
) -> impl Transform<S, Request = In, Response = Out::Item, Error = Out::Error, InitError = Err>
where
S: Service,
F: FnMut(In, &mut S) -> Out + Clone,
Out: IntoFuture,
Out::Error: From<S::Error>,
{
FnTransform::new(f)
}
pub struct FnTransform<F, S, In, Out, Err>
where
F: FnMut(In, &mut S) -> Out + Clone,
Out: IntoFuture,
{
f: F,
_t: PhantomData<(S, In, Out, Err)>,
}
impl<F, S, In, Out, Err> FnTransform<F, S, In, Out, Err>
where
F: FnMut(In, &mut S) -> Out + Clone,
Out: IntoFuture,
{
pub fn new(f: F) -> Self {
FnTransform { f, _t: PhantomData }
}
}
impl<F, S, In, Out, Err> Transform<S> for FnTransform<F, S, In, Out, Err>
where
S: Service,
F: FnMut(In, &mut S) -> Out + Clone,
Out: IntoFuture,
Out::Error: From<S::Error>,
{
type Request = In;
type Response = Out::Item;
type Error = Out::Error;
type Transform = Apply<S, F, In, Out>;
type InitError = Err;
type Future = FutureResult<Self::Transform, Self::InitError>;
fn new_transform(&self, service: S) -> Self::Future {
ok(Apply::new(service, self.f.clone()))
}
}
impl<F, S, In, Out, Err> IntoTransform<FnTransform<F, S, In, Out, Err>, S> for F
where
S: Service,
F: FnMut(In, &mut S) -> Out + Clone,
Out: IntoFuture,
Out::Error: From<S::Error>,
{
fn into_transform(self) -> FnTransform<F, S, In, Out, Err> {
FnTransform::new(self)
}
}
impl<F, S, In, Out, Err> Clone for FnTransform<F, S, In, Out, Err>
where
F: FnMut(In, &mut S) -> Out + Clone,
Out: IntoFuture,
{
fn clone(&self) -> Self {
Self::new(self.f.clone())
}
}

View File

@ -1,220 +0,0 @@
use std::marker::PhantomData;
use futures::{Async, Future, Poll};
use super::{NewService, Service};
/// Service for the `from_err` combinator, changing the error type of a service.
///
/// This is created by the `ServiceExt::from_err` method.
pub struct FromErr<A, E> {
service: A,
f: PhantomData<E>,
}
impl<A, E> FromErr<A, E> {
pub(crate) fn new(service: A) -> Self
where
A: Service,
E: From<A::Error>,
{
FromErr {
service,
f: PhantomData,
}
}
}
impl<A, E> Clone for FromErr<A, E>
where
A: Clone,
{
fn clone(&self) -> Self {
FromErr {
service: self.service.clone(),
f: PhantomData,
}
}
}
impl<A, E> Service for FromErr<A, E>
where
A: Service,
E: From<A::Error>,
{
type Request = A::Request;
type Response = A::Response;
type Error = E;
type Future = FromErrFuture<A, E>;
fn poll_ready(&mut self) -> Poll<(), E> {
self.service.poll_ready().map_err(E::from)
}
fn call(&mut self, req: A::Request) -> Self::Future {
FromErrFuture {
fut: self.service.call(req),
f: PhantomData,
}
}
}
pub struct FromErrFuture<A: Service, E> {
fut: A::Future,
f: PhantomData<E>,
}
impl<A, E> Future for FromErrFuture<A, E>
where
A: Service,
E: From<A::Error>,
{
type Item = A::Response;
type Error = E;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.fut.poll().map_err(E::from)
}
}
/// NewService for the `from_err` combinator, changing the type of a new
/// service's error.
///
/// This is created by the `NewServiceExt::from_err` method.
pub struct FromErrNewService<A, E> {
a: A,
e: PhantomData<E>,
}
impl<A, E> FromErrNewService<A, E> {
/// Create new `FromErr` new service instance
pub fn new(a: A) -> Self
where
A: NewService,
E: From<A::Error>,
{
Self { a, e: PhantomData }
}
}
impl<A, E> Clone for FromErrNewService<A, E>
where
A: Clone,
{
fn clone(&self) -> Self {
Self {
a: self.a.clone(),
e: PhantomData,
}
}
}
impl<A, E> NewService for FromErrNewService<A, E>
where
A: NewService,
E: From<A::Error>,
{
type Request = A::Request;
type Response = A::Response;
type Error = E;
type Config = A::Config;
type Service = FromErr<A::Service, E>;
type InitError = A::InitError;
type Future = FromErrNewServiceFuture<A, E>;
fn new_service(&self, cfg: &A::Config) -> Self::Future {
FromErrNewServiceFuture {
fut: self.a.new_service(cfg),
e: PhantomData,
}
}
}
pub struct FromErrNewServiceFuture<A, E>
where
A: NewService,
E: From<A::Error>,
{
fut: A::Future,
e: PhantomData<E>,
}
impl<A, E> Future for FromErrNewServiceFuture<A, E>
where
A: NewService,
E: From<A::Error>,
{
type Item = FromErr<A::Service, E>;
type Error = A::InitError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Async::Ready(service) = self.fut.poll()? {
Ok(Async::Ready(FromErr::new(service)))
} else {
Ok(Async::NotReady)
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{err, FutureResult};
use super::*;
use crate::{IntoNewService, NewService, Service, ServiceExt};
struct Srv;
impl Service for Srv {
type Request = ();
type Response = ();
type Error = ();
type Future = FutureResult<(), ()>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Err(())
}
fn call(&mut self, _: ()) -> Self::Future {
err(())
}
}
#[derive(Debug, PartialEq)]
struct Error;
impl From<()> for Error {
fn from(_: ()) -> Self {
Error
}
}
#[test]
fn test_poll_ready() {
let mut srv = Srv.from_err::<Error>();
let res = srv.poll_ready();
assert!(res.is_err());
assert_eq!(res.err().unwrap(), Error);
}
#[test]
fn test_call() {
let mut srv = Srv.from_err::<Error>();
let res = srv.call(()).poll();
assert!(res.is_err());
assert_eq!(res.err().unwrap(), Error);
}
#[test]
fn test_new_service() {
let blank = || Ok::<_, ()>(Srv);
let new_srv = blank.into_new_service().from_err::<Error>();
if let Async::Ready(mut srv) = new_srv.new_service(&()).poll().unwrap() {
let res = srv.call(()).poll();
assert!(res.is_err());
assert_eq!(res.err().unwrap(), Error);
} else {
panic!()
}
}
}

204
actix-service/src/into.rs Normal file
View File

@ -0,0 +1,204 @@
use std::task::{Context, Poll};
use crate::map::{Map, MapNewService};
use crate::map_err::{MapErr, MapErrNewService};
use crate::map_init_err::MapInitErr;
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
#[inline]
/// Convert object of type `U` to a service `T`
pub fn into_service<T, U>(service: U) -> ServiceMapper<T>
where
U: IntoService<T>,
T: Service,
{
ServiceMapper {
service: service.into_service(),
}
}
pub fn into_factory<T, F>(factory: F) -> ServiceFactoryMapper<T>
where
T: ServiceFactory,
F: IntoServiceFactory<T>,
{
ServiceFactoryMapper {
factory: factory.into_factory(),
}
}
pub struct ServiceMapper<T> {
service: T,
}
pub struct ServiceFactoryMapper<T> {
factory: T,
}
impl<T: Service> ServiceMapper<T> {
/// Map this service's output to a different type, returning a new service
/// of the resulting type.
///
/// This function is similar to the `Option::map` or `Iterator::map` where
/// it will change the type of the underlying service.
///
/// 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,
) -> ServiceMapper<impl Service<Request = T::Request, Response = R, Error = T::Error>>
where
Self: Sized,
F: FnMut(T::Response) -> R + Clone,
{
ServiceMapper {
service: Map::new(self.service, f),
}
}
/// Map this service's error to a different error, returning a new service.
///
/// This function is similar to the `Result::map_err` where it will change
/// the error type of the underlying service. This is useful for example to
/// ensure that services have the same error type.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
pub fn map_err<F, E>(
self,
f: F,
) -> ServiceMapper<impl Service<Request = T::Request, Response = T::Response, Error = E>>
where
Self: Sized,
F: Fn(T::Error) -> E + Clone,
{
ServiceMapper {
service: MapErr::new(self, f),
}
}
}
impl<T> Clone for ServiceMapper<T>
where
T: Clone,
{
fn clone(&self) -> Self {
ServiceMapper {
service: self.service.clone(),
}
}
}
impl<T: Service> Service for ServiceMapper<T> {
type Request = T::Request;
type Response = T::Response;
type Error = T::Error;
type Future = T::Future;
#[inline]
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(ctx)
}
#[inline]
fn call(&mut self, req: T::Request) -> Self::Future {
self.service.call(req)
}
}
impl<T: ServiceFactory> ServiceFactoryMapper<T> {
/// 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,
) -> ServiceFactoryMapper<
impl ServiceFactory<
Config = T::Config,
Request = T::Request,
Response = R,
Error = T::Error,
InitError = T::InitError,
>,
>
where
Self: Sized,
F: FnMut(T::Response) -> R + Clone,
{
ServiceFactoryMapper {
factory: MapNewService::new(self.factory, f),
}
}
/// Map this service's error to a different error, returning a new service.
pub fn map_err<F, E>(
self,
f: F,
) -> ServiceFactoryMapper<
impl ServiceFactory<
Config = T::Config,
Request = T::Request,
Response = T::Response,
Error = E,
InitError = T::InitError,
>,
>
where
Self: Sized,
F: Fn(T::Error) -> E + Clone,
{
ServiceFactoryMapper {
factory: MapErrNewService::new(self.factory, f),
}
}
/// Map this factory's init error to a different error, returning a new service.
pub fn map_init_err<F, E>(
self,
f: F,
) -> ServiceFactoryMapper<
impl ServiceFactory<
Config = T::Config,
Request = T::Request,
Response = T::Response,
Error = T::Error,
InitError = E,
>,
>
where
Self: Sized,
F: Fn(T::InitError) -> E + Clone,
{
ServiceFactoryMapper {
factory: MapInitErr::new(self.factory, f),
}
}
}
impl<T> Clone for ServiceFactoryMapper<T>
where
T: Clone,
{
fn clone(&self) -> Self {
ServiceFactoryMapper {
factory: self.factory.clone(),
}
}
}
impl<T: ServiceFactory> ServiceFactory for ServiceFactoryMapper<T> {
type Config = T::Config;
type Request = T::Request;
type Response = T::Response;
type Error = T::Error;
type Service = T::Service;
type InitError = T::InitError;
type Future = T::Future;
#[inline]
fn new_service(&self, cfg: &T::Config) -> Self::Future {
self.factory.new_service(cfg)
}
}

View File

@ -1,43 +1,32 @@
use std::cell::RefCell;
use std::future::Future;
use std::rc::Rc;
use std::sync::Arc;
use futures::{Future, IntoFuture, Poll};
use std::task::{self, Context, Poll};
mod and_then;
mod and_then_apply;
mod and_then_apply_fn;
mod apply;
mod apply_cfg;
pub mod blank;
pub mod boxed;
mod cell;
mod fn_service;
mod fn_transform;
mod from_err;
mod into;
mod map;
mod map_config;
mod map_err;
mod map_init_err;
mod pipeline;
mod then;
mod transform;
mod transform_err;
pub use self::and_then::{AndThen, AndThenNewService};
pub use self::apply::{apply_fn, new_apply_fn, Apply, ApplyNewService};
pub use self::apply_cfg::{apply_cfg, new_apply_cfg};
pub use self::fn_service::{new_service_cfg, new_service_fn, service_fn, ServiceFn};
pub use self::fn_transform::transform_fn;
pub use self::from_err::{FromErr, FromErrNewService};
pub use self::map::{Map, MapNewService};
pub use self::map_config::{MapConfig, MappedConfig, UnitConfig};
pub use self::map_err::{MapErr, MapErrNewService};
pub use self::map_init_err::MapInitErr;
pub use self::then::{Then, ThenNewService};
pub use self::transform::{apply_transform, IntoTransform, Transform};
use self::and_then_apply::AndThenTransform;
use self::and_then_apply_fn::{AndThenApply, AndThenApplyNewService};
pub use self::apply::{apply_fn, apply_fn_factory};
pub use self::apply_cfg::{apply_cfg, apply_cfg_factory};
pub use self::fn_service::{factory_fn, factory_fn_cfg, service_fn, service_fn2};
pub use self::into::{into_factory, into_service, ServiceFactoryMapper, ServiceMapper};
pub use self::map_config::{map_config, unit_config, MappedConfig};
pub use self::pipeline::{pipeline, pipeline_factory, Pipeline, PipelineFactory};
pub use self::transform::{apply, Transform};
/// An asynchronous function from `Request` to a `Response`.
pub trait Service {
@ -51,7 +40,7 @@ pub trait Service {
type Error;
/// The future response value.
type Future: Future<Item = Self::Response, Error = Self::Error>;
type Future: Future<Output = Result<Self::Response, Self::Error>>;
/// Returns `Ready` when the service is able to process requests.
///
@ -62,7 +51,7 @@ pub trait Service {
/// This is a **best effort** implementation. False positives are permitted.
/// It is permitted for the service to return `Ready` from a `poll_ready`
/// call and the next invocation of `call` results in an error.
fn poll_ready(&mut self) -> Poll<(), Self::Error>;
fn poll_ready(&mut self, ctx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
/// Process the request and return the response asynchronously.
///
@ -76,113 +65,16 @@ pub trait Service {
fn call(&mut self, req: Self::Request) -> Self::Future;
}
/// An extension trait for `Service`s that provides a variety of convenient
/// adapters
pub trait ServiceExt: Service {
/// Apply function to specified service and use it as a next service in
/// chain.
fn apply_fn<F, B, B1, Out>(self, service: B1, f: F) -> AndThenApply<Self, B, F, Out>
where
Self: Sized,
F: FnMut(Self::Response, &mut B) -> Out,
Out: IntoFuture,
Out::Error: Into<Self::Error>,
B: Service<Error = Self::Error>,
B1: IntoService<B>,
{
AndThenApply::new(self, service, f)
}
/// Call another service after call to this one has resolved successfully.
///
/// This function can be used to chain two services together and ensure that
/// the second service isn't called until call to the fist service have
/// finished. Result of the call to the first service is used as an
/// input parameter for the second service's call.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
fn and_then<F, B>(self, service: F) -> AndThen<Self, B>
where
Self: Sized,
F: IntoService<B>,
B: Service<Request = Self::Response, Error = Self::Error>,
{
AndThen::new(self, service.into_service())
}
/// Map this service's error to any error implementing `From` for
/// this service`s `Error`.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
fn from_err<E>(self) -> FromErr<Self, E>
where
Self: Sized,
E: From<Self::Error>,
{
FromErr::new(self)
}
/// Chain on a computation for when a call to the service finished,
/// passing the result of the call to the next service `B`.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
fn then<B>(self, service: B) -> Then<Self, B>
where
Self: Sized,
B: Service<Request = Result<Self::Response, Self::Error>, Error = Self::Error>,
{
Then::new(self, service)
}
/// Map this service's output to a different type, returning a new service
/// of the resulting type.
///
/// This function is similar to the `Option::map` or `Iterator::map` where
/// it will change the type of the underlying service.
///
/// 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.
fn map<F, R>(self, f: F) -> Map<Self, F, R>
where
Self: Sized,
F: FnMut(Self::Response) -> R,
{
Map::new(self, f)
}
/// Map this service's error to a different error, returning a new service.
///
/// This function is similar to the `Result::map_err` where it will change
/// the error type of the underlying service. This is useful for example to
/// ensure that services have the same error type.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
fn map_err<F, E>(self, f: F) -> MapErr<Self, F, E>
where
Self: Sized,
F: Fn(Self::Error) -> E,
{
MapErr::new(self, f)
}
}
impl<T: ?Sized> ServiceExt for T where T: Service {}
/// Creates new `Service` values.
///
/// Acts as a service factory. This is useful for cases where new `Service`
/// values must be produced. One case is a TCP server listener. The listener
/// accepts new TCP streams, obtains a new `Service` value using the
/// `NewService` trait, and uses that new `Service` value to process inbound
/// `ServiceFactory` trait, and uses that new `Service` value to process inbound
/// requests on that new TCP stream.
///
/// `Config` is a service factory configuration type.
pub trait NewService {
pub trait ServiceFactory {
/// Requests handled by the service.
type Request;
@ -206,132 +98,10 @@ pub trait NewService {
type InitError;
/// The future of the `Service` instance.
type Future: Future<Item = Self::Service, Error = Self::InitError>;
type Future: Future<Output = Result<Self::Service, Self::InitError>>;
/// Create and return a new service value asynchronously.
fn new_service(&self, cfg: &Self::Config) -> Self::Future;
/// Apply transform service to specified service and use it as a next service in
/// chain.
fn apply<T, T1, B, B1>(self, transform: T1, service: B1) -> AndThenTransform<T, Self, B>
where
Self: Sized,
T: Transform<B::Service, Request = Self::Response, InitError = Self::InitError>,
T::Error: From<Self::Error>,
T1: IntoTransform<T, B::Service>,
B: NewService<Config = Self::Config, InitError = Self::InitError>,
B1: IntoNewService<B>,
{
AndThenTransform::new(transform.into_transform(), self, service.into_new_service())
}
/// Apply function to specified service and use it as a next service in
/// chain.
fn apply_fn<B, I, F, Out>(self, service: I, f: F) -> AndThenApplyNewService<Self, B, F, Out>
where
Self: Sized,
B: NewService<Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,
I: IntoNewService<B>,
F: FnMut(Self::Response, &mut B::Service) -> Out,
Out: IntoFuture,
Out::Error: Into<Self::Error>,
{
AndThenApplyNewService::new(self, service, f)
}
/// Call another service after call to this one has resolved successfully.
fn and_then<F, B>(self, new_service: F) -> AndThenNewService<Self, B>
where
Self: Sized,
F: IntoNewService<B>,
B: NewService<
Config = Self::Config,
Request = Self::Response,
Error = Self::Error,
InitError = Self::InitError,
>,
{
AndThenNewService::new(self, new_service)
}
/// `NewService` that create service to map this service's error
/// and new service's init error to any error
/// implementing `From` for this service`s `Error`.
///
/// Note that this function consumes the receiving new service and returns a
/// wrapped version of it.
fn from_err<E>(self) -> FromErrNewService<Self, E>
where
Self: Sized,
E: From<Self::Error>,
{
FromErrNewService::new(self)
}
/// 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 `B`.
///
/// Note that this function consumes the receiving future and returns a
/// wrapped version of it.
fn then<F, B>(self, new_service: F) -> ThenNewService<Self, B>
where
Self: Sized,
F: IntoNewService<B>,
B: NewService<
Config = Self::Config,
Request = Result<Self::Response, Self::Error>,
Error = Self::Error,
InitError = Self::InitError,
>,
{
ThenNewService::new(self, new_service)
}
/// Map this service's output to a different type, returning a new service
/// of the resulting type.
fn map<F, R>(self, f: F) -> MapNewService<Self, F, R>
where
Self: Sized,
F: FnMut(Self::Response) -> R,
{
MapNewService::new(self, f)
}
/// Map this service's error to a different error, returning a new service.
fn map_err<F, E>(self, f: F) -> MapErrNewService<Self, F, E>
where
Self: Sized,
F: Fn(Self::Error) -> E + Clone,
{
MapErrNewService::new(self, f)
}
/// Map this factory's init error to a different error, returning a new service.
fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, E>
where
Self: Sized,
F: Fn(Self::InitError) -> E,
{
MapInitErr::new(self, f)
}
/// Map config to a different error, returning a new service.
fn map_config<F, C>(self, f: F) -> MapConfig<Self, F, C>
where
Self: Sized,
F: Fn(&C) -> MappedConfig<Self::Config>,
{
MapConfig::new(self, f)
}
/// Replace config with unit
fn unit_config<C>(self) -> UnitConfig<Self, C>
where
Self: NewService<Config = ()> + Sized,
{
UnitConfig::new(self)
}
}
impl<'a, S> Service for &'a mut S
@ -343,8 +113,8 @@ where
type Error = S::Error;
type Future = S::Future;
fn poll_ready(&mut self) -> Poll<(), S::Error> {
(**self).poll_ready()
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
(**self).poll_ready(ctx)
}
fn call(&mut self, request: Self::Request) -> S::Future {
@ -361,8 +131,8 @@ where
type Error = S::Error;
type Future = S::Future;
fn poll_ready(&mut self) -> Poll<(), S::Error> {
(**self).poll_ready()
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), S::Error>> {
(**self).poll_ready(ctx)
}
fn call(&mut self, request: Self::Request) -> S::Future {
@ -379,18 +149,18 @@ where
type Error = S::Error;
type Future = S::Future;
fn poll_ready(&mut self) -> Poll<(), S::Error> {
self.borrow_mut().poll_ready()
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.borrow_mut().poll_ready(ctx)
}
fn call(&mut self, request: Self::Request) -> S::Future {
self.borrow_mut().call(request)
(&mut (**self).borrow_mut()).call(request)
}
}
impl<S> NewService for Rc<S>
impl<S> ServiceFactory for Rc<S>
where
S: NewService,
S: ServiceFactory,
{
type Request = S::Request;
type Response = S::Response;
@ -405,9 +175,9 @@ where
}
}
impl<S> NewService for Arc<S>
impl<S> ServiceFactory for Arc<S>
where
S: NewService,
S: ServiceFactory,
{
type Request = S::Request;
type Response = S::Response;
@ -431,13 +201,13 @@ where
fn into_service(self) -> T;
}
/// Trait for types that can be converted to a `NewService`
pub trait IntoNewService<T>
/// Trait for types that can be converted to a `ServiceFactory`
pub trait IntoServiceFactory<T>
where
T: NewService,
T: ServiceFactory,
{
/// Convert to an `NewService`
fn into_new_service(self) -> T;
/// Convert `Self` an `ServiceFactory`
fn into_factory(self) -> T;
}
impl<T> IntoService<T> for T
@ -449,11 +219,11 @@ where
}
}
impl<T> IntoNewService<T> for T
impl<T> IntoServiceFactory<T> for T
where
T: NewService,
T: ServiceFactory,
{
fn into_new_service(self) -> T {
fn into_factory(self) -> T {
self
}
}

View File

@ -1,13 +1,16 @@
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::{Async, Future, Poll};
use pin_project::pin_project;
use super::{NewService, Service};
use super::{Service, ServiceFactory};
/// Service for the `map` combinator, changing the type of a service's response.
///
/// This is created by the `ServiceExt::map` method.
pub struct Map<A, F, Response> {
pub(crate) struct Map<A, F, Response> {
service: A,
f: F,
_t: PhantomData<Response>,
@ -52,8 +55,8 @@ where
type Error = A::Error;
type Future = MapFuture<A, F, Response>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(ctx)
}
fn call(&mut self, req: A::Request) -> Self::Future {
@ -61,12 +64,14 @@ where
}
}
pub struct MapFuture<A, F, Response>
#[pin_project]
pub(crate) struct MapFuture<A, F, Response>
where
A: Service,
F: FnMut(A::Response) -> Response,
{
f: F,
#[pin]
fut: A::Future,
}
@ -85,19 +90,20 @@ where
A: Service,
F: FnMut(A::Response) -> Response,
{
type Item = Response;
type Error = A::Error;
type Output = Result<Response, A::Error>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self.fut.poll()? {
Async::Ready(resp) => Ok(Async::Ready((self.f)(resp))),
Async::NotReady => Ok(Async::NotReady),
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
match this.fut.poll(cx) {
Poll::Ready(Ok(resp)) => Poll::Ready(Ok((this.f)(resp))),
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
Poll::Pending => Poll::Pending,
}
}
}
/// `MapNewService` new service combinator
pub struct MapNewService<A, F, Res> {
pub(crate) struct MapNewService<A, F, Res> {
a: A,
f: F,
r: PhantomData<Res>,
@ -107,7 +113,7 @@ impl<A, F, Res> MapNewService<A, F, Res> {
/// Create new `Map` new service instance
pub fn new(a: A, f: F) -> Self
where
A: NewService,
A: ServiceFactory,
F: FnMut(A::Response) -> Res,
{
Self {
@ -132,9 +138,9 @@ where
}
}
impl<A, F, Res> NewService for MapNewService<A, F, Res>
impl<A, F, Res> ServiceFactory for MapNewService<A, F, Res>
where
A: NewService,
A: ServiceFactory,
F: FnMut(A::Response) -> Res + Clone,
{
type Request = A::Request;
@ -151,18 +157,20 @@ where
}
}
pub struct MapNewServiceFuture<A, F, Res>
#[pin_project]
pub(crate) struct MapNewServiceFuture<A, F, Res>
where
A: NewService,
A: ServiceFactory,
F: FnMut(A::Response) -> Res,
{
#[pin]
fut: A::Future,
f: Option<F>,
}
impl<A, F, Res> MapNewServiceFuture<A, F, Res>
where
A: NewService,
A: ServiceFactory,
F: FnMut(A::Response) -> Res,
{
fn new(fut: A::Future, f: F) -> Self {
@ -172,37 +180,38 @@ where
impl<A, F, Res> Future for MapNewServiceFuture<A, F, Res>
where
A: NewService,
A: ServiceFactory,
F: FnMut(A::Response) -> Res,
{
type Item = Map<A::Service, F, Res>;
type Error = A::InitError;
type Output = Result<Map<A::Service, F, Res>, A::InitError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Async::Ready(service) = self.fut.poll()? {
Ok(Async::Ready(Map::new(service, self.f.take().unwrap())))
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(Map::new(svc, this.f.take().unwrap())))
} else {
Ok(Async::NotReady)
Poll::Pending
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{ok, FutureResult};
use futures::future::{lazy, ok, Ready};
use super::*;
use crate::{IntoNewService, Service, ServiceExt};
use crate::{into_factory, into_service, Service};
struct Srv;
impl Service for Srv {
type Request = ();
type Response = ();
type Error = ();
type Future = FutureResult<(), ()>;
type Future = Ready<Result<(), ()>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _: ()) -> Self::Future {
@ -210,32 +219,27 @@ mod tests {
}
}
#[test]
fn test_poll_ready() {
let mut srv = Srv.map(|_| "ok");
let res = srv.poll_ready();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(()));
#[tokio::test]
async fn test_poll_ready() {
let mut srv = into_service(Srv).map(|_| "ok");
let res = lazy(|cx| srv.poll_ready(cx)).await;
assert_eq!(res, Poll::Ready(Ok(())));
}
#[test]
fn test_call() {
let mut srv = Srv.map(|_| "ok");
let res = srv.call(()).poll();
#[tokio::test]
async fn test_call() {
let mut srv = into_service(Srv).map(|_| "ok");
let res = srv.call(()).await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready("ok"));
assert_eq!(res.unwrap(), "ok");
}
#[test]
fn test_new_service() {
let blank = || Ok::<_, ()>(Srv);
let new_srv = blank.into_new_service().map(|_| "ok");
if let Async::Ready(mut srv) = new_srv.new_service(&()).poll().unwrap() {
let res = srv.call(()).poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready("ok"));
} else {
panic!()
}
#[tokio::test]
async fn test_new_service() {
let new_srv = into_factory(|| ok::<_, ()>(Srv)).map(|_| "ok");
let mut srv = new_srv.new_service(&()).await.unwrap();
let res = srv.call(()).await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), ("ok"));
}
}

View File

@ -1,14 +1,48 @@
use std::marker::PhantomData;
use super::NewService;
use super::ServiceFactory;
pub enum MappedConfig<'a, T> {
Ref(&'a T),
Owned(T),
}
/// Adapt external config to a config for provided new service
pub fn map_config<T, F, C>(
factory: T,
f: F,
) -> impl ServiceFactory<
Config = C,
Request = T::Request,
Response = T::Response,
Error = T::Error,
InitError = T::InitError,
>
where
T: ServiceFactory,
F: Fn(&C) -> MappedConfig<T::Config>,
{
MapConfig::new(factory, f)
}
/// Replace config with unit
pub fn unit_config<T, C>(
new_service: T,
) -> impl ServiceFactory<
Config = C,
Request = T::Request,
Response = T::Response,
Error = T::Error,
InitError = T::InitError,
>
where
T: ServiceFactory<Config = ()>,
{
UnitConfig::new(new_service)
}
/// `MapInitErr` service combinator
pub struct MapConfig<A, F, C> {
pub(crate) struct MapConfig<A, F, C> {
a: A,
f: F,
e: PhantomData<C>,
@ -18,7 +52,7 @@ impl<A, F, C> MapConfig<A, F, C> {
/// Create new `MapConfig` combinator
pub fn new(a: A, f: F) -> Self
where
A: NewService,
A: ServiceFactory,
F: Fn(&C) -> MappedConfig<A::Config>,
{
Self {
@ -43,9 +77,9 @@ where
}
}
impl<A, F, C> NewService for MapConfig<A, F, C>
impl<A, F, C> ServiceFactory for MapConfig<A, F, C>
where
A: NewService,
A: ServiceFactory,
F: Fn(&C) -> MappedConfig<A::Config>,
{
type Request = A::Request;
@ -66,17 +100,17 @@ where
}
/// `MapInitErr` service combinator
pub struct UnitConfig<A, C> {
pub(crate) struct UnitConfig<A, C> {
a: A,
e: PhantomData<C>,
}
impl<A, C> UnitConfig<A, C> {
impl<A, C> UnitConfig<A, C>
where
A: ServiceFactory<Config = ()>,
{
/// Create new `UnitConfig` combinator
pub fn new(a: A) -> Self
where
A: NewService<Config = ()>,
{
pub(crate) fn new(a: A) -> Self {
Self { a, e: PhantomData }
}
}
@ -93,9 +127,9 @@ where
}
}
impl<A, C> NewService for UnitConfig<A, C>
impl<A, C> ServiceFactory for UnitConfig<A, C>
where
A: NewService<Config = ()>,
A: ServiceFactory<Config = ()>,
{
type Request = A::Request;
type Response = A::Response;

View File

@ -1,14 +1,17 @@
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::{Async, Future, Poll};
use pin_project::pin_project;
use super::{NewService, Service};
use super::{Service, ServiceFactory};
/// Service for the `map_err` combinator, changing the type of a service's
/// error.
///
/// This is created by the `ServiceExt::map_err` method.
pub struct MapErr<A, F, E> {
pub(crate) struct MapErr<A, F, E> {
service: A,
f: F,
_t: PhantomData<E>,
@ -53,8 +56,8 @@ where
type Error = E;
type Future = MapErrFuture<A, F, E>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready().map_err(&self.f)
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(ctx).map_err(&self.f)
}
fn call(&mut self, req: A::Request) -> Self::Future {
@ -62,12 +65,14 @@ where
}
}
pub struct MapErrFuture<A, F, E>
#[pin_project]
pub(crate) struct MapErrFuture<A, F, E>
where
A: Service,
F: Fn(A::Error) -> E,
{
f: F,
#[pin]
fut: A::Future,
}
@ -86,21 +91,21 @@ where
A: Service,
F: Fn(A::Error) -> E,
{
type Item = A::Response;
type Error = E;
type Output = Result<A::Response, E>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.fut.poll().map_err(&self.f)
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.fut.poll(cx).map_err(this.f)
}
}
/// NewService for the `map_err` combinator, changing the type of a new
/// Factory for the `map_err` combinator, changing the type of a new
/// service's error.
///
/// This is created by the `NewServiceExt::map_err` method.
pub struct MapErrNewService<A, F, E>
pub(crate) struct MapErrNewService<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::Error) -> E + Clone,
{
a: A,
@ -110,11 +115,11 @@ where
impl<A, F, E> MapErrNewService<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::Error) -> E + Clone,
{
/// Create new `MapErr` new service instance
pub fn new(a: A, f: F) -> Self {
pub(crate) fn new(a: A, f: F) -> Self {
Self {
a,
f,
@ -125,7 +130,7 @@ where
impl<A, F, E> Clone for MapErrNewService<A, F, E>
where
A: NewService + Clone,
A: ServiceFactory + Clone,
F: Fn(A::Error) -> E + Clone,
{
fn clone(&self) -> Self {
@ -137,9 +142,9 @@ where
}
}
impl<A, F, E> NewService for MapErrNewService<A, F, E>
impl<A, F, E> ServiceFactory for MapErrNewService<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::Error) -> E + Clone,
{
type Request = A::Request;
@ -156,18 +161,20 @@ where
}
}
pub struct MapErrNewServiceFuture<A, F, E>
#[pin_project]
pub(crate) struct MapErrNewServiceFuture<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::Error) -> E,
{
#[pin]
fut: A::Future,
f: F,
}
impl<A, F, E> MapErrNewServiceFuture<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::Error) -> E,
{
fn new(fut: A::Future, f: F) -> Self {
@ -177,27 +184,27 @@ where
impl<A, F, E> Future for MapErrNewServiceFuture<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::Error) -> E + Clone,
{
type Item = MapErr<A::Service, F, E>;
type Error = A::InitError;
type Output = Result<MapErr<A::Service, F, E>, A::InitError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Async::Ready(service) = self.fut.poll()? {
Ok(Async::Ready(MapErr::new(service, self.f.clone())))
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(MapErr::new(svc, this.f.clone())))
} else {
Ok(Async::NotReady)
Poll::Pending
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{err, FutureResult};
use futures::future::{err, lazy, ok, Ready};
use super::*;
use crate::{IntoNewService, NewService, Service, ServiceExt};
use crate::{into_factory, into_service, Service};
struct Srv;
@ -205,10 +212,10 @@ mod tests {
type Request = ();
type Response = ();
type Error = ();
type Future = FutureResult<(), ()>;
type Future = Ready<Result<(), ()>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Err(())
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Err(()))
}
fn call(&mut self, _: ()) -> Self::Future {
@ -216,32 +223,27 @@ mod tests {
}
}
#[test]
fn test_poll_ready() {
let mut srv = Srv.map_err(|_| "error");
let res = srv.poll_ready();
#[tokio::test]
async fn test_poll_ready() {
let mut srv = into_service(Srv).map_err(|_| "error");
let res = lazy(|cx| srv.poll_ready(cx)).await;
assert_eq!(res, Poll::Ready(Err("error")));
}
#[tokio::test]
async fn test_call() {
let mut srv = into_service(Srv).map_err(|_| "error");
let res = srv.call(()).await;
assert!(res.is_err());
assert_eq!(res.err().unwrap(), "error");
}
#[test]
fn test_call() {
let mut srv = Srv.map_err(|_| "error");
let res = srv.call(()).poll();
#[tokio::test]
async fn test_new_service() {
let new_srv = into_factory(|| ok::<_, ()>(Srv)).map_err(|_| "error");
let mut srv = new_srv.new_service(&()).await.unwrap();
let res = srv.call(()).await;
assert!(res.is_err());
assert_eq!(res.err().unwrap(), "error");
}
#[test]
fn test_new_service() {
let blank = || Ok::<_, ()>(Srv);
let new_srv = blank.into_new_service().map_err(|_| "error");
if let Async::Ready(mut srv) = new_srv.new_service(&()).poll().unwrap() {
let res = srv.call(()).poll();
assert!(res.is_err());
assert_eq!(res.err().unwrap(), "error");
} else {
panic!()
}
}
}

View File

@ -1,23 +1,26 @@
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::{Future, Poll};
use pin_project::pin_project;
use super::NewService;
use super::ServiceFactory;
/// `MapInitErr` service combinator
pub struct MapInitErr<A, F, E> {
pub(crate) struct MapInitErr<A, F, E> {
a: A,
f: F,
e: PhantomData<E>,
}
impl<A, F, E> MapInitErr<A, F, E> {
impl<A, F, E> MapInitErr<A, F, E>
where
A: ServiceFactory,
F: Fn(A::InitError) -> E,
{
/// Create new `MapInitErr` combinator
pub fn new(a: A, f: F) -> Self
where
A: NewService,
F: Fn(A::InitError) -> E,
{
pub(crate) fn new(a: A, f: F) -> Self {
Self {
a,
f,
@ -40,9 +43,9 @@ where
}
}
impl<A, F, E> NewService for MapInitErr<A, F, E>
impl<A, F, E> ServiceFactory for MapInitErr<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::InitError) -> E + Clone,
{
type Request = A::Request;
@ -58,19 +61,20 @@ where
MapInitErrFuture::new(self.a.new_service(cfg), self.f.clone())
}
}
pub struct MapInitErrFuture<A, F, E>
#[pin_project]
pub(crate) struct MapInitErrFuture<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::InitError) -> E,
{
f: F,
#[pin]
fut: A::Future,
}
impl<A, F, E> MapInitErrFuture<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::InitError) -> E,
{
fn new(fut: A::Future, f: F) -> Self {
@ -80,13 +84,13 @@ where
impl<A, F, E> Future for MapInitErrFuture<A, F, E>
where
A: NewService,
A: ServiceFactory,
F: Fn(A::InitError) -> E,
{
type Item = A::Service;
type Error = E;
type Output = Result<A::Service, E>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.fut.poll().map_err(&self.f)
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.fut.poll(cx).map_err(this.f)
}
}

View File

@ -0,0 +1,196 @@
use std::task::{Context, Poll};
use crate::and_then::{AndThen, AndThenNewService};
use crate::then::{Then, ThenNewService};
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
pub fn pipeline<F, T>(service: F) -> Pipeline<T>
where
F: IntoService<T>,
T: Service,
{
Pipeline {
service: service.into_service(),
}
}
pub fn pipeline_factory<T, F>(factory: F) -> PipelineFactory<T>
where
T: ServiceFactory,
F: IntoServiceFactory<T>,
{
PipelineFactory {
factory: factory.into_factory(),
}
}
/// Pipeline service
pub struct Pipeline<T> {
service: T,
}
impl<T: Service> Pipeline<T> {
/// Call another service after call to this one has resolved successfully.
///
/// This function can be used to chain two services together and ensure that
/// the second service isn't called until call to the fist service have
/// finished. Result of the call to the first service is used as an
/// input parameter for the second service's call.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
pub fn and_then<F, U>(
self,
service: F,
) -> Pipeline<impl Service<Request = T::Request, Response = U::Response, Error = T::Error>>
where
Self: Sized,
F: IntoService<U>,
U: Service<Request = T::Response, Error = T::Error>,
{
Pipeline {
service: AndThen::new(self.service, service.into_service()),
}
}
/// Chain on a computation for when a call to the service finished,
/// passing the result of the call to the next service `U`.
///
/// Note that this function consumes the receiving pipeline and returns a
/// wrapped version of it.
pub fn then<F, U>(
self,
service: F,
) -> Pipeline<impl Service<Request = T::Request, Response = U::Response, Error = T::Error>>
where
Self: Sized,
F: IntoService<U>,
U: Service<Request = Result<T::Response, T::Error>, Error = T::Error>,
{
Pipeline {
service: Then::new(self.service, service.into_service()),
}
}
}
impl<T> Clone for Pipeline<T>
where
T: Clone,
{
fn clone(&self) -> Self {
Pipeline {
service: self.service.clone(),
}
}
}
impl<T: Service> Service for Pipeline<T> {
type Request = T::Request;
type Response = T::Response;
type Error = T::Error;
type Future = T::Future;
#[inline]
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), T::Error>> {
self.service.poll_ready(ctx)
}
#[inline]
fn call(&mut self, req: T::Request) -> Self::Future {
self.service.call(req)
}
}
/// Pipeline constructor
pub struct PipelineFactory<T> {
factory: T,
}
impl<T: ServiceFactory> PipelineFactory<T> {
/// Call another service after call to this one has resolved successfully.
pub fn and_then<F, U>(
self,
factory: F,
) -> PipelineFactory<
impl ServiceFactory<
Config = T::Config,
Request = T::Request,
Response = U::Response,
Error = T::Error,
InitError = T::InitError,
>,
>
where
Self: Sized,
F: IntoServiceFactory<U>,
U: ServiceFactory<
Config = T::Config,
Request = T::Response,
Error = T::Error,
InitError = T::InitError,
>,
{
PipelineFactory {
factory: AndThenNewService::new(self.factory, factory.into_factory()),
}
}
/// 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 `U`.
///
/// Note that this function consumes the receiving pipeline and returns a
/// wrapped version of it.
pub fn then<F, U>(
self,
factory: F,
) -> PipelineFactory<
impl ServiceFactory<
Config = T::Config,
Request = T::Request,
Response = U::Response,
Error = T::Error,
InitError = T::InitError,
>,
>
where
Self: Sized,
F: IntoServiceFactory<U>,
U: ServiceFactory<
Config = T::Config,
Request = Result<T::Response, T::Error>,
Error = T::Error,
InitError = T::InitError,
>,
{
PipelineFactory {
factory: ThenNewService::new(self.factory, factory.into_factory()),
}
}
}
impl<T> Clone for PipelineFactory<T>
where
T: Clone,
{
fn clone(&self) -> Self {
PipelineFactory {
factory: self.factory.clone(),
}
}
}
impl<T: ServiceFactory> ServiceFactory for PipelineFactory<T> {
type Config = T::Config;
type Request = T::Request;
type Response = T::Response;
type Error = T::Error;
type Service = T::Service;
type InitError = T::InitError;
type Future = T::Future;
#[inline]
fn new_service(&self, cfg: &T::Config) -> Self::Future {
self.factory.new_service(cfg)
}
}

View File

@ -1,13 +1,17 @@
use futures::{Async, Future, Poll};
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use super::{IntoNewService, NewService, Service};
use pin_project::pin_project;
use super::{Service, ServiceFactory};
use crate::cell::Cell;
/// Service for the `then` combinator, chaining a computation onto the end of
/// another service.
///
/// This is created by the `ServiceExt::then` method.
pub struct Then<A, B> {
pub(crate) struct Then<A, B> {
a: A,
b: Cell<B>,
}
@ -45,12 +49,12 @@ where
type Error = B::Error;
type Future = ThenFuture<A, B>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
let not_ready = self.a.poll_ready()?.is_not_ready();
if self.b.get_mut().poll_ready()?.is_not_ready() || not_ready {
Ok(Async::NotReady)
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let not_ready = !self.a.poll_ready(ctx)?.is_ready();
if !self.b.get_mut().poll_ready(ctx)?.is_ready() || not_ready {
Poll::Pending
} else {
Ok(Async::Ready(()))
Poll::Ready(Ok(()))
}
}
@ -59,13 +63,16 @@ where
}
}
pub struct ThenFuture<A, B>
#[pin_project]
pub(crate) struct ThenFuture<A, B>
where
A: Service,
B: Service<Request = Result<A::Response, A::Error>>,
{
b: Cell<B>,
#[pin]
fut_b: Option<B::Future>,
#[pin]
fut_a: Option<A::Future>,
}
@ -88,60 +95,63 @@ where
A: Service,
B: Service<Request = Result<A::Response, A::Error>>,
{
type Item = B::Response;
type Error = B::Error;
type Output = Result<B::Response, B::Error>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut_b {
return fut.poll();
}
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
match self.fut_a.as_mut().expect("bug in actix-service").poll() {
Ok(Async::Ready(resp)) => {
let _ = self.fut_a.take();
self.fut_b = Some(self.b.get_mut().call(Ok(resp)));
self.poll()
loop {
let mut fut_a = this.fut_a.as_mut();
let mut fut_b = this.fut_b.as_mut();
if let Some(fut) = fut_b.as_mut().as_pin_mut() {
return fut.poll(cx);
}
Err(err) => {
let _ = self.fut_a.take();
self.fut_b = Some(self.b.get_mut().call(Err(err)));
self.poll()
match fut_a
.as_mut()
.as_pin_mut()
.expect("Bug in actix-service")
.poll(cx)
{
Poll::Ready(r) => {
fut_a.set(None);
let new_fut = this.b.get_mut().call(r);
fut_b.set(Some(new_fut));
}
Poll::Pending => return Poll::Pending,
}
Ok(Async::NotReady) => Ok(Async::NotReady),
}
}
}
/// `ThenNewService` new service combinator
pub struct ThenNewService<A, B> {
/// `.then()` service factory combinator
pub(crate) struct ThenNewService<A, B> {
a: A,
b: B,
}
impl<A, B> ThenNewService<A, B> {
impl<A, B> ThenNewService<A, B>
where
A: ServiceFactory,
B: ServiceFactory<
Config = A::Config,
Request = Result<A::Response, A::Error>,
Error = A::Error,
InitError = A::InitError,
>,
{
/// Create new `AndThen` combinator
pub fn new<F>(a: A, f: F) -> Self
where
A: NewService,
B: NewService<
Config = A::Config,
Request = Result<A::Response, A::Error>,
Error = A::Error,
InitError = A::InitError,
>,
F: IntoNewService<B>,
{
Self {
a,
b: f.into_new_service(),
}
pub fn new(a: A, b: B) -> Self {
Self { a, b }
}
}
impl<A, B> NewService for ThenNewService<A, B>
impl<A, B> ServiceFactory for ThenNewService<A, B>
where
A: NewService,
B: NewService<
A: ServiceFactory,
B: ServiceFactory<
Config = A::Config,
Request = Result<A::Response, A::Error>,
Error = A::Error,
@ -175,17 +185,20 @@ where
}
}
pub struct ThenNewServiceFuture<A, B>
#[pin_project]
pub(crate) struct ThenNewServiceFuture<A, B>
where
A: NewService,
B: NewService<
A: ServiceFactory,
B: ServiceFactory<
Config = A::Config,
Request = Result<A::Response, A::Error>,
Error = A::Error,
InitError = A::InitError,
>,
{
#[pin]
fut_b: B::Future,
#[pin]
fut_a: A::Future,
a: Option<A::Service>,
b: Option<B::Service>,
@ -193,8 +206,8 @@ where
impl<A, B> ThenNewServiceFuture<A, B>
where
A: NewService,
B: NewService<
A: ServiceFactory,
B: ServiceFactory<
Config = A::Config,
Request = Result<A::Response, A::Error>,
Error = A::Error,
@ -213,61 +226,61 @@ where
impl<A, B> Future for ThenNewServiceFuture<A, B>
where
A: NewService,
B: NewService<
A: ServiceFactory,
B: ServiceFactory<
Config = A::Config,
Request = Result<A::Response, A::Error>,
Error = A::Error,
InitError = A::InitError,
>,
{
type Item = Then<A::Service, B::Service>;
type Error = A::InitError;
type Output = Result<Then<A::Service, B::Service>, A::InitError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.a.is_none() {
if let Async::Ready(service) = self.fut_a.poll()? {
self.a = Some(service);
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 self.b.is_none() {
if let Async::Ready(service) = self.fut_b.poll()? {
self.b = Some(service);
if this.b.is_none() {
if let Poll::Ready(service) = this.fut_b.poll(cx)? {
*this.b = Some(service);
}
}
if self.a.is_some() && self.b.is_some() {
Ok(Async::Ready(Then::new(
self.a.take().unwrap(),
self.b.take().unwrap(),
if this.a.is_some() && this.b.is_some() {
Poll::Ready(Ok(Then::new(
this.a.take().unwrap(),
this.b.take().unwrap(),
)))
} else {
Ok(Async::NotReady)
Poll::Pending
}
}
}
#[cfg(test)]
mod tests {
use futures::future::{err, ok, FutureResult};
use futures::{Async, Future, Poll};
use std::cell::Cell;
use std::rc::Rc;
use std::task::{Context, Poll};
use crate::{IntoNewService, NewService, Service, ServiceExt};
use futures::future::{err, lazy, ok, ready, Ready};
use crate::{pipeline, pipeline_factory, Service, ServiceFactory};
#[derive(Clone)]
struct Srv1(Rc<Cell<usize>>);
impl Service for Srv1 {
type Request = Result<&'static str, &'static str>;
type Response = &'static str;
type Error = ();
type Future = FutureResult<Self::Response, Self::Error>;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.0.set(self.0.get() + 1);
Ok(Async::Ready(()))
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Result<&'static str, &'static str>) -> Self::Future {
@ -284,11 +297,11 @@ mod tests {
type Request = Result<&'static str, ()>;
type Response = (&'static str, &'static str);
type Error = ();
type Future = FutureResult<Self::Response, ()>;
type Future = Ready<Result<Self::Response, ()>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.0.set(self.0.get() + 1);
Ok(Async::Ready(()))
Poll::Ready(Err(()))
}
fn call(&mut self, req: Result<&'static str, ()>) -> Self::Future {
@ -299,46 +312,42 @@ mod tests {
}
}
#[test]
fn test_poll_ready() {
#[tokio::test]
async fn test_poll_ready() {
let cnt = Rc::new(Cell::new(0));
let mut srv = Srv1(cnt.clone()).then(Srv2(cnt.clone()));
let res = srv.poll_ready();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(()));
let mut srv = pipeline(Srv1(cnt.clone())).then(Srv2(cnt.clone()));
let res = lazy(|cx| srv.poll_ready(cx)).await;
assert_eq!(res, Poll::Ready(Err(())));
assert_eq!(cnt.get(), 2);
}
#[test]
fn test_call() {
#[tokio::test]
async fn test_call() {
let cnt = Rc::new(Cell::new(0));
let mut srv = Srv1(cnt.clone()).then(Srv2(cnt)).clone();
let mut srv = pipeline(Srv1(cnt.clone())).then(Srv2(cnt));
let res = srv.call(Ok("srv1")).poll();
let res = srv.call(Ok("srv1")).await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv1", "ok")));
assert_eq!(res.unwrap(), (("srv1", "ok")));
let res = srv.call(Err("srv")).poll();
let res = srv.call(Err("srv")).await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv2", "err")));
assert_eq!(res.unwrap(), (("srv2", "err")));
}
#[test]
fn test_new_service() {
#[tokio::test]
async fn test_factory() {
let cnt = Rc::new(Cell::new(0));
let cnt2 = cnt.clone();
let blank = move || Ok::<_, ()>(Srv1(cnt2.clone()));
let new_srv = blank.into_new_service().then(move || Ok(Srv2(cnt.clone())));
if let Async::Ready(mut srv) = new_srv.clone().new_service(&()).poll().unwrap() {
let res = srv.call(Ok("srv1")).poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv1", "ok")));
let blank = move || ready(Ok::<_, ()>(Srv1(cnt2.clone())));
let factory = pipeline_factory(blank).then(move || ready(Ok(Srv2(cnt.clone()))));
let mut srv = factory.new_service(&()).await.unwrap();
let res = srv.call(Ok("srv1")).await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), (("srv1", "ok")));
let res = srv.call(Err("srv")).poll();
assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv2", "err")));
} else {
panic!()
}
let res = srv.call(Err("srv")).await;
assert!(res.is_ok());
assert_eq!(res.unwrap(), (("srv2", "err")));
}
}

View File

@ -1,10 +1,13 @@
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
use std::task::{Context, Poll};
use futures::{Async, Future, IntoFuture, Poll};
use crate::transform_err::TransformMapInitErr;
use crate::{IntoServiceFactory, Service, ServiceFactory};
use crate::transform_err::{TransformFromErr, TransformMapInitErr};
use crate::{IntoNewService, NewService, Service};
use pin_project::pin_project;
/// The `Transform` trait defines the interface of a Service factory. `Transform`
/// is often implemented for middleware, defining how to construct a
@ -32,7 +35,7 @@ pub trait Transform<S> {
type InitError;
/// The future response value.
type Future: Future<Item = Self::Transform, Error = Self::InitError>;
type Future: Future<Output = Result<Self::Transform, Self::InitError>>;
/// Creates and returns a new Service component, asynchronously
fn new_transform(&self, service: S) -> Self::Future;
@ -46,32 +49,6 @@ pub trait Transform<S> {
{
TransformMapInitErr::new(self, f)
}
/// Map this service's init error to any error implementing `From` for
/// this service`s `Error`.
///
/// Note that this function consumes the receiving transform and returns a
/// wrapped version of it.
fn from_err<E>(self) -> TransformFromErr<Self, S, E>
where
Self: Sized,
E: From<Self::InitError>,
{
TransformFromErr::new(self)
}
// /// Map this service's init error to service's init error
// /// if it is implementing `Into` to this service`s `InitError`.
// ///
// /// Note that this function consumes the receiving transform and returns a
// /// wrapped version of it.
// fn into_err<E>(self) -> TransformIntoErr<Self, S>
// where
// Self: Sized,
// Self::InitError: From<Self::InitError>,
// {
// TransformFromErr::new(self)
// }
}
impl<T, S> Transform<S> for Rc<T>
@ -106,31 +83,13 @@ where
}
}
/// Trait for types that can be converted to a *transform service*
pub trait IntoTransform<T, S>
where
T: Transform<S>,
{
/// Convert to a `TransformService`
fn into_transform(self) -> T;
}
impl<T, S> IntoTransform<T, S> for T
where
T: Transform<S>,
{
fn into_transform(self) -> T {
self
}
}
/// Apply transform to service factory. Function returns
/// Apply transform to a service. Function returns
/// services factory that in initialization creates
/// service and applies transform to this service.
pub fn apply_transform<T, S, F, U>(
t: F,
pub fn apply<T, S, U>(
t: T,
service: U,
) -> impl NewService<
) -> impl ServiceFactory<
Config = S::Config,
Request = T::Request,
Response = T::Response,
@ -139,30 +98,29 @@ pub fn apply_transform<T, S, F, U>(
InitError = S::InitError,
> + Clone
where
S: NewService,
S: ServiceFactory,
T: Transform<S::Service, InitError = S::InitError>,
F: IntoTransform<T, S::Service>,
U: IntoNewService<S>,
U: IntoServiceFactory<S>,
{
ApplyTransform::new(t.into_transform(), service.into_new_service())
ApplyTransform::new(t, service.into_factory())
}
/// `Apply` transform to new service
pub struct ApplyTransform<T, S> {
struct ApplyTransform<T, S> {
s: Rc<S>,
t: Rc<T>,
}
impl<T, S> ApplyTransform<T, S>
where
S: NewService,
S: ServiceFactory,
T: Transform<S::Service, InitError = S::InitError>,
{
/// Create new `ApplyTransform` new service instance
pub fn new<F: IntoTransform<T, S::Service>>(t: F, service: S) -> Self {
fn new(t: T, service: S) -> Self {
Self {
s: Rc::new(service),
t: Rc::new(t.into_transform()),
t: Rc::new(t),
}
}
}
@ -176,9 +134,9 @@ impl<T, S> Clone for ApplyTransform<T, S> {
}
}
impl<T, S> NewService for ApplyTransform<T, S>
impl<T, S> ServiceFactory for ApplyTransform<T, S>
where
S: NewService,
S: ServiceFactory,
T: Transform<S::Service, InitError = S::InitError>,
{
type Request = T::Request;
@ -193,40 +151,45 @@ where
fn new_service(&self, cfg: &S::Config) -> Self::Future {
ApplyTransformFuture {
t_cell: self.t.clone(),
fut_a: self.s.new_service(cfg).into_future(),
fut_a: self.s.new_service(cfg),
fut_t: None,
}
}
}
pub struct ApplyTransformFuture<T, S>
#[pin_project]
struct ApplyTransformFuture<T, S>
where
S: NewService,
S: ServiceFactory,
T: Transform<S::Service, InitError = S::InitError>,
{
#[pin]
fut_a: S::Future,
fut_t: Option<<T::Future as IntoFuture>::Future>,
#[pin]
fut_t: Option<T::Future>,
t_cell: Rc<T>,
}
impl<T, S> Future for ApplyTransformFuture<T, S>
where
S: NewService,
S: ServiceFactory,
T: Transform<S::Service, InitError = S::InitError>,
{
type Item = T::Transform;
type Error = T::InitError;
type Output = Result<T::Transform, T::InitError>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.fut_t.is_none() {
if let Async::Ready(service) = self.fut_a.poll()? {
self.fut_t = Some(self.t_cell.new_transform(service).into_future());
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
if this.fut_t.as_mut().as_pin_mut().is_none() {
if let Poll::Ready(service) = this.fut_a.poll(cx)? {
this.fut_t.set(Some(this.t_cell.new_transform(service)));
}
}
if let Some(ref mut fut) = self.fut_t {
fut.poll()
if let Some(fut) = this.fut_t.as_mut().as_pin_mut() {
fut.poll(cx)
} else {
Ok(Async::NotReady)
Poll::Pending
}
}
}

View File

@ -1,6 +1,9 @@
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::{Future, Poll};
use pin_project::pin_project;
use super::Transform;
@ -63,12 +66,13 @@ where
}
}
}
#[pin_project]
pub struct TransformMapInitErrFuture<T, S, F, E>
where
T: Transform<S>,
F: Fn(T::InitError) -> E,
{
#[pin]
fut: T::Future,
f: F,
}
@ -78,85 +82,10 @@ where
T: Transform<S>,
F: Fn(T::InitError) -> E + Clone,
{
type Item = T::Transform;
type Error = E;
type Output = Result<T::Transform, E>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.fut.poll().map_err(&self.f)
}
}
/// Transform for the `from_err` combinator, changing the type of a new
/// transform's init error.
///
/// This is created by the `Transform::from_err` method.
pub struct TransformFromErr<T, S, E> {
t: T,
e: PhantomData<(S, E)>,
}
impl<T, S, E> TransformFromErr<T, S, E>
where
T: Transform<S>,
E: From<T::InitError>,
{
/// Create new `TransformFromErr` new transform instance
pub fn new(t: T) -> Self {
Self { t, e: PhantomData }
}
}
impl<T, S, E> Clone for TransformFromErr<T, S, E>
where
T: Clone,
{
fn clone(&self) -> Self {
Self {
t: self.t.clone(),
e: PhantomData,
}
}
}
impl<T, S, E> Transform<S> for TransformFromErr<T, S, E>
where
T: Transform<S>,
E: From<T::InitError>,
{
type Request = T::Request;
type Response = T::Response;
type Error = T::Error;
type Transform = T::Transform;
type InitError = E;
type Future = TransformFromErrFuture<T, S, E>;
fn new_transform(&self, service: S) -> Self::Future {
TransformFromErrFuture {
fut: self.t.new_transform(service),
_t: PhantomData,
}
}
}
pub struct TransformFromErrFuture<T, S, E>
where
T: Transform<S>,
E: From<T::InitError>,
{
fut: T::Future,
_t: PhantomData<E>,
}
impl<T, S, E> Future for TransformFromErrFuture<T, S, E>
where
T: Transform<S>,
E: From<T::InitError>,
{
type Item = T::Transform;
type Error = E;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.fut.poll().map_err(E::from)
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.fut.poll(cx).map_err(this.f)
}
}