tower/util/optional/
mod.rs

1//! Contains [`Optional`] and related types and functions.
2//!
3//! See [`Optional`] documentation for more details.
4
5/// Error types for [`Optional`].
6pub mod error;
7/// Future types for [`Optional`].
8pub mod future;
9
10use self::future::ResponseFuture;
11use std::task::{Context, Poll};
12use 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)]
20pub struct Optional<T> {
21    inner: Option<T>,
22}
23
24impl<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
35impl<T, Request> Service<Request> for Optional<T>
36where
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) => match inner.poll_ready(cx) {
47                Poll::Ready(r) => Poll::Ready(r.map_err(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 = self.inner.as_mut().map(|i| i.call(request));
57        ResponseFuture::new(inner)
58    }
59}