tower_layer/
layer_fn.rs

1use super::Layer;
2use core::fmt;
3
4/// Returns a new [`LayerFn`] that implements [`Layer`] by calling the
5/// given function.
6///
7/// The [`Layer::layer()`] method takes a type implementing [`Service`] and
8/// returns a different type implementing [`Service`]. In many cases, this can
9/// be implemented by a function or a closure. The [`LayerFn`] helper allows
10/// writing simple [`Layer`] implementations without needing the boilerplate of
11/// a new struct implementing [`Layer`].
12///
13/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
14/// [`Layer::layer()`]: crate::Layer::layer
15///
16/// # Examples
17///
18/// ```rust
19/// # use tower::Service;
20/// # use core::task::{Poll, Context};
21/// # use tower_layer::{Layer, layer_fn};
22/// # use core::fmt;
23/// # use core::convert::Infallible;
24/// #
25/// // A middleware that logs requests before forwarding them to another service
26/// pub struct LogService<S> {
27///     target: &'static str,
28///     service: S,
29/// }
30///
31/// impl<S, Request> Service<Request> for LogService<S>
32/// where
33///     S: Service<Request>,
34///     Request: fmt::Debug,
35/// {
36///     type Response = S::Response;
37///     type Error = S::Error;
38///     type Future = S::Future;
39///
40///     fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
41///         self.service.poll_ready(cx)
42///     }
43///
44///     fn call(&mut self, request: Request) -> Self::Future {
45///         // Log the request
46///         println!("request = {:?}, target = {:?}", request, self.target);
47///
48///         self.service.call(request)
49///     }
50/// }
51///
52/// // A `Layer` that wraps services in `LogService`
53/// let log_layer = layer_fn(|service| {
54///     LogService {
55///         service,
56///         target: "tower-docs",
57///     }
58/// });
59///
60/// // An example service. This one uppercases strings
61/// let uppercase_service = tower::service_fn(|request: String| async move {
62///     Ok::<_, Infallible>(request.to_uppercase())
63/// });
64///
65/// // Wrap our service in a `LogService` so requests are logged.
66/// let wrapped_service = log_layer.layer(uppercase_service);
67/// ```
68pub fn layer_fn<T>(f: T) -> LayerFn<T> {
69    LayerFn { f }
70}
71
72/// A `Layer` implemented by a closure. See the docs for [`layer_fn`] for more details.
73#[derive(Clone, Copy)]
74pub struct LayerFn<F> {
75    f: F,
76}
77
78impl<F, S, Out> Layer<S> for LayerFn<F>
79where
80    F: Fn(S) -> Out,
81{
82    type Service = Out;
83
84    fn layer(&self, inner: S) -> Self::Service {
85        (self.f)(inner)
86    }
87}
88
89impl<F> fmt::Debug for LayerFn<F> {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        f.debug_struct("LayerFn")
92            .field("f", &format_args!("{}", core::any::type_name::<F>()))
93            .finish()
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100    use alloc::{format, string::ToString};
101
102    #[allow(dead_code)]
103    #[test]
104    fn layer_fn_has_useful_debug_impl() {
105        struct WrappedService<S> {
106            inner: S,
107        }
108        let layer = layer_fn(|svc| WrappedService { inner: svc });
109        let _svc = layer.layer("foo");
110
111        assert_eq!(
112            "LayerFn { f: tower_layer::layer_fn::tests::layer_fn_has_useful_debug_impl::{{closure}} }".to_string(),
113            format!("{layer:?}"),
114        );
115    }
116}