1use std::{
26 marker::PhantomData,
27 task::{Context, Poll},
28};
29
30use tower_layer::Layer;
31use tower_service::Service;
32
33use crate::server::NamedService;
34
35#[derive(Debug, Clone)]
37pub struct Layered<S, T> {
38 inner: S,
39 _ty: PhantomData<T>,
40}
41
42impl<S, T: NamedService> NamedService for Layered<S, T> {
43 const NAME: &'static str = T::NAME;
44}
45
46impl<Req, S, T> Service<Req> for Layered<S, T>
47where
48 S: Service<Req>,
49{
50 type Response = S::Response;
51 type Error = S::Error;
52 type Future = S::Future;
53
54 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
55 self.inner.poll_ready(cx)
56 }
57
58 fn call(&mut self, req: Req) -> Self::Future {
59 self.inner.call(req)
60 }
61}
62
63pub trait LayerExt<L>: sealed::Sealed {
65 fn named_layer<S>(&self, service: S) -> Layered<L::Service, S>
67 where
68 L: Layer<S>;
69}
70
71impl<L> LayerExt<L> for L {
72 fn named_layer<S>(&self, service: S) -> Layered<<L>::Service, S>
73 where
74 L: Layer<S>,
75 {
76 Layered {
77 inner: self.layer(service),
78 _ty: PhantomData,
79 }
80 }
81}
82
83mod sealed {
84 pub trait Sealed {}
85 impl<T> Sealed for T {}
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[derive(Debug, Default)]
93 struct TestService {}
94
95 const TEST_SERVICE_NAME: &str = "test-service-name";
96
97 impl NamedService for TestService {
98 const NAME: &'static str = TEST_SERVICE_NAME;
99 }
100
101 fn get_name_of_named_service<S: NamedService>(_s: &S) -> &'static str {
103 S::NAME
104 }
105
106 #[test]
107 fn named_service_is_propagated_to_layered() {
108 use std::time::Duration;
109 use tower::{limit::ConcurrencyLimitLayer, timeout::TimeoutLayer};
110
111 let layered = TimeoutLayer::new(Duration::from_secs(5)).named_layer(TestService::default());
112 assert_eq!(get_name_of_named_service(&layered), TEST_SERVICE_NAME);
113
114 let layered = ConcurrencyLimitLayer::new(3).named_layer(layered);
115 assert_eq!(get_name_of_named_service(&layered), TEST_SERVICE_NAME);
116 }
117}