mirror of
https://github.com/Noratrieb/101844-repro.git
synced 2026-01-17 07:25:02 +01:00
smol
This commit is contained in:
parent
b1cba78afa
commit
f5f20836d4
4 changed files with 90 additions and 308 deletions
90
tower/tower/src/make.rs
Normal file
90
tower/tower/src/make.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
//! Trait aliases for Services that produce specific types of Responses.
|
||||||
|
|
||||||
|
pub use self::make_service::shared::Shared;
|
||||||
|
pub use self::make_service::MakeService;
|
||||||
|
|
||||||
|
pub mod future {
|
||||||
|
//! Future types
|
||||||
|
|
||||||
|
pub use super::make_service::shared::SharedFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod make_service {
|
||||||
|
//! 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 mod shared {
|
||||||
|
use std::convert::Infallible;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
use tower_service::Service;
|
||||||
|
|
||||||
|
pub struct Shared<S> {
|
||||||
|
service: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
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>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, _target: T) -> Self::Future {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opaque_future! {
|
||||||
|
/// Response future from [`Shared`] services.
|
||||||
|
pub type SharedFuture<S> = futures_util::future::Ready<Result<S, Infallible>>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MakeService<Target, Request> {
|
||||||
|
type Response;
|
||||||
|
type Error;
|
||||||
|
type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
|
||||||
|
type MakeError;
|
||||||
|
type Future;
|
||||||
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>;
|
||||||
|
fn make_service(&mut self, target: Target) -> Self::Future;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
//! 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> {
|
|
||||||
type Response;
|
|
||||||
type Error;
|
|
||||||
type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
|
|
||||||
type MakeError;
|
|
||||||
type Future;
|
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>;
|
|
||||||
fn make_service(&mut self, target: Target) -> Self::Future;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,146 +0,0 @@
|
||||||
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 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
//! Trait aliases for Services that produce specific types of Responses.
|
|
||||||
|
|
||||||
mod make_service;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue