1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-12-22 08:07:18 +00:00

better error conversion impl for and_then

This commit is contained in:
Nikolay Kim 2018-09-04 12:07:13 -07:00
parent 41eddae266
commit 9456065d7b
5 changed files with 143 additions and 51 deletions

View file

@ -259,14 +259,18 @@ where
impl<A, B, C> NewConfigurableService<C> for AndThenNewConfigurableService<A, B, C> impl<A, B, C> NewConfigurableService<C> for AndThenNewConfigurableService<A, B, C>
where where
A: NewConfigurableService<C, Response = B::Request, InitError = B::InitError>, A: NewConfigurableService<C>,
A::Error: Into<B::Error>, B: NewConfigurableService<
B: NewConfigurableService<C>, C,
Request = A::Response,
Error = A::Error,
InitError = A::InitError,
>,
C: Clone, C: Clone,
{ {
type Request = A::Request; type Request = A::Request;
type Response = B::Response; type Response = B::Response;
type Error = B::Error; type Error = A::Error;
type Service = AndThen<A::Service, B::Service>; type Service = AndThen<A::Service, B::Service>;
type InitError = A::InitError; type InitError = A::InitError;
@ -282,9 +286,13 @@ where
impl<A, B, C> Clone for AndThenNewConfigurableService<A, B, C> impl<A, B, C> Clone for AndThenNewConfigurableService<A, B, C>
where where
A: NewConfigurableService<C, Response = B::Request, InitError = B::InitError> + Clone, A: NewConfigurableService<C> + Clone,
A::Error: Into<B::Error>, B: NewConfigurableService<
B: NewConfigurableService<C> + Clone, C,
Request = A::Response,
Error = A::Error,
InitError = A::InitError,
> + Clone,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
@ -326,18 +334,22 @@ where
impl<A, B, C> Future for AndThenNewConfigurableServiceFuture<A, B, C> impl<A, B, C> Future for AndThenNewConfigurableServiceFuture<A, B, C>
where where
A: NewConfigurableService<C>, A: NewConfigurableService<C>,
A::Error: Into<B::Error>, B: NewConfigurableService<
B: NewConfigurableService<C, Request = A::Response, InitError = A::InitError>, C,
Request = A::Response,
Error = A::Error,
InitError = A::InitError,
>,
{ {
type Item = AndThen<A::Service, B::Service>; type Item = AndThen<A::Service, B::Service>;
type Error = B::InitError; type Error = A::InitError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Async::Ready(service) = self.fut_a.poll()? { if let Async::Ready(service) = self.fut_a.poll()? {
self.a = Some(service); self.a = Some(service);
} }
if let Async::Ready(service) = self.fut_b.poll()? { if let Async::Ready(service) = self.fut_b.poll().map_err(|e| e.into())? {
self.b = Some(service); self.b = Some(service);
} }

View file

@ -15,8 +15,7 @@ pub struct AndThen<A, B> {
impl<A, B> AndThen<A, B> impl<A, B> AndThen<A, B>
where where
A: Service, A: Service,
A::Error: Into<B::Error>, B: Service<Request = A::Response, Error = A::Error>,
B: Service<Request = A::Response>,
{ {
/// Create new `AndThen` combinator /// Create new `AndThen` combinator
pub fn new(a: A, b: B) -> Self { pub fn new(a: A, b: B) -> Self {
@ -30,19 +29,18 @@ where
impl<A, B> Service for AndThen<A, B> impl<A, B> Service for AndThen<A, B>
where where
A: Service, A: Service,
A::Error: Into<B::Error>, B: Service<Request = A::Response, Error = A::Error>,
B: Service<Request = A::Response>,
{ {
type Request = A::Request; type Request = A::Request;
type Response = B::Response; type Response = B::Response;
type Error = B::Error; type Error = A::Error;
type Future = AndThenFuture<A, B>; type Future = AndThenFuture<A, B>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self) -> Poll<(), Self::Error> {
match self.a.poll_ready() { match self.a.poll_ready() {
Ok(Async::Ready(_)) => self.b.borrow_mut().poll_ready(), Ok(Async::Ready(_)) => self.b.borrow_mut().poll_ready().map_err(|e| e.into()),
Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::NotReady) => Ok(Async::NotReady),
Err(err) => Err(err.into()), Err(err) => Err(err),
} }
} }
@ -54,8 +52,7 @@ where
pub struct AndThenFuture<A, B> pub struct AndThenFuture<A, B>
where where
A: Service, A: Service,
A::Error: Into<B::Error>, B: Service<Request = A::Response, Error = A::Error>,
B: Service<Request = A::Response>,
{ {
b: Rc<RefCell<B>>, b: Rc<RefCell<B>>,
fut_b: Option<B::Future>, fut_b: Option<B::Future>,
@ -65,8 +62,7 @@ where
impl<A, B> AndThenFuture<A, B> impl<A, B> AndThenFuture<A, B>
where where
A: Service, A: Service,
A::Error: Into<B::Error>, B: Service<Request = A::Response, Error = A::Error>,
B: Service<Request = A::Response>,
{ {
fn new(fut_a: A::Future, b: Rc<RefCell<B>>) -> Self { fn new(fut_a: A::Future, b: Rc<RefCell<B>>) -> Self {
AndThenFuture { AndThenFuture {
@ -80,15 +76,15 @@ where
impl<A, B> Future for AndThenFuture<A, B> impl<A, B> Future for AndThenFuture<A, B>
where where
A: Service, A: Service,
A::Error: Into<B::Error>, B: Service<Request = A::Response, Error = A::Error>,
B: Service<Request = A::Response>, B::Error: Into<A::Error>,
{ {
type Item = B::Response; type Item = B::Response;
type Error = B::Error; type Error = A::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut_b { if let Some(ref mut fut) = self.fut_b {
return fut.poll(); return fut.poll().map_err(|e| e.into());
} }
match self.fut_a.poll() { match self.fut_a.poll() {
@ -97,7 +93,7 @@ where
self.poll() self.poll()
} }
Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::NotReady) => Ok(Async::NotReady),
Err(err) => Err(err.into()), Err(err) => Err(err),
} }
} }
} }
@ -124,17 +120,15 @@ where
impl<A, B> NewService for AndThenNewService<A, B> impl<A, B> NewService for AndThenNewService<A, B>
where where
A: NewService<Response = B::Request, InitError = B::InitError>, A: NewService,
A::Error: Into<B::Error>, B: NewService<Request = A::Response, Error = A::Error, InitError = A::InitError>,
A::InitError: Into<B::InitError>,
B: NewService,
{ {
type Request = A::Request; type Request = A::Request;
type Response = B::Response; type Response = B::Response;
type Error = B::Error; type Error = A::Error;
type Service = AndThen<A::Service, B::Service>; type Service = AndThen<A::Service, B::Service>;
type InitError = B::InitError; type InitError = A::InitError;
type Future = AndThenNewServiceFuture<A, B>; type Future = AndThenNewServiceFuture<A, B>;
fn new_service(&self) -> Self::Future { fn new_service(&self) -> Self::Future {
@ -144,10 +138,8 @@ where
impl<A, B> Clone for AndThenNewService<A, B> impl<A, B> Clone for AndThenNewService<A, B>
where where
A: NewService<Response = B::Request, InitError = B::InitError> + Clone, A: NewService + Clone,
A::Error: Into<B::Error>, B: NewService<Request = A::Response, Error = A::Error, InitError = A::InitError> + Clone,
A::InitError: Into<B::InitError>,
B: NewService + Clone,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
@ -186,22 +178,20 @@ where
impl<A, B> Future for AndThenNewServiceFuture<A, B> impl<A, B> Future for AndThenNewServiceFuture<A, B>
where where
A: NewService, A: NewService,
A::Error: Into<B::Error>, B: NewService<Request = A::Response, Error = A::Error, InitError = A::InitError>,
A::InitError: Into<B::InitError>,
B: NewService<Request = A::Response>,
{ {
type Item = AndThen<A::Service, B::Service>; type Item = AndThen<A::Service, B::Service>;
type Error = B::InitError; type Error = A::InitError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.a.is_none() { if self.a.is_none() {
if let Async::Ready(service) = self.fut_a.poll().map_err(|e| e.into())? { if let Async::Ready(service) = self.fut_a.poll()? {
self.a = Some(service); self.a = Some(service);
} }
} }
if self.b.is_none() { if self.b.is_none() {
if let Async::Ready(service) = self.fut_b.poll()? { if let Async::Ready(service) = self.fut_b.poll().map_err(|e| e.into())? {
self.b = Some(service); self.b = Some(service);
} }
} }

61
src/service/from_err.rs Normal file
View file

@ -0,0 +1,61 @@
use std::marker::PhantomData;
use futures::{Future, Poll};
use tower_service::Service;
pub struct FromErr<A, E>
where
A: Service,
{
service: A,
f: PhantomData<E>,
}
impl<A: Service, E: From<A::Error>> FromErr<A, E> {
pub(crate) fn new(service: A) -> Self {
FromErr {
service,
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> {
Ok(self.service.poll_ready().map_err(E::from)?)
}
fn call(&mut self, req: Self::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)
}
}

View file

@ -4,6 +4,7 @@ mod and_then;
mod apply; mod apply;
mod fn_service; mod fn_service;
mod fn_state_service; mod fn_state_service;
mod from_err;
mod map; mod map;
mod map_err; mod map_err;
mod map_init_err; mod map_init_err;
@ -12,6 +13,7 @@ pub use self::and_then::{AndThen, AndThenNewService};
pub use self::apply::{Apply, ApplyNewService}; pub use self::apply::{Apply, ApplyNewService};
pub use self::fn_service::{FnNewService, FnService}; pub use self::fn_service::{FnNewService, FnService};
pub use self::fn_state_service::{FnStateNewService, FnStateService}; pub use self::fn_state_service::{FnStateNewService, FnStateService};
pub use self::from_err::FromErr;
pub use self::map::{Map, MapNewService}; pub use self::map::{Map, MapNewService};
pub use self::map_err::{MapErr, MapErrNewService}; pub use self::map_err::{MapErr, MapErrNewService};
pub use self::map_init_err::MapInitErr; pub use self::map_init_err::MapInitErr;
@ -37,6 +39,14 @@ pub trait ServiceExt: Service {
AndThen::new(self, service.into_service()) AndThen::new(self, service.into_service())
} }
fn from_err<E>(self) -> FromErr<Self, E>
where
Self: Sized,
E: From<Self::Error>,
{
FromErr::new(self)
}
fn map<F, R>(self, f: F) -> Map<Self, F, R> fn map<F, R>(self, f: F) -> Map<Self, F, R>
where where
Self: Sized, Self: Sized,

View file

@ -92,38 +92,57 @@ impl<T: AsyncRead + AsyncWrite> Service for OpensslAcceptorService<T> {
} }
/// Openssl connector factory /// Openssl connector factory
pub struct OpensslConnector<T, Io> { pub struct OpensslConnector<T, Io, E> {
connector: SslConnector, connector: SslConnector,
t: PhantomData<T>, t: PhantomData<T>,
io: PhantomData<Io>, io: PhantomData<Io>,
_e: PhantomData<E>,
} }
impl<T, Io> OpensslConnector<T, Io> { impl<T, Io, E> OpensslConnector<T, Io, E> {
pub fn new(connector: SslConnector) -> Self { pub fn new(connector: SslConnector) -> Self {
OpensslConnector { OpensslConnector {
connector, connector,
t: PhantomData, t: PhantomData,
io: PhantomData, io: PhantomData,
_e: PhantomData,
} }
} }
} }
impl<T, Io> Clone for OpensslConnector<T, Io> { impl<T, Io: AsyncRead + AsyncWrite> OpensslConnector<T, Io, ()> {
fn clone(&self) -> Self { pub fn service(
Self { connector: SslConnector,
connector: self.connector.clone(), ) -> impl Service<
Request = (T, ConnectionInfo, Io),
Response = (T, ConnectionInfo, SslStream<Io>),
Error = Error,
> {
OpensslConnectorService {
connector: connector,
t: PhantomData, t: PhantomData,
io: PhantomData, io: PhantomData,
} }
} }
} }
impl<T, Io: AsyncRead + AsyncWrite> NewService for OpensslConnector<T, Io> { impl<T, Io, E> Clone for OpensslConnector<T, Io, E> {
fn clone(&self) -> Self {
Self {
connector: self.connector.clone(),
t: PhantomData,
io: PhantomData,
_e: PhantomData,
}
}
}
impl<T, Io: AsyncRead + AsyncWrite, E> NewService for OpensslConnector<T, Io, E> {
type Request = (T, ConnectionInfo, Io); type Request = (T, ConnectionInfo, Io);
type Response = (T, ConnectionInfo, SslStream<Io>); type Response = (T, ConnectionInfo, SslStream<Io>);
type Error = Error; type Error = Error;
type Service = OpensslConnectorService<T, Io>; type Service = OpensslConnectorService<T, Io>;
type InitError = io::Error; type InitError = E;
type Future = FutureResult<Self::Service, Self::InitError>; type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self) -> Self::Future { fn new_service(&self) -> Self::Future {