use std::task::{Context, Poll}; use crate::and_then::{AndThenService, AndThenServiceFactory}; use crate::then::{ThenService, ThenServiceFactory}; use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory}; pub fn pipeline(service: F) -> Pipeline where F: IntoService, T: Service, { Pipeline { service: service.into_service(), } } pub fn pipeline_factory(factory: F) -> PipelineFactory where T: ServiceFactory, F: IntoServiceFactory, { PipelineFactory { factory: factory.into_factory(), } } /// Pipeline service pub struct Pipeline { service: T, } impl Pipeline { /// 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. pub fn and_then(self, service: F) -> Pipeline> where Self: Sized, F: IntoService, U: Service, { Pipeline { service: AndThenService::new(self.service, service.into_service()), } } /// 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. pub fn then(self, service: F) -> Pipeline> where Self: Sized, F: IntoService, U: Service, Error = T::Error>, { Pipeline { service: ThenService::new(self.service, service.into_service()), } } } impl Clone for Pipeline where T: Clone, { fn clone(&self) -> Self { Pipeline { service: self.service.clone(), } } } impl Service for Pipeline { 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> { self.service.poll_ready(ctx) } #[inline] fn call(&mut self, req: T::Request) -> Self::Future { self.service.call(req) } } /// Pipeline constructor pub struct PipelineFactory { factory: T, } impl PipelineFactory { /// Call another service after call to this one has resolved successfully. pub fn and_then(self, factory: F) -> PipelineFactory> where Self: Sized, F: IntoServiceFactory, U: ServiceFactory< Config = T::Config, Request = T::Response, Error = T::Error, InitError = T::InitError, >, { PipelineFactory { factory: AndThenServiceFactory::new(self.factory, factory.into_factory()), } } /// 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. pub fn then(self, factory: F) -> PipelineFactory> where Self: Sized, F: IntoServiceFactory, U: ServiceFactory< Config = T::Config, Request = Result, Error = T::Error, InitError = T::InitError, >, { PipelineFactory { factory: ThenServiceFactory::new(self.factory, factory.into_factory()), } } } impl Clone for PipelineFactory where T: Clone, { fn clone(&self) -> Self { PipelineFactory { factory: self.factory.clone(), } } } impl ServiceFactory for PipelineFactory { 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) } }