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