| 1 | //! Contains [`Optional`] and related types and functions. |
| 2 | //! |
| 3 | //! See [`Optional`] documentation for more details. |
| 4 | |
| 5 | /// Error types for [`Optional`]. |
| 6 | pub mod error; |
| 7 | /// Future types for [`Optional`]. |
| 8 | pub mod future; |
| 9 | |
| 10 | use self::future::ResponseFuture; |
| 11 | use std::task::{Context, Poll}; |
| 12 | use tower_service::Service; |
| 13 | |
| 14 | /// Optionally forwards requests to an inner service. |
| 15 | /// |
| 16 | /// If the inner service is [`None`], [`optional::None`] is returned as the response. |
| 17 | /// |
| 18 | /// [`optional::None`]: crate::util::error::optional::None |
| 19 | #[derive (Debug)] |
| 20 | pub struct Optional<T> { |
| 21 | inner: Option<T>, |
| 22 | } |
| 23 | |
| 24 | impl<T> Optional<T> { |
| 25 | /// Create a new [`Optional`]. |
| 26 | pub const fn new<Request>(inner: Option<T>) -> Optional<T> |
| 27 | where |
| 28 | T: Service<Request>, |
| 29 | T::Error: Into<crate::BoxError>, |
| 30 | { |
| 31 | Optional { inner } |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | impl<T, Request> Service<Request> for Optional<T> |
| 36 | where |
| 37 | T: Service<Request>, |
| 38 | T::Error: Into<crate::BoxError>, |
| 39 | { |
| 40 | type Response = T::Response; |
| 41 | type Error = crate::BoxError; |
| 42 | type Future = ResponseFuture<T::Future>; |
| 43 | |
| 44 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
| 45 | match self.inner { |
| 46 | Some(ref mut inner: &mut T) => match inner.poll_ready(cx) { |
| 47 | Poll::Ready(r: Result<(), impl Into>>) => Poll::Ready(r.map_err(op:Into::into)), |
| 48 | Poll::Pending => Poll::Pending, |
| 49 | }, |
| 50 | // None services are always ready |
| 51 | None => Poll::Ready(Ok(())), |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | fn call(&mut self, request: Request) -> Self::Future { |
| 56 | let inner: Option>> = self.inner.as_mut().map(|i: &mut T| i.call(req:request)); |
| 57 | ResponseFuture::new(inner) |
| 58 | } |
| 59 | } |
| 60 | |