//! Contains `Either` service and related types and functions. use actix_service::{NewService, Service}; use futures::{future, try_ready, Async, Future, Poll}; /// Combine two different service types into a single type. /// /// Both services must be of the same request, response, and error types. /// `EitherService` is useful for handling conditional branching in service /// middleware to different inner service types. pub enum EitherService { A(A), B(B), } impl Clone for EitherService { fn clone(&self) -> Self { match self { EitherService::A(srv) => EitherService::A(srv.clone()), EitherService::B(srv) => EitherService::B(srv.clone()), } } } impl Service for EitherService where A: Service, B: Service, { type Response = A::Response; type Error = A::Error; type Future = future::Either; fn poll_ready(&mut self) -> Poll<(), Self::Error> { match self { EitherService::A(ref mut inner) => inner.poll_ready(), EitherService::B(ref mut inner) => inner.poll_ready(), } } fn call(&mut self, req: Request) -> Self::Future { match self { EitherService::A(ref mut inner) => future::Either::A(inner.call(req)), EitherService::B(ref mut inner) => future::Either::B(inner.call(req)), } } } /// Combine two different new service types into a single type. pub enum Either { A(A), B(B), } impl Either { pub fn new_a(srv: A) -> Self where A: NewService, B: NewService< Request, Response = A::Response, Error = A::Error, InitError = A::InitError, >, { Either::A(srv) } pub fn new_b(srv: B) -> Self where A: NewService, B: NewService< Request, Response = A::Response, Error = A::Error, InitError = A::InitError, >, { Either::B(srv) } } impl NewService for Either where A: NewService, B: NewService, { type Response = A::Response; type Error = A::Error; type InitError = A::InitError; type Service = EitherService; type Future = EitherNewService; fn new_service(&self) -> Self::Future { match self { Either::A(ref inner) => EitherNewService::A(inner.new_service()), Either::B(ref inner) => EitherNewService::B(inner.new_service()), } } } impl Clone for Either { fn clone(&self) -> Self { match self { Either::A(srv) => Either::A(srv.clone()), Either::B(srv) => Either::B(srv.clone()), } } } #[doc(hidden)] pub enum EitherNewService, B: NewService, R> { A(A::Future), B(B::Future), } impl Future for EitherNewService where A: NewService, B: NewService, { type Item = EitherService; type Error = A::InitError; fn poll(&mut self) -> Poll { match self { EitherNewService::A(ref mut fut) => { let service = try_ready!(fut.poll()); Ok(Async::Ready(EitherService::A(service))) } EitherNewService::B(ref mut fut) => { let service = try_ready!(fut.poll()); Ok(Async::Ready(EitherService::B(service))) } } } }