/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 | | } |