From a522c3151abd11795d3263f6607a7caf7c19a585 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Fri, 30 Nov 2018 12:57:53 -0800 Subject: [PATCH] feat(service): export `hyper::service::MakeServiceRef` It's sealed, and has a blanket implementation, and so should only be used as bounds. Even still, its hidden from the docs. --- src/server/conn.rs | 37 +------------------ src/server/mod.rs | 4 +-- src/server/shutdown.rs | 4 +-- src/service/make_service.rs | 72 +++++++++++++++++++++++++++++++++++++ src/service/mod.rs | 3 +- 5 files changed, 79 insertions(+), 41 deletions(-) diff --git a/src/server/conn.rs b/src/server/conn.rs index c729183fe1..296221d17f 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -25,10 +25,9 @@ use common::exec::{Exec, H2Exec, NewSvcExec}; use common::io::Rewind; use error::{Kind, Parse}; use proto; -use service::Service; +use service::{MakeServiceRef, Service}; use upgrade::Upgraded; -pub(super) use self::make_service::MakeServiceRef; pub(super) use self::spawn_all::NoopWatcher; use self::spawn_all::NewSvcTask; pub(super) use self::spawn_all::Watcher; @@ -910,37 +909,3 @@ mod upgrades { } } -pub(crate) mod make_service { - use std::error::Error as StdError; - - pub trait MakeServiceRef { - type Error: Into>; - type ReqBody: ::body::Payload; - type ResBody: ::body::Payload; - type Service: ::service::Service; - type Future: ::futures::Future; - - fn make_service_ref(&mut self, ctx: &Ctx) -> Self::Future; - } - - impl MakeServiceRef for T - where - T: for<'a> ::service::MakeService<&'a Ctx, Error=E, MakeError=ME, Service=S, Future=F, ReqBody=IB, ResBody=OB>, - E: Into>, - ME: Into>, - S: ::service::Service, - F: ::futures::Future, - IB: ::body::Payload, - OB: ::body::Payload, - { - type Error = E; - type Service = S; - type ReqBody = IB; - type ResBody = OB; - type Future = F; - - fn make_service_ref(&mut self, ctx: &Ctx) -> Self::Future { - self.make_service(ctx) - } - } -} diff --git a/src/server/mod.rs b/src/server/mod.rs index 681656e947..01cf071349 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -65,10 +65,10 @@ use tokio_io::{AsyncRead, AsyncWrite}; use body::{Body, Payload}; use common::exec::{Exec, H2Exec, NewSvcExec}; -use service::Service; +use service::{MakeServiceRef, Service}; // Renamed `Http` as `Http_` for now so that people upgrading don't see an // error that `hyper::server::Http` is private... -use self::conn::{Http as Http_, MakeServiceRef, NoopWatcher, SpawnAll}; +use self::conn::{Http as Http_, NoopWatcher, SpawnAll}; use self::shutdown::{Graceful, GracefulWatcher}; #[cfg(feature = "runtime")] use self::tcp::AddrIncoming; diff --git a/src/server/shutdown.rs b/src/server/shutdown.rs index 167b3def96..4d464e6131 100644 --- a/src/server/shutdown.rs +++ b/src/server/shutdown.rs @@ -4,8 +4,8 @@ use tokio_io::{AsyncRead, AsyncWrite}; use body::{Body, Payload}; use common::drain::{self, Draining, Signal, Watch, Watching}; use common::exec::{H2Exec, NewSvcExec}; -use service::Service; -use super::conn::{MakeServiceRef, SpawnAll, UpgradeableConnection, Watcher}; +use service::{MakeServiceRef, Service}; +use super::conn::{SpawnAll, UpgradeableConnection, Watcher}; #[allow(missing_debug_implementations)] pub struct Graceful { diff --git a/src/service/make_service.rs b/src/service/make_service.rs index e2cdad3a2a..f694e30cc5 100644 --- a/src/service/make_service.rs +++ b/src/service/make_service.rs @@ -34,6 +34,68 @@ pub trait MakeService { fn make_service(&mut self, ctx: Ctx) -> Self::Future; } +// Just a sort-of "trait alias" of `MakeService`, not to be implemented +// by anyone, only used as bounds. +#[doc(hidden)] +pub trait MakeServiceRef: self::sealed::Sealed { + type ReqBody: Payload; + type ResBody: Payload; + type Error: Into>; + type Service: Service< + ReqBody=Self::ReqBody, + ResBody=Self::ResBody, + Error=Self::Error, + >; + type Future: Future; + + // Acting like a #[non_exhaustive] for associated types of this trait. + // + // Basically, no one outside of hyper should be able to set this type + // or declare bounds on it, so it should prevent people from creating + // trait objects or otherwise writing code that requires using *all* + // of the associated types. + // + // Why? So we can add new associated types to this alias in the future, + // if necessary. + type __DontNameMe: self::sealed::CantImpl; + + fn make_service_ref(&mut self, ctx: &Ctx) -> Self::Future; +} + +impl MakeServiceRef for T +where + T: for<'a> MakeService<&'a Ctx, Error=E, MakeError=ME, Service=S, Future=F, ReqBody=IB, ResBody=OB>, + E: Into>, + ME: Into>, + S: Service, + F: Future, + IB: Payload, + OB: Payload, +{ + type Error = E; + type Service = S; + type ReqBody = IB; + type ResBody = OB; + type Future = F; + + type __DontNameMe = self::sealed::CantName; + + fn make_service_ref(&mut self, ctx: &Ctx) -> Self::Future { + self.make_service(ctx) + } +} + +impl self::sealed::Sealed for T +where + T: for<'a> MakeService<&'a Ctx, Error=E, MakeError=ME, Service=S, Future=F, ReqBody=IB, ResBody=OB>, + E: Into>, + ME: Into>, + S: Service, + F: Future, + IB: Payload, + OB: Payload, +{} + /// Create a `MakeService` from a function. /// @@ -94,3 +156,13 @@ impl fmt::Debug for MakeServiceFn { } } +mod sealed { + pub trait Sealed {} + + pub trait CantImpl {} + + #[allow(missing_debug_implementations)] + pub enum CantName {} + + impl CantImpl for CantName {} +} diff --git a/src/service/mod.rs b/src/service/mod.rs index 95b2fba510..54faca8d65 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -33,7 +33,8 @@ mod make_service; mod new_service; mod service; -pub use self::make_service::{make_service_fn, MakeService}; +pub use self::make_service::{make_service_fn, MakeService, MakeServiceRef}; +// NewService is soft-deprecated. #[doc(hidden)] pub use self::new_service::NewService; pub use self::service::{service_fn, service_fn_ok, Service};