From 9456065d7bc33ed283b056e67f221d503fddb779 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 4 Sep 2018 12:07:13 -0700 Subject: [PATCH] better error conversion impl for and_then --- src/configurable.rs | 34 +++++++++++++++-------- src/service/and_then.rs | 54 +++++++++++++++--------------------- src/service/from_err.rs | 61 +++++++++++++++++++++++++++++++++++++++++ src/service/mod.rs | 10 +++++++ src/ssl/openssl.rs | 35 +++++++++++++++++------ 5 files changed, 143 insertions(+), 51 deletions(-) create mode 100644 src/service/from_err.rs diff --git a/src/configurable.rs b/src/configurable.rs index 66eb58492..614a491d0 100644 --- a/src/configurable.rs +++ b/src/configurable.rs @@ -259,14 +259,18 @@ where impl NewConfigurableService for AndThenNewConfigurableService where - A: NewConfigurableService, - A::Error: Into, - B: NewConfigurableService, + A: NewConfigurableService, + B: NewConfigurableService< + C, + Request = A::Response, + Error = A::Error, + InitError = A::InitError, + >, C: Clone, { type Request = A::Request; type Response = B::Response; - type Error = B::Error; + type Error = A::Error; type Service = AndThen; type InitError = A::InitError; @@ -282,9 +286,13 @@ where impl Clone for AndThenNewConfigurableService where - A: NewConfigurableService + Clone, - A::Error: Into, - B: NewConfigurableService + Clone, + A: NewConfigurableService + Clone, + B: NewConfigurableService< + C, + Request = A::Response, + Error = A::Error, + InitError = A::InitError, + > + Clone, { fn clone(&self) -> Self { Self { @@ -326,18 +334,22 @@ where impl Future for AndThenNewConfigurableServiceFuture where A: NewConfigurableService, - A::Error: Into, - B: NewConfigurableService, + B: NewConfigurableService< + C, + Request = A::Response, + Error = A::Error, + InitError = A::InitError, + >, { type Item = AndThen; - type Error = B::InitError; + type Error = A::InitError; fn poll(&mut self) -> Poll { if let Async::Ready(service) = self.fut_a.poll()? { 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); } diff --git a/src/service/and_then.rs b/src/service/and_then.rs index 2d248667f..5b0a65f38 100644 --- a/src/service/and_then.rs +++ b/src/service/and_then.rs @@ -15,8 +15,7 @@ pub struct AndThen { impl AndThen where A: Service, - A::Error: Into, - B: Service, + B: Service, { /// Create new `AndThen` combinator pub fn new(a: A, b: B) -> Self { @@ -30,19 +29,18 @@ where impl Service for AndThen where A: Service, - A::Error: Into, - B: Service, + B: Service, { type Request = A::Request; type Response = B::Response; - type Error = B::Error; + type Error = A::Error; type Future = AndThenFuture; fn poll_ready(&mut self) -> Poll<(), Self::Error> { 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), - Err(err) => Err(err.into()), + Err(err) => Err(err), } } @@ -54,8 +52,7 @@ where pub struct AndThenFuture where A: Service, - A::Error: Into, - B: Service, + B: Service, { b: Rc>, fut_b: Option, @@ -65,8 +62,7 @@ where impl AndThenFuture where A: Service, - A::Error: Into, - B: Service, + B: Service, { fn new(fut_a: A::Future, b: Rc>) -> Self { AndThenFuture { @@ -80,15 +76,15 @@ where impl Future for AndThenFuture where A: Service, - A::Error: Into, - B: Service, + B: Service, + B::Error: Into, { type Item = B::Response; - type Error = B::Error; + type Error = A::Error; fn poll(&mut self) -> Poll { 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() { @@ -97,7 +93,7 @@ where self.poll() } Ok(Async::NotReady) => Ok(Async::NotReady), - Err(err) => Err(err.into()), + Err(err) => Err(err), } } } @@ -124,17 +120,15 @@ where impl NewService for AndThenNewService where - A: NewService, - A::Error: Into, - A::InitError: Into, - B: NewService, + A: NewService, + B: NewService, { type Request = A::Request; type Response = B::Response; - type Error = B::Error; + type Error = A::Error; type Service = AndThen; - type InitError = B::InitError; + type InitError = A::InitError; type Future = AndThenNewServiceFuture; fn new_service(&self) -> Self::Future { @@ -144,10 +138,8 @@ where impl Clone for AndThenNewService where - A: NewService + Clone, - A::Error: Into, - A::InitError: Into, - B: NewService + Clone, + A: NewService + Clone, + B: NewService + Clone, { fn clone(&self) -> Self { Self { @@ -186,22 +178,20 @@ where impl Future for AndThenNewServiceFuture where A: NewService, - A::Error: Into, - A::InitError: Into, - B: NewService, + B: NewService, { type Item = AndThen; - type Error = B::InitError; + type Error = A::InitError; fn poll(&mut self) -> Poll { 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); } } 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); } } diff --git a/src/service/from_err.rs b/src/service/from_err.rs new file mode 100644 index 000000000..613d6041b --- /dev/null +++ b/src/service/from_err.rs @@ -0,0 +1,61 @@ +use std::marker::PhantomData; + +use futures::{Future, Poll}; +use tower_service::Service; + +pub struct FromErr +where + A: Service, +{ + service: A, + f: PhantomData, +} + +impl> FromErr { + pub(crate) fn new(service: A) -> Self { + FromErr { + service, + f: PhantomData, + } + } +} + +impl Service for FromErr +where + A: Service, + E: From, +{ + type Request = A::Request; + type Response = A::Response; + type Error = E; + type Future = FromErrFuture; + + 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 { + fut: A::Future, + f: PhantomData, +} + +impl Future for FromErrFuture +where + A: Service, + E: From, +{ + type Item = A::Response; + type Error = E; + + fn poll(&mut self) -> Poll { + self.fut.poll().map_err(E::from) + } +} diff --git a/src/service/mod.rs b/src/service/mod.rs index 250accf34..31d1aec4a 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -4,6 +4,7 @@ mod and_then; mod apply; mod fn_service; mod fn_state_service; +mod from_err; mod map; mod map_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::fn_service::{FnNewService, FnService}; pub use self::fn_state_service::{FnStateNewService, FnStateService}; +pub use self::from_err::FromErr; pub use self::map::{Map, MapNewService}; pub use self::map_err::{MapErr, MapErrNewService}; pub use self::map_init_err::MapInitErr; @@ -37,6 +39,14 @@ pub trait ServiceExt: Service { AndThen::new(self, service.into_service()) } + fn from_err(self) -> FromErr + where + Self: Sized, + E: From, + { + FromErr::new(self) + } + fn map(self, f: F) -> Map where Self: Sized, diff --git a/src/ssl/openssl.rs b/src/ssl/openssl.rs index 052cbf4bd..ac25de66a 100644 --- a/src/ssl/openssl.rs +++ b/src/ssl/openssl.rs @@ -92,38 +92,57 @@ impl Service for OpensslAcceptorService { } /// Openssl connector factory -pub struct OpensslConnector { +pub struct OpensslConnector { connector: SslConnector, t: PhantomData, io: PhantomData, + _e: PhantomData, } -impl OpensslConnector { +impl OpensslConnector { pub fn new(connector: SslConnector) -> Self { OpensslConnector { connector, t: PhantomData, io: PhantomData, + _e: PhantomData, } } } -impl Clone for OpensslConnector { - fn clone(&self) -> Self { - Self { - connector: self.connector.clone(), +impl OpensslConnector { + pub fn service( + connector: SslConnector, + ) -> impl Service< + Request = (T, ConnectionInfo, Io), + Response = (T, ConnectionInfo, SslStream), + Error = Error, + > { + OpensslConnectorService { + connector: connector, t: PhantomData, io: PhantomData, } } } -impl NewService for OpensslConnector { +impl Clone for OpensslConnector { + fn clone(&self) -> Self { + Self { + connector: self.connector.clone(), + t: PhantomData, + io: PhantomData, + _e: PhantomData, + } + } +} + +impl NewService for OpensslConnector { type Request = (T, ConnectionInfo, Io); type Response = (T, ConnectionInfo, SslStream); type Error = Error; type Service = OpensslConnectorService; - type InitError = io::Error; + type InitError = E; type Future = FutureResult; fn new_service(&self) -> Self::Future {