| //! Contains [`Optional`] and related types and functions. |
| //! |
| //! See [`Optional`] documentation for more details. |
| |
| /// Error types for [`Optional`]. |
| pub mod error; |
| /// Future types for [`Optional`]. |
| pub mod future; |
| |
| use self::future::ResponseFuture; |
| use std::task::{Context, Poll}; |
| use tower_service::Service; |
| |
| /// Optionally forwards requests to an inner service. |
| /// |
| /// If the inner service is [`None`], [`optional::None`] is returned as the response. |
| /// |
| /// [`optional::None`]: crate::util::error::optional::None |
| #[derive(Debug)] |
| pub struct Optional<T> { |
| inner: Option<T>, |
| } |
| |
| impl<T> Optional<T> { |
| /// Create a new [`Optional`]. |
| pub fn new<Request>(inner: Option<T>) -> Optional<T> |
| where |
| T: Service<Request>, |
| T::Error: Into<crate::BoxError>, |
| { |
| Optional { inner } |
| } |
| } |
| |
| impl<T, Request> Service<Request> for Optional<T> |
| where |
| T: Service<Request>, |
| T::Error: Into<crate::BoxError>, |
| { |
| type Response = T::Response; |
| type Error = crate::BoxError; |
| type Future = ResponseFuture<T::Future>; |
| |
| fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
| match self.inner { |
| Some(ref mut inner) => match inner.poll_ready(cx) { |
| Poll::Ready(r) => Poll::Ready(r.map_err(Into::into)), |
| Poll::Pending => Poll::Pending, |
| }, |
| // None services are always ready |
| None => Poll::Ready(Ok(())), |
| } |
| } |
| |
| fn call(&mut self, request: Request) -> Self::Future { |
| let inner = self.inner.as_mut().map(|i| i.call(request)); |
| ResponseFuture::new(inner) |
| } |
| } |