1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-01-31 19:40:07 +01:00

150 lines
4.1 KiB
Rust
Raw Normal View History

2018-09-27 17:05:48 -07:00
//! Contains `Either` service and related types and functions.
use actix_service::{IntoNewService, NewService, Service};
2019-03-04 20:37:03 -08:00
use futures::{future, try_ready, Async, Future, IntoFuture, Poll};
2018-09-27 17:05:48 -07:00
/// 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 struct EitherService<A, B> {
left: A,
right: B,
2018-09-27 17:05:48 -07:00
}
2019-01-16 15:00:08 -08:00
impl<A: Clone, B: Clone> Clone for EitherService<A, B> {
fn clone(&self) -> Self {
EitherService {
left: self.left.clone(),
right: self.right.clone(),
2019-01-16 15:00:08 -08:00
}
}
}
2019-03-09 07:27:35 -08:00
impl<A, B> Service for EitherService<A, B>
2018-09-27 17:05:48 -07:00
where
2019-03-09 07:27:35 -08:00
A: Service,
B: Service<Response = A::Response, Error = A::Error>,
2018-09-27 17:05:48 -07:00
{
type Request = either::Either<A::Request, B::Request>;
2018-09-27 17:05:48 -07:00
type Response = A::Response;
type Error = A::Error;
type Future = future::Either<A::Future, B::Future>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
let left = self.left.poll_ready()?;
let right = self.right.poll_ready()?;
if left.is_ready() && right.is_ready() {
Ok(Async::Ready(()))
} else {
Ok(Async::NotReady)
2018-09-27 17:05:48 -07:00
}
}
fn call(&mut self, req: either::Either<A::Request, B::Request>) -> Self::Future {
match req {
either::Either::Left(req) => future::Either::A(self.left.call(req)),
either::Either::Right(req) => future::Either::B(self.right.call(req)),
2018-09-27 17:05:48 -07:00
}
}
}
/// Combine two different new service types into a single service.
pub struct Either<A, B> {
left: A,
right: B,
2018-09-27 17:05:48 -07:00
}
impl<A, B> Either<A, B> {
2019-05-14 17:32:50 -07:00
pub fn new<F1, F2>(srv_a: F1, srv_b: F2) -> Either<A, B>
where
A: NewService,
2019-05-14 17:32:50 -07:00
B: NewService<
Config = A::Config,
Response = A::Response,
Error = A::Error,
InitError = A::InitError,
>,
F1: IntoNewService<A>,
F2: IntoNewService<B>,
{
Either {
2019-05-14 17:32:50 -07:00
left: srv_a.into_new_service(),
right: srv_b.into_new_service(),
}
}
}
impl<A, B> NewService for Either<A, B>
2018-09-27 17:05:48 -07:00
where
A: NewService,
2019-03-09 07:27:35 -08:00
B: NewService<
Config = A::Config,
2019-03-09 07:27:35 -08:00
Response = A::Response,
Error = A::Error,
InitError = A::InitError,
>,
2018-09-27 17:05:48 -07:00
{
type Request = either::Either<A::Request, B::Request>;
2018-09-27 17:05:48 -07:00
type Response = A::Response;
type Error = A::Error;
type InitError = A::InitError;
type Config = A::Config;
2018-09-27 17:05:48 -07:00
type Service = EitherService<A::Service, B::Service>;
type Future = EitherNewService<A, B>;
2018-09-27 17:05:48 -07:00
fn new_service(&self, cfg: &A::Config) -> Self::Future {
EitherNewService {
left: None,
right: None,
left_fut: self.left.new_service(cfg),
right_fut: self.right.new_service(cfg),
2018-09-27 17:05:48 -07:00
}
}
}
2019-01-16 15:00:08 -08:00
impl<A: Clone, B: Clone> Clone for Either<A, B> {
fn clone(&self) -> Self {
Self {
left: self.left.clone(),
right: self.right.clone(),
2019-01-16 15:00:08 -08:00
}
}
}
2018-09-27 17:05:48 -07:00
#[doc(hidden)]
pub struct EitherNewService<A: NewService, B: NewService> {
left: Option<A::Service>,
right: Option<B::Service>,
left_fut: <A::Future as IntoFuture>::Future,
right_fut: <B::Future as IntoFuture>::Future,
2018-09-27 17:05:48 -07:00
}
impl<A, B> Future for EitherNewService<A, B>
2018-09-27 17:05:48 -07:00
where
A: NewService,
B: NewService<Response = A::Response, Error = A::Error, InitError = A::InitError>,
2018-09-27 17:05:48 -07:00
{
type Item = EitherService<A::Service, B::Service>;
type Error = A::InitError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.left.is_none() {
self.left = Some(try_ready!(self.left_fut.poll()));
}
if self.right.is_none() {
self.right = Some(try_ready!(self.right_fut.poll()));
}
if self.left.is_some() && self.right.is_some() {
Ok(Async::Ready(EitherService {
left: self.left.take().unwrap(),
right: self.right.take().unwrap(),
}))
} else {
Ok(Async::NotReady)
2018-09-27 17:05:48 -07:00
}
}
}