Skip to content

Commit 8b246a1

Browse files
authored
chore: remove tower dep by vendoring Oneshot (#151)
1 parent d3e9699 commit 8b246a1

File tree

6 files changed

+88
-16
lines changed

6 files changed

+88
-16
lines changed

Cargo.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ futures-channel = { version = "0.3", optional = true }
2828
socket2 = { version = "0.5", optional = true, features = ["all"] }
2929
tracing = { version = "0.1", default-features = false, features = ["std"], optional = true }
3030
tokio = { version = "1", optional = true, default-features = false }
31-
tower-service ={ version = "0.3", optional = true }
32-
tower = { version = "0.4.1", optional = true, default-features = false, features = ["make", "util"] }
31+
tower-service = { version = "0.3", optional = true }
3332

3433
[dev-dependencies]
3534
hyper = { version = "1.4.0", features = ["full"] }
@@ -58,14 +57,14 @@ full = [
5857
"tokio",
5958
]
6059

61-
client = ["hyper/client", "dep:tracing", "dep:futures-channel", "dep:tower", "dep:tower-service"]
60+
client = ["hyper/client", "dep:tracing", "dep:futures-channel", "dep:tower-service"]
6261
client-legacy = ["client", "dep:socket2", "tokio/sync"]
6362

6463
server = ["hyper/server"]
6564
server-auto = ["server", "http1", "http2"]
66-
server-graceful = ["server", "tokio/sync"]
65+
server-graceful = ["server", "tokio/sync", "futures-util/alloc"]
6766

68-
service = ["dep:tower", "dep:tower-service"]
67+
service = ["dep:tower-service"]
6968

7069
http1 = ["hyper/http1"]
7170
http2 = ["hyper/http2"]

src/client/legacy/connect/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
//! use std::{future::Future, net::SocketAddr, pin::Pin, task::{self, Poll}};
3030
//! use http::Uri;
3131
//! use tokio::net::TcpStream;
32-
//! use tower::Service;
32+
//! use tower_service::Service;
3333
//!
3434
//! #[derive(Clone)]
3535
//! struct LocalConnector;
@@ -57,7 +57,7 @@
5757
//! better starting place to extend from.
5858
//!
5959
//! [`HttpConnector`]: HttpConnector
60-
//! [`Service`]: tower::Service
60+
//! [`Service`]: tower_service::Service
6161
//! [`Uri`]: ::http::Uri
6262
//! [`Read`]: hyper::rt::Read
6363
//! [`Write`]: hyper::rt::Write
@@ -343,8 +343,8 @@ pub(super) mod sealed {
343343
{
344344
type _Svc = S;
345345

346-
fn connect(self, _: Internal, dst: Uri) -> tower::util::Oneshot<S, Uri> {
347-
tower::util::Oneshot::new(self, dst)
346+
fn connect(self, _: Internal, dst: Uri) -> crate::service::Oneshot<S, Uri> {
347+
crate::service::Oneshot::new(self, dst)
348348
}
349349
}
350350

@@ -357,10 +357,10 @@ pub(super) mod sealed {
357357
{
358358
type Connection = T;
359359
type Error = S::Error;
360-
type Future = tower::util::Oneshot<S, Uri>;
360+
type Future = crate::service::Oneshot<S, Uri>;
361361

362362
fn connect(self, _: Internal, dst: Uri) -> Self::Future {
363-
tower::util::Oneshot::new(self, dst)
363+
crate::service::Oneshot::new(self, dst)
364364
}
365365
}
366366

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod common;
1212
pub mod rt;
1313
#[cfg(feature = "server")]
1414
pub mod server;
15-
#[cfg(feature = "service")]
15+
#[cfg(any(feature = "service", feature = "client-legacy"))]
1616
pub mod service;
1717

1818
mod error;

src/service.rs renamed to src/service/glue.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
//! Service utilities.
2-
31
use pin_project_lite::pin_project;
42
use std::{
53
future::Future,
64
pin::Pin,
75
task::{Context, Poll},
86
};
9-
use tower::{util::Oneshot, ServiceExt};
7+
8+
use super::Oneshot;
109

1110
/// A tower service converted into a hyper service.
1211
#[derive(Debug, Copy, Clone)]
@@ -33,7 +32,7 @@ where
3332

3433
fn call(&self, req: R) -> Self::Future {
3534
TowerToHyperServiceFuture {
36-
future: self.service.clone().oneshot(req),
35+
future: Oneshot::new(self.service.clone(), req),
3736
}
3837
}
3938
}

src/service/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//! Service utilities.
2+
3+
#[cfg(feature = "service")]
4+
mod glue;
5+
#[cfg(any(feature = "client-legacy", feature = "service"))]
6+
mod oneshot;
7+
8+
#[cfg(feature = "service")]
9+
pub use self::glue::{TowerToHyperService, TowerToHyperServiceFuture};
10+
#[cfg(any(feature = "client-legacy", feature = "service"))]
11+
pub(crate) use self::oneshot::Oneshot;

src/service/oneshot.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use futures_util::ready;
2+
use pin_project_lite::pin_project;
3+
use std::future::Future;
4+
use std::pin::Pin;
5+
use std::task::{Context, Poll};
6+
use tower_service::Service;
7+
8+
// Vendored from tower::util to reduce dependencies, the code is small enough.
9+
10+
// Not really pub, but used in a trait for bounds
11+
pin_project! {
12+
#[project = OneshotProj]
13+
#[derive(Debug)]
14+
pub enum Oneshot<S: Service<Req>, Req> {
15+
NotReady {
16+
svc: S,
17+
req: Option<Req>,
18+
},
19+
Called {
20+
#[pin]
21+
fut: S::Future,
22+
},
23+
Done,
24+
}
25+
}
26+
27+
impl<S, Req> Oneshot<S, Req>
28+
where
29+
S: Service<Req>,
30+
{
31+
pub(crate) const fn new(svc: S, req: Req) -> Self {
32+
Oneshot::NotReady {
33+
svc,
34+
req: Some(req),
35+
}
36+
}
37+
}
38+
39+
impl<S, Req> Future for Oneshot<S, Req>
40+
where
41+
S: Service<Req>,
42+
{
43+
type Output = Result<S::Response, S::Error>;
44+
45+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
46+
loop {
47+
let this = self.as_mut().project();
48+
match this {
49+
OneshotProj::NotReady { svc, req } => {
50+
let _ = ready!(svc.poll_ready(cx))?;
51+
let fut = svc.call(req.take().expect("already called"));
52+
self.set(Oneshot::Called { fut });
53+
}
54+
OneshotProj::Called { fut } => {
55+
let res = ready!(fut.poll(cx))?;
56+
self.set(Oneshot::Done);
57+
return Poll::Ready(Ok(res));
58+
}
59+
OneshotProj::Done => panic!("polled after complete"),
60+
}
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)