xitca_service/pipeline/
enum.rs

1use core::{
2    convert::Infallible,
3    error::Error,
4    fmt::{self, Debug, Display, Formatter},
5};
6
7use crate::{ready::ReadyService, service::Service};
8
9/// A pipeline type where two variants have a either/or relationship
10pub enum Pipeline<F, S> {
11    First(F),
12    Second(S),
13}
14
15impl<F, S> Clone for Pipeline<F, S>
16where
17    F: Clone,
18    S: Clone,
19{
20    fn clone(&self) -> Self {
21        match *self {
22            Self::First(ref p) => Self::First(p.clone()),
23            Self::Second(ref p) => Self::Second(p.clone()),
24        }
25    }
26}
27
28impl<F, S> Pipeline<F, S>
29where
30    F: From<S>,
31{
32    pub fn into_first(self) -> F {
33        match self {
34            Self::First(f) => f,
35            Self::Second(s) => F::from(s),
36        }
37    }
38}
39
40impl<F, S> Pipeline<F, S>
41where
42    S: From<F>,
43{
44    pub fn into_second(self) -> S {
45        match self {
46            Self::First(f) => S::from(f),
47            Self::Second(s) => s,
48        }
49    }
50}
51
52impl<F, S> Debug for Pipeline<F, S>
53where
54    F: Debug,
55    S: Debug,
56{
57    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
58        match *self {
59            Self::First(ref p) => Debug::fmt(p, f),
60            Self::Second(ref p) => Debug::fmt(p, f),
61        }
62    }
63}
64
65impl<F, S> Display for Pipeline<F, S>
66where
67    F: Display,
68    S: Display,
69{
70    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
71        match *self {
72            Self::First(ref p) => Display::fmt(p, f),
73            Self::Second(ref p) => Display::fmt(p, f),
74        }
75    }
76}
77
78// useful default impl when pipeline enum used as error type.
79impl<F, S> From<Infallible> for Pipeline<F, S> {
80    fn from(e: Infallible) -> Self {
81        match e {}
82    }
83}
84
85impl<F, S, Req> Service<Req> for Pipeline<F, S>
86where
87    F: Service<Req>,
88    S: Service<Req, Response = F::Response, Error = F::Error>,
89{
90    type Response = F::Response;
91    type Error = F::Error;
92
93    async fn call(&self, req: Req) -> Result<Self::Response, Self::Error> {
94        match *self {
95            Self::First(ref f) => f.call(req).await,
96            Self::Second(ref s) => s.call(req).await,
97        }
98    }
99}
100
101impl<F, S> ReadyService for Pipeline<F, S>
102where
103    F: ReadyService,
104    S: ReadyService,
105{
106    type Ready = Pipeline<F::Ready, S::Ready>;
107
108    #[inline]
109    async fn ready(&self) -> Self::Ready {
110        match *self {
111            Self::First(ref f) => Pipeline::First(f.ready().await),
112            Self::Second(ref s) => Pipeline::Second(s.ready().await),
113        }
114    }
115}
116
117impl<F, S> Error for Pipeline<F, S>
118where
119    F: Error,
120    S: Error,
121{
122    fn source(&self) -> Option<&(dyn Error + 'static)> {
123        match *self {
124            Self::First(ref f) => Error::source(f),
125            Self::Second(ref f) => Error::source(f),
126        }
127    }
128}