diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/tower/src/make | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/tower/src/make')
| -rw-r--r-- | vendor/tower/src/make/make_connection.rs | 47 | ||||
| -rw-r--r-- | vendor/tower/src/make/make_service.rs | 251 | ||||
| -rw-r--r-- | vendor/tower/src/make/make_service/shared.rs | 146 | ||||
| -rw-r--r-- | vendor/tower/src/make/mod.rs | 14 |
4 files changed, 458 insertions, 0 deletions
diff --git a/vendor/tower/src/make/make_connection.rs b/vendor/tower/src/make/make_connection.rs new file mode 100644 index 00000000..9566cc68 --- /dev/null +++ b/vendor/tower/src/make/make_connection.rs @@ -0,0 +1,47 @@ +use crate::sealed::Sealed; +use std::future::Future; +use std::task::{Context, Poll}; +use tokio::io::{AsyncRead, AsyncWrite}; +use tower_service::Service; + +/// The [`MakeConnection`] trait is used to create transports. +/// +/// The goal of this service is to allow composable methods for creating +/// `AsyncRead + AsyncWrite` transports. This could mean creating a TLS +/// based connection or using some other method to authenticate the connection. +pub trait MakeConnection<Target>: Sealed<(Target,)> { + /// The transport provided by this service + type Connection: AsyncRead + AsyncWrite; + + /// Errors produced by the connecting service + type Error; + + /// The future that eventually produces the transport + type Future: Future<Output = Result<Self::Connection, Self::Error>>; + + /// Returns `Poll::Ready(Ok(()))` when it is able to make more connections. + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>; + + /// Connect and return a transport asynchronously + fn make_connection(&mut self, target: Target) -> Self::Future; +} + +impl<S, Target> Sealed<(Target,)> for S where S: Service<Target> {} + +impl<C, Target> MakeConnection<Target> for C +where + C: Service<Target>, + C::Response: AsyncRead + AsyncWrite, +{ + type Connection = C::Response; + type Error = C::Error; + type Future = C::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + Service::poll_ready(self, cx) + } + + fn make_connection(&mut self, target: Target) -> Self::Future { + Service::call(self, target) + } +} diff --git a/vendor/tower/src/make/make_service.rs b/vendor/tower/src/make/make_service.rs new file mode 100644 index 00000000..aa519d68 --- /dev/null +++ b/vendor/tower/src/make/make_service.rs @@ -0,0 +1,251 @@ +//! Contains [`MakeService`] which is a trait alias for a [`Service`] of [`Service`]s. + +use crate::sealed::Sealed; +use std::fmt; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use tower_service::Service; + +pub(crate) mod shared; + +/// Creates new [`Service`] values. +/// +/// Acts as a service factory. This is useful for cases where new [`Service`] +/// values must be produced. One case is a TCP server listener. The listener +/// accepts new TCP streams, obtains a new [`Service`] value using the +/// [`MakeService`] trait, and uses that new [`Service`] value to process inbound +/// requests on that new TCP stream. +/// +/// This is essentially a trait alias for a [`Service`] of [`Service`]s. +pub trait MakeService<Target, Request>: Sealed<(Target, Request)> { + /// Responses given by the service + type Response; + + /// Errors produced by the service + type Error; + + /// The [`Service`] value created by this factory + type Service: Service<Request, Response = Self::Response, Error = Self::Error>; + + /// Errors produced while building a service. + type MakeError; + + /// The future of the [`Service`] instance. + type Future: Future<Output = Result<Self::Service, Self::MakeError>>; + + /// Returns [`Poll::Ready`] when the factory is able to create more services. + /// + /// If the service is at capacity, then [`Poll::Pending`] is returned and the task + /// is notified when the service becomes ready again. This function is + /// expected to be called while on a task. + /// + /// [`Poll::Ready`]: std::task::Poll::Ready + /// [`Poll::Pending`]: std::task::Poll::Pending + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>; + + /// Create and return a new service value asynchronously. + fn make_service(&mut self, target: Target) -> Self::Future; + + /// Consume this [`MakeService`] and convert it into a [`Service`]. + /// + /// # Example + /// ``` + /// use std::convert::Infallible; + /// use tower::Service; + /// use tower::make::MakeService; + /// use tower::service_fn; + /// + /// # fn main() { + /// # async { + /// // A `MakeService` + /// let make_service = service_fn(|make_req: ()| async { + /// Ok::<_, Infallible>(service_fn(|req: String| async { + /// Ok::<_, Infallible>(req) + /// })) + /// }); + /// + /// // Convert the `MakeService` into a `Service` + /// let mut svc = make_service.into_service(); + /// + /// // Make a new service + /// let mut new_svc = svc.call(()).await.unwrap(); + /// + /// // Call the service + /// let res = new_svc.call("foo".to_string()).await.unwrap(); + /// # }; + /// # } + /// ``` + fn into_service(self) -> IntoService<Self, Request> + where + Self: Sized, + { + IntoService { + make: self, + _marker: PhantomData, + } + } + + /// Convert this [`MakeService`] into a [`Service`] without consuming the original [`MakeService`]. + /// + /// # Example + /// ``` + /// use std::convert::Infallible; + /// use tower::Service; + /// use tower::make::MakeService; + /// use tower::service_fn; + /// + /// # fn main() { + /// # async { + /// // A `MakeService` + /// let mut make_service = service_fn(|make_req: ()| async { + /// Ok::<_, Infallible>(service_fn(|req: String| async { + /// Ok::<_, Infallible>(req) + /// })) + /// }); + /// + /// // Convert the `MakeService` into a `Service` + /// let mut svc = make_service.as_service(); + /// + /// // Make a new service + /// let mut new_svc = svc.call(()).await.unwrap(); + /// + /// // Call the service + /// let res = new_svc.call("foo".to_string()).await.unwrap(); + /// + /// // The original `MakeService` is still accessible + /// let new_svc = make_service.make_service(()).await.unwrap(); + /// # }; + /// # } + /// ``` + fn as_service(&mut self) -> AsService<Self, Request> + where + Self: Sized, + { + AsService { + make: self, + _marker: PhantomData, + } + } +} + +impl<M, S, Target, Request> Sealed<(Target, Request)> for M +where + M: Service<Target, Response = S>, + S: Service<Request>, +{ +} + +impl<M, S, Target, Request> MakeService<Target, Request> for M +where + M: Service<Target, Response = S>, + S: Service<Request>, +{ + type Response = S::Response; + type Error = S::Error; + type Service = S; + type MakeError = M::Error; + type Future = M::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>> { + Service::poll_ready(self, cx) + } + + fn make_service(&mut self, target: Target) -> Self::Future { + Service::call(self, target) + } +} + +/// Service returned by [`MakeService::into_service`][into]. +/// +/// See the documentation on [`into_service`][into] for details. +/// +/// [into]: MakeService::into_service +pub struct IntoService<M, Request> { + make: M, + _marker: PhantomData<Request>, +} + +impl<M, Request> Clone for IntoService<M, Request> +where + M: Clone, +{ + fn clone(&self) -> Self { + Self { + make: self.make.clone(), + _marker: PhantomData, + } + } +} + +impl<M, Request> fmt::Debug for IntoService<M, Request> +where + M: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("IntoService") + .field("make", &self.make) + .finish() + } +} + +impl<M, S, Target, Request> Service<Target> for IntoService<M, Request> +where + M: Service<Target, Response = S>, + S: Service<Request>, +{ + type Response = M::Response; + type Error = M::Error; + type Future = M::Future; + + #[inline] + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + self.make.poll_ready(cx) + } + + #[inline] + fn call(&mut self, target: Target) -> Self::Future { + self.make.make_service(target) + } +} + +/// Service returned by [`MakeService::as_service`][as]. +/// +/// See the documentation on [`as_service`][as] for details. +/// +/// [as]: MakeService::as_service +pub struct AsService<'a, M, Request> { + make: &'a mut M, + _marker: PhantomData<Request>, +} + +impl<M, Request> fmt::Debug for AsService<'_, M, Request> +where + M: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsService") + .field("make", &self.make) + .finish() + } +} + +impl<M, S, Target, Request> Service<Target> for AsService<'_, M, Request> +where + M: Service<Target, Response = S>, + S: Service<Request>, +{ + type Response = M::Response; + type Error = M::Error; + type Future = M::Future; + + #[inline] + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + self.make.poll_ready(cx) + } + + #[inline] + fn call(&mut self, target: Target) -> Self::Future { + self.make.make_service(target) + } +} diff --git a/vendor/tower/src/make/make_service/shared.rs b/vendor/tower/src/make/make_service/shared.rs new file mode 100644 index 00000000..2b2bc026 --- /dev/null +++ b/vendor/tower/src/make/make_service/shared.rs @@ -0,0 +1,146 @@ +use std::convert::Infallible; +use std::task::{Context, Poll}; +use tower_service::Service; + +/// A [`MakeService`] that produces services by cloning an inner service. +/// +/// [`MakeService`]: super::MakeService +/// +/// # Example +/// +/// ``` +/// # use std::task::{Context, Poll}; +/// # use std::pin::Pin; +/// # use std::convert::Infallible; +/// use tower::make::{MakeService, Shared}; +/// use tower::buffer::Buffer; +/// use tower::Service; +/// use futures::future::{Ready, ready}; +/// +/// // An example connection type +/// struct Connection {} +/// +/// // An example request type +/// struct Request {} +/// +/// // An example response type +/// struct Response {} +/// +/// // Some service that doesn't implement `Clone` +/// struct MyService; +/// +/// impl Service<Request> for MyService { +/// type Response = Response; +/// type Error = Infallible; +/// type Future = Ready<Result<Response, Infallible>>; +/// +/// fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { +/// Poll::Ready(Ok(())) +/// } +/// +/// fn call(&mut self, req: Request) -> Self::Future { +/// ready(Ok(Response {})) +/// } +/// } +/// +/// // Example function that runs a service by accepting new connections and using +/// // `Make` to create new services that might be bound to the connection. +/// // +/// // This is similar to what you might find in hyper. +/// async fn serve_make_service<Make>(make: Make) +/// where +/// Make: MakeService<Connection, Request> +/// { +/// // ... +/// } +/// +/// # async { +/// // Our service +/// let svc = MyService; +/// +/// // Make it `Clone` by putting a channel in front +/// let buffered = Buffer::new(svc, 1024); +/// +/// // Convert it into a `MakeService` +/// let make = Shared::new(buffered); +/// +/// // Run the service and just ignore the `Connection`s as `MyService` doesn't need them +/// serve_make_service(make).await; +/// # }; +/// ``` +#[derive(Debug, Clone, Copy)] +pub struct Shared<S> { + service: S, +} + +impl<S> Shared<S> { + /// Create a new [`Shared`] from a service. + pub const fn new(service: S) -> Self { + Self { service } + } +} + +impl<S, T> Service<T> for Shared<S> +where + S: Clone, +{ + type Response = S; + type Error = Infallible; + type Future = SharedFuture<S>; + + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, _target: T) -> Self::Future { + SharedFuture::new(futures_util::future::ready(Ok(self.service.clone()))) + } +} + +opaque_future! { + /// Response future from [`Shared`] services. + pub type SharedFuture<S> = futures_util::future::Ready<Result<S, Infallible>>; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::make::MakeService; + use crate::service_fn; + use futures::future::poll_fn; + + async fn echo<R>(req: R) -> Result<R, Infallible> { + Ok(req) + } + + #[tokio::test] + async fn as_make_service() { + let mut shared = Shared::new(service_fn(echo::<&'static str>)); + + poll_fn(|cx| MakeService::<(), _>::poll_ready(&mut shared, cx)) + .await + .unwrap(); + let mut svc = shared.make_service(()).await.unwrap(); + + poll_fn(|cx| svc.poll_ready(cx)).await.unwrap(); + let res = svc.call("foo").await.unwrap(); + + assert_eq!(res, "foo"); + } + + #[tokio::test] + async fn as_make_service_into_service() { + let shared = Shared::new(service_fn(echo::<&'static str>)); + let mut shared = MakeService::<(), _>::into_service(shared); + + poll_fn(|cx| Service::<()>::poll_ready(&mut shared, cx)) + .await + .unwrap(); + let mut svc = shared.call(()).await.unwrap(); + + poll_fn(|cx| svc.poll_ready(cx)).await.unwrap(); + let res = svc.call("foo").await.unwrap(); + + assert_eq!(res, "foo"); + } +} diff --git a/vendor/tower/src/make/mod.rs b/vendor/tower/src/make/mod.rs new file mode 100644 index 00000000..a377f2a2 --- /dev/null +++ b/vendor/tower/src/make/mod.rs @@ -0,0 +1,14 @@ +//! Trait aliases for Services that produce specific types of Responses. + +mod make_connection; +mod make_service; + +pub use self::make_connection::MakeConnection; +pub use self::make_service::shared::Shared; +pub use self::make_service::{AsService, IntoService, MakeService}; + +pub mod future { + //! Future types + + pub use super::make_service::shared::SharedFuture; +} |
