tower_layer/layer_fn.rs
1use super::Layer;
2use 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
67pub 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)]
73pub struct LayerFn<F> {
74 f: F,
75}
76
77impl<F, S, Out> Layer<S> for LayerFn<F>
78where
79 F: Fn(S) -> Out,
80{
81 type Service = Out;
82
83 fn layer(&self, inner: S) -> Self::Service {
84 (self.f)(inner)
85 }
86}
87
88impl<F> fmt::Debug for LayerFn<F> {
89 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)]
97mod tests {
98 use super::*;
99
100 #[allow(dead_code)]
101 #[test]
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}