2019-11-14 13:38:24 +01:00
|
|
|
use std::task::{Context, Poll};
|
|
|
|
|
2019-11-18 09:30:04 +01:00
|
|
|
use crate::and_then::{AndThenService, AndThenServiceFactory};
|
|
|
|
use crate::then::{ThenService, ThenServiceFactory};
|
2019-11-14 13:38:24 +01:00
|
|
|
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
|
|
|
|
|
|
|
|
pub fn pipeline<F, T>(service: F) -> Pipeline<T>
|
|
|
|
where
|
|
|
|
F: IntoService<T>,
|
|
|
|
T: Service,
|
|
|
|
{
|
|
|
|
Pipeline {
|
|
|
|
service: service.into_service(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pipeline_factory<T, F>(factory: F) -> PipelineFactory<T>
|
|
|
|
where
|
|
|
|
T: ServiceFactory,
|
|
|
|
F: IntoServiceFactory<T>,
|
|
|
|
{
|
|
|
|
PipelineFactory {
|
|
|
|
factory: factory.into_factory(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Pipeline service
|
|
|
|
pub struct Pipeline<T> {
|
|
|
|
service: T,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Service> Pipeline<T> {
|
|
|
|
/// Call another service after call to this one has resolved successfully.
|
|
|
|
///
|
|
|
|
/// This function can be used to chain two services together and ensure that
|
|
|
|
/// the second service isn't called until call to the fist service have
|
|
|
|
/// finished. Result of the call to the first service is used as an
|
|
|
|
/// input parameter for the second service's call.
|
|
|
|
///
|
|
|
|
/// Note that this function consumes the receiving service and returns a
|
|
|
|
/// wrapped version of it.
|
2019-11-18 09:30:04 +01:00
|
|
|
pub fn and_then<F, U>(self, service: F) -> Pipeline<AndThenService<T, U>>
|
2019-11-14 13:38:24 +01:00
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
F: IntoService<U>,
|
2019-11-18 13:28:54 +01:00
|
|
|
U: Service<Request = T::Response, Error = T::Error>,
|
2019-11-14 13:38:24 +01:00
|
|
|
{
|
|
|
|
Pipeline {
|
2019-11-18 09:30:04 +01:00
|
|
|
service: AndThenService::new(self.service, service.into_service()),
|
2019-11-14 13:38:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Chain on a computation for when a call to the service finished,
|
|
|
|
/// passing the result of the call to the next service `U`.
|
|
|
|
///
|
|
|
|
/// Note that this function consumes the receiving pipeline and returns a
|
|
|
|
/// wrapped version of it.
|
2019-11-18 09:30:04 +01:00
|
|
|
pub fn then<F, U>(self, service: F) -> Pipeline<ThenService<T, U>>
|
2019-11-14 13:38:24 +01:00
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
F: IntoService<U>,
|
|
|
|
U: Service<Request = Result<T::Response, T::Error>, Error = T::Error>,
|
|
|
|
{
|
|
|
|
Pipeline {
|
2019-11-18 09:30:04 +01:00
|
|
|
service: ThenService::new(self.service, service.into_service()),
|
2019-11-14 13:38:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Clone for Pipeline<T>
|
|
|
|
where
|
|
|
|
T: Clone,
|
|
|
|
{
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Pipeline {
|
|
|
|
service: self.service.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Service> Service for Pipeline<T> {
|
|
|
|
type Request = T::Request;
|
|
|
|
type Response = T::Response;
|
|
|
|
type Error = T::Error;
|
|
|
|
type Future = T::Future;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), T::Error>> {
|
|
|
|
self.service.poll_ready(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn call(&mut self, req: T::Request) -> Self::Future {
|
|
|
|
self.service.call(req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Pipeline constructor
|
|
|
|
pub struct PipelineFactory<T> {
|
|
|
|
factory: T,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ServiceFactory> PipelineFactory<T> {
|
|
|
|
/// Call another service after call to this one has resolved successfully.
|
2019-11-18 09:30:04 +01:00
|
|
|
pub fn and_then<F, U>(self, factory: F) -> PipelineFactory<AndThenServiceFactory<T, U>>
|
2019-11-14 13:38:24 +01:00
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
F: IntoServiceFactory<U>,
|
|
|
|
U: ServiceFactory<
|
|
|
|
Config = T::Config,
|
|
|
|
Request = T::Response,
|
|
|
|
Error = T::Error,
|
|
|
|
InitError = T::InitError,
|
|
|
|
>,
|
|
|
|
{
|
|
|
|
PipelineFactory {
|
2019-11-18 09:30:04 +01:00
|
|
|
factory: AndThenServiceFactory::new(self.factory, factory.into_factory()),
|
2019-11-14 13:38:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create `NewService` to chain on a computation for when a call to the
|
|
|
|
/// service finished, passing the result of the call to the next
|
|
|
|
/// service `U`.
|
|
|
|
///
|
|
|
|
/// Note that this function consumes the receiving pipeline and returns a
|
|
|
|
/// wrapped version of it.
|
2019-11-18 09:30:04 +01:00
|
|
|
pub fn then<F, U>(self, factory: F) -> PipelineFactory<ThenServiceFactory<T, U>>
|
2019-11-14 13:38:24 +01:00
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
F: IntoServiceFactory<U>,
|
|
|
|
U: ServiceFactory<
|
|
|
|
Config = T::Config,
|
|
|
|
Request = Result<T::Response, T::Error>,
|
|
|
|
Error = T::Error,
|
|
|
|
InitError = T::InitError,
|
|
|
|
>,
|
|
|
|
{
|
|
|
|
PipelineFactory {
|
2019-11-18 09:30:04 +01:00
|
|
|
factory: ThenServiceFactory::new(self.factory, factory.into_factory()),
|
2019-11-14 13:38:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Clone for PipelineFactory<T>
|
|
|
|
where
|
|
|
|
T: Clone,
|
|
|
|
{
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
PipelineFactory {
|
|
|
|
factory: self.factory.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ServiceFactory> ServiceFactory for PipelineFactory<T> {
|
|
|
|
type Config = T::Config;
|
|
|
|
type Request = T::Request;
|
|
|
|
type Response = T::Response;
|
|
|
|
type Error = T::Error;
|
|
|
|
type Service = T::Service;
|
|
|
|
type InitError = T::InitError;
|
|
|
|
type Future = T::Future;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn new_service(&self, cfg: &T::Config) -> Self::Future {
|
|
|
|
self.factory.new_service(cfg)
|
|
|
|
}
|
|
|
|
}
|