Skip to content

Commit

Permalink
chore: remove tower dep by vendoring Oneshot (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmonstar authored Sep 24, 2024
1 parent d3e9699 commit 8b246a1
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 16 deletions.
9 changes: 4 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ futures-channel = { version = "0.3", optional = true }
socket2 = { version = "0.5", optional = true, features = ["all"] }
tracing = { version = "0.1", default-features = false, features = ["std"], optional = true }
tokio = { version = "1", optional = true, default-features = false }
tower-service ={ version = "0.3", optional = true }
tower = { version = "0.4.1", optional = true, default-features = false, features = ["make", "util"] }
tower-service = { version = "0.3", optional = true }

[dev-dependencies]
hyper = { version = "1.4.0", features = ["full"] }
Expand Down Expand Up @@ -58,14 +57,14 @@ full = [
"tokio",
]

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

server = ["hyper/server"]
server-auto = ["server", "http1", "http2"]
server-graceful = ["server", "tokio/sync"]
server-graceful = ["server", "tokio/sync", "futures-util/alloc"]

service = ["dep:tower", "dep:tower-service"]
service = ["dep:tower-service"]

http1 = ["hyper/http1"]
http2 = ["hyper/http2"]
Expand Down
12 changes: 6 additions & 6 deletions src/client/legacy/connect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
//! use std::{future::Future, net::SocketAddr, pin::Pin, task::{self, Poll}};
//! use http::Uri;
//! use tokio::net::TcpStream;
//! use tower::Service;
//! use tower_service::Service;
//!
//! #[derive(Clone)]
//! struct LocalConnector;
Expand Down Expand Up @@ -57,7 +57,7 @@
//! better starting place to extend from.
//!
//! [`HttpConnector`]: HttpConnector
//! [`Service`]: tower::Service
//! [`Service`]: tower_service::Service
//! [`Uri`]: ::http::Uri
//! [`Read`]: hyper::rt::Read
//! [`Write`]: hyper::rt::Write
Expand Down Expand Up @@ -343,8 +343,8 @@ pub(super) mod sealed {
{
type _Svc = S;

fn connect(self, _: Internal, dst: Uri) -> tower::util::Oneshot<S, Uri> {
tower::util::Oneshot::new(self, dst)
fn connect(self, _: Internal, dst: Uri) -> crate::service::Oneshot<S, Uri> {
crate::service::Oneshot::new(self, dst)
}
}

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

fn connect(self, _: Internal, dst: Uri) -> Self::Future {
tower::util::Oneshot::new(self, dst)
crate::service::Oneshot::new(self, dst)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod common;
pub mod rt;
#[cfg(feature = "server")]
pub mod server;
#[cfg(feature = "service")]
#[cfg(any(feature = "service", feature = "client-legacy"))]
pub mod service;

mod error;
7 changes: 3 additions & 4 deletions src/service.rs → src/service/glue.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
//! Service utilities.
use pin_project_lite::pin_project;
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use tower::{util::Oneshot, ServiceExt};

use super::Oneshot;

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

fn call(&self, req: R) -> Self::Future {
TowerToHyperServiceFuture {
future: self.service.clone().oneshot(req),
future: Oneshot::new(self.service.clone(), req),
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/service/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Service utilities.
#[cfg(feature = "service")]
mod glue;
#[cfg(any(feature = "client-legacy", feature = "service"))]
mod oneshot;

#[cfg(feature = "service")]
pub use self::glue::{TowerToHyperService, TowerToHyperServiceFuture};
#[cfg(any(feature = "client-legacy", feature = "service"))]
pub(crate) use self::oneshot::Oneshot;
63 changes: 63 additions & 0 deletions src/service/oneshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use futures_util::ready;
use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use tower_service::Service;

// Vendored from tower::util to reduce dependencies, the code is small enough.

// Not really pub, but used in a trait for bounds
pin_project! {
#[project = OneshotProj]
#[derive(Debug)]
pub enum Oneshot<S: Service<Req>, Req> {
NotReady {
svc: S,
req: Option<Req>,
},
Called {
#[pin]
fut: S::Future,
},
Done,
}
}

impl<S, Req> Oneshot<S, Req>
where
S: Service<Req>,
{
pub(crate) const fn new(svc: S, req: Req) -> Self {
Oneshot::NotReady {
svc,
req: Some(req),
}
}
}

impl<S, Req> Future for Oneshot<S, Req>
where
S: Service<Req>,
{
type Output = Result<S::Response, S::Error>;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop {
let this = self.as_mut().project();
match this {
OneshotProj::NotReady { svc, req } => {
let _ = ready!(svc.poll_ready(cx))?;
let fut = svc.call(req.take().expect("already called"));
self.set(Oneshot::Called { fut });
}
OneshotProj::Called { fut } => {
let res = ready!(fut.poll(cx))?;
self.set(Oneshot::Done);
return Poll::Ready(Ok(res));
}
OneshotProj::Done => panic!("polled after complete"),
}
}
}
}

0 comments on commit 8b246a1

Please sign in to comment.