1use std::future::poll_fn;
58use std::pin::Pin;
59use std::task::{Context, Poll};
60
61use tower_layer::Layer;
62
63use crate::Service;
64
65#[derive(Debug, Clone)]
71pub struct Adapter<S>(pub S);
72
73impl<S, Req, T, E> tower_service::Service<Req> for Adapter<S>
74where
75 S: Service<Req, Out = Result<T, E>> + Clone + 'static,
76 T: Send + 'static,
77 E: Send + 'static,
78 Req: Send + 'static,
79{
80 type Response = T;
81 type Error = E;
82 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
83
84 #[cfg_attr(test, mutants::skip)] fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
86 Poll::Ready(Ok(()))
88 }
89
90 fn call(&mut self, req: Req) -> Self::Future {
91 let service = self.0.clone();
92 Box::pin(async move { service.execute(req).await })
93 }
94}
95
96impl<S, In: Send> Service<In> for Adapter<S>
97where
98 S: tower_service::Service<In> + Send + Sync + Clone,
99 S::Future: Send,
100{
101 type Out = Result<S::Response, S::Error>;
102
103 fn execute(&self, input: In) -> impl Future<Output = Self::Out> + Send {
104 let mut clone = self.0.clone();
105
106 async move {
107 poll_fn(|cx| clone.poll_ready(cx)).await?;
109 clone.call(input).await
111 }
112 }
113}
114
115pub fn tower_layer<L>(tower_layer: L) -> AdapterLayer<L> {
126 AdapterLayer(tower_layer)
127}
128
129#[derive(Debug, Clone)]
133pub struct AdapterLayer<L>(L);
134
135impl<L, S> Layer<S> for AdapterLayer<L>
136where
137 L: Layer<Adapter<S>> + Clone,
138{
139 type Service = Adapter<L::Service>;
140
141 fn layer(&self, inner: S) -> Self::Service {
142 let tower_adapted = Adapter(inner);
144 let tower_layered = self.0.layer(tower_adapted);
146 Adapter(tower_layered)
148 }
149}
150
151#[cfg_attr(coverage_nightly, coverage(off))]
152#[cfg(test)]
153mod tests {
154 use futures::executor::block_on;
155 use tower::service_fn;
156 use tower_service::Service as TowerService;
157
158 use super::*;
159 use crate::testing::MockService;
160
161 #[test]
162 fn adapt_tower_ok() {
163 let service = service_fn(|req: u32| async move { Ok::<_, ()>(req + 1) });
164 let service = Adapter(service);
165
166 let result = block_on(service.execute(0));
167
168 assert_eq!(result, Ok(1));
169 }
170
171 #[test]
172 fn adapt_tower_ensure_poll_error_respected() {
173 let service = MockService::new(Poll::Ready(Err("error".to_string())), Err("call error".to_string()));
174 let service = Adapter(service);
175
176 let result = block_on(service.execute("request".to_string()));
177
178 assert_eq!(result, Err("error".to_string()));
179 }
180
181 #[test]
182 fn adapt_oxidizer_ok() {
183 let mock_service = MockService::new(Poll::Ready(Ok(())), Ok("success".to_string()));
184 let mut service = Adapter(mock_service);
185
186 let result = block_on(async move { service.call("request".to_string()).await });
187
188 assert_eq!(result, Ok("success".to_string()));
189 }
190
191 #[test]
192 fn poll_ready_always_returns_ready_ok() {
193 let mock_service = MockService::new(Poll::Ready(Ok(())), Ok("success".to_string()));
194 let mut adapter = Adapter(mock_service);
195
196 let waker = futures::task::noop_waker();
197 let mut cx = Context::from_waker(&waker);
198
199 let result = adapter.poll_ready(&mut cx);
200 assert_eq!(result, Poll::Ready(Ok(())));
201 }
202
203 #[test]
204 fn poll_ready_consistent_behavior() {
205 let mock_service = MockService::new(Poll::Ready(Ok(())), Ok("success".to_string()));
206 let mut adapter = Adapter(mock_service);
207
208 let waker = futures::task::noop_waker();
209 let mut cx = Context::from_waker(&waker);
210
211 for _ in 0..3 {
213 let result = adapter.poll_ready(&mut cx);
214 assert_eq!(result, Poll::Ready(Ok(())));
215 }
216 }
217
218 #[test]
219 fn poll_ready_with_mock_service() {
220 let mock_service = MockService::new(Poll::Ready(Ok(())), Ok("success".to_string()));
221 let mut mock_adapter = Adapter(mock_service);
222
223 let waker = futures::task::noop_waker();
224 let mut cx = Context::from_waker(&waker);
225
226 assert_eq!(mock_adapter.poll_ready(&mut cx), Poll::Ready(Ok(())));
227 }
228
229 #[test]
230 fn poll_ready_mutation_equivalence() {
231 let mock_service = MockService::new(Poll::Ready(Ok(())), Ok("success".to_string()));
234 let mut adapter = Adapter(mock_service);
235
236 let waker = futures::task::noop_waker();
237 let mut cx = Context::from_waker(&waker);
238
239 let result1 = adapter.poll_ready(&mut cx);
240 let result2 = Poll::from(Ok::<(), String>(()));
241
242 assert_eq!(result1, Poll::Ready(Ok(())));
244 assert_eq!(result2, Poll::Ready(Ok(())));
245 assert_eq!(result1, result2);
246 }
247
248 #[test]
249 fn adapter_execute_fails_when_tower_service_poll_ready_errors() {
250 let mock_service = MockService::new(Poll::Ready(Err("service unavailable".to_string())), Ok("success".to_string()));
251 let service = Adapter(mock_service);
252
253 let result = block_on(service.execute("request".to_string()));
254
255 assert_eq!(result, Err("service unavailable".to_string()));
256 }
257
258 #[test]
259 fn tower_layer_adapter() {
260 use crate::{Execute, Stack};
261 use tower_layer::Identity;
262
263 let stack = (tower_layer(Identity::new()), Execute::new(|x: i32| async move { Ok::<_, ()>(x) }));
264 let svc = stack.into_service();
265 assert_eq!(block_on(svc.execute(42)), Ok(42));
266 }
267}