Coverage Report

Created: 2026-02-14 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tower-layer-0.3.3/src/layer_fn.rs
Line
Count
Source
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
67
0
pub fn layer_fn<T>(f: T) -> LayerFn<T> {
68
0
    LayerFn { f }
69
0
}
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
83
0
    fn layer(&self, inner: S) -> Self::Service {
84
0
        (self.f)(inner)
85
0
    }
86
}
87
88
impl<F> fmt::Debug for LayerFn<F> {
89
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90
0
        f.debug_struct("LayerFn")
91
0
            .field("f", &format_args!("{}", std::any::type_name::<F>()))
92
0
            .finish()
93
0
    }
94
}
95
96
#[cfg(test)]
97
mod 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
}