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: &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