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