1use core::convert::Infallible;
4use core::fmt;
5use core::marker::PhantomData;
6use core::pin::Pin;
7
8use crate::std::{boxed::Box, sync::Arc};
9
10pub trait Service<Input>: Sized + Send + Sync + 'static {
14 type Output: Send + 'static;
16
17 type Error: Send + 'static;
19
20 fn serve(
22 &self,
23 input: Input,
24 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send + '_;
25
26 fn boxed(self) -> BoxService<Input, Self::Output, Self::Error> {
28 BoxService::new(self)
29 }
30}
31
32impl<Input> Service<Input> for ()
33where
34 Input: Send + 'static,
35{
36 type Output = Input;
37 type Error = Infallible;
38
39 async fn serve(&self, input: Input) -> Result<Self::Output, Self::Error> {
40 Ok(input)
41 }
42}
43
44impl<S, Input> Service<Input> for Arc<S>
45where
46 S: Service<Input>,
47{
48 type Output = S::Output;
49 type Error = S::Error;
50
51 #[inline]
52 fn serve(
53 &self,
54 input: Input,
55 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send + '_ {
56 self.as_ref().serve(input)
57 }
58}
59
60impl<S, Input> Service<Input> for &'static S
61where
62 S: Service<Input>,
63{
64 type Output = S::Output;
65 type Error = S::Error;
66
67 #[inline(always)]
68 fn serve(
69 &self,
70 input: Input,
71 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send + '_ {
72 (**self).serve(input)
73 }
74}
75
76impl<S, Input> Service<Input> for Box<S>
77where
78 S: Service<Input>,
79{
80 type Output = S::Output;
81 type Error = S::Error;
82
83 #[inline]
84 fn serve(
85 &self,
86
87 input: Input,
88 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send + '_ {
89 self.as_ref().serve(input)
90 }
91}
92
93trait DynService<Input> {
98 type Output;
99 type Error;
100
101 #[expect(clippy::type_complexity)]
102 fn serve_box(
103 &self,
104 input: Input,
105 ) -> Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send + '_>>;
106}
107
108impl<Input, T> DynService<Input> for T
109where
110 T: Service<Input>,
111{
112 type Output = T::Output;
113 type Error = T::Error;
114
115 fn serve_box(
116 &self,
117 input: Input,
118 ) -> Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send + '_>> {
119 Box::pin(self.serve(input))
120 }
121}
122
123pub struct BoxService<Input, Output, Error> {
126 inner: Arc<dyn DynService<Input, Output = Output, Error = Error> + Send + Sync + 'static>,
127}
128
129impl<Input, Output, Error> Clone for BoxService<Input, Output, Error> {
130 fn clone(&self) -> Self {
131 Self {
132 inner: self.inner.clone(),
133 }
134 }
135}
136
137impl<Input, Output, Error> BoxService<Input, Output, Error> {
138 #[inline]
140 pub fn new<T>(service: T) -> Self
141 where
142 T: Service<Input, Output = Output, Error = Error>,
143 {
144 Self {
145 inner: Arc::new(service),
146 }
147 }
148}
149
150impl<Input, Output, Error> core::fmt::Debug for BoxService<Input, Output, Error> {
151 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
152 f.debug_struct("BoxService").finish()
153 }
154}
155
156impl<Input, Output, Error> Service<Input> for BoxService<Input, Output, Error>
157where
158 Input: 'static,
159 Output: Send + 'static,
160 Error: Send + 'static,
161{
162 type Output = Output;
163 type Error = Error;
164
165 #[inline]
166 fn serve(
167 &self,
168
169 input: Input,
170 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send + '_ {
171 self.inner.serve_box(input)
172 }
173
174 #[inline]
175 fn boxed(self) -> Self {
176 self
177 }
178}
179
180macro_rules! impl_service_either {
181 ($id:ident, $first:ident $(, $param:ident)* $(,)?) => {
182 impl<$first, $($param,)* Input, Output> Service<Input> for crate::combinators::$id<$first $(,$param)*>
183 where
184 $first: Service<Input, Output = Output>,
185 $(
186 $param: Service<Input, Output = Output, Error: Into<$first::Error>>,
187 )*
188 Input: Send + 'static,
189 Output: Send + 'static,
190 {
191 type Output = Output;
192 type Error = $first::Error;
193
194 async fn serve(&self, input: Input) -> Result<Self::Output, Self::Error> {
195 match self {
196 crate::combinators::$id::$first(s) => s.serve(input).await,
197 $(
198 crate::combinators::$id::$param(s) => s.serve(input).await.map_err(Into::into),
199 )*
200 }
201 }
202 }
203 };
204}
205
206crate::combinators::impl_either!(impl_service_either);
207
208#[non_exhaustive]
209#[derive(Debug, Clone, Copy, Default)]
210pub struct MirrorService;
213
214impl MirrorService {
215 #[inline(always)]
217 #[must_use]
218 pub fn new() -> Self {
219 Self
220 }
221}
222
223impl<Input> Service<Input> for MirrorService
224where
225 Input: Send + 'static,
226{
227 type Output = Input;
228 type Error = Infallible;
229
230 #[inline]
231 fn serve(
232 &self,
233 input: Input,
234 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send + '_ {
235 core::future::ready(Ok(input))
236 }
237}
238
239rama_utils::macros::error::static_str_error! {
240 #[doc = "Input rejected"]
241 pub struct RejectError;
242}
243
244pub struct RejectService<R = (), E = RejectError> {
246 error: E,
247 _phantom: PhantomData<fn() -> R>,
248}
249
250impl Default for RejectService {
251 fn default() -> Self {
252 Self {
253 error: RejectError,
254 _phantom: PhantomData,
255 }
256 }
257}
258
259impl<R, E: Clone + Send + Sync + 'static> RejectService<R, E> {
260 pub fn new(error: E) -> Self {
262 Self {
263 error,
264 _phantom: PhantomData,
265 }
266 }
267}
268
269impl<R, E: Clone> Clone for RejectService<R, E> {
270 fn clone(&self) -> Self {
271 Self {
272 error: self.error.clone(),
273 _phantom: PhantomData,
274 }
275 }
276}
277
278impl<R, E: fmt::Debug> fmt::Debug for RejectService<R, E> {
279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280 f.debug_struct("RejectService")
281 .field("error", &self.error)
282 .field(
283 "_phantom",
284 &format_args!("{}", core::any::type_name::<fn() -> R>()),
285 )
286 .finish()
287 }
288}
289
290impl<Input, Output, Error> Service<Input> for RejectService<Output, Error>
291where
292 Input: 'static,
293 Output: Send + 'static,
294 Error: Clone + Send + Sync + 'static,
295{
296 type Output = Output;
297 type Error = Error;
298
299 #[inline]
300 fn serve(
301 &self,
302
303 _input: Input,
304 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send + '_ {
305 let error = self.error.clone();
306 core::future::ready(Err(error))
307 }
308}
309
310#[derive(Debug, Clone)]
312pub struct StaticOutput<O>(O);
313
314impl<O> StaticOutput<O>
315where
316 O: Clone + Send + Sync + 'static,
317{
318 #[inline(always)]
320 pub fn new(value: O) -> Self {
321 Self(value)
322 }
323}
324
325impl<I, O> Service<I> for StaticOutput<O>
326where
327 I: Send + 'static,
328 O: Clone + Send + Sync + 'static,
329{
330 type Output = O;
331 type Error = Infallible;
332
333 async fn serve(&self, _: I) -> Result<Self::Output, Self::Error> {
334 Ok(self.0.clone())
335 }
336}
337
338#[cfg(test)]
339mod tests {
340 use super::*;
341 use core::convert::Infallible;
342
343 #[derive(Debug)]
344 struct AddSvc(usize);
345
346 impl Service<usize> for AddSvc {
347 type Output = usize;
348 type Error = Infallible;
349
350 async fn serve(&self, input: usize) -> Result<Self::Output, Self::Error> {
351 Ok(self.0 + input)
352 }
353 }
354
355 #[derive(Debug)]
356 struct MulSvc(usize);
357
358 impl Service<usize> for MulSvc {
359 type Output = usize;
360 type Error = Infallible;
361
362 async fn serve(&self, input: usize) -> Result<Self::Output, Self::Error> {
363 Ok(self.0 * input)
364 }
365 }
366
367 #[test]
368 fn assert_send() {
369 use rama_utils::test_helpers::*;
370
371 assert_send::<AddSvc>();
372 assert_send::<MulSvc>();
373 assert_send::<BoxService<(), (), ()>>();
374 assert_send::<RejectService>();
375 }
376
377 #[test]
378 fn assert_sync() {
379 use rama_utils::test_helpers::*;
380
381 assert_sync::<AddSvc>();
382 assert_sync::<MulSvc>();
383 assert_sync::<BoxService<(), (), ()>>();
384 assert_sync::<RejectService>();
385 }
386
387 #[tokio::test]
388 async fn add_svc() {
389 let svc = AddSvc(1);
390
391 let output = svc.serve(1).await.unwrap();
392 assert_eq!(output, 2);
393 }
394
395 #[tokio::test]
396 async fn static_dispatch() {
397 let services = vec![AddSvc(1), AddSvc(2), AddSvc(3)];
398
399 for (i, svc) in services.into_iter().enumerate() {
400 let output = svc.serve(i).await.unwrap();
401 assert_eq!(output, i * 2 + 1);
402 }
403 }
404
405 #[tokio::test]
406 async fn dynamic_dispatch() {
407 let services = vec![
408 AddSvc(1).boxed(),
409 AddSvc(2).boxed(),
410 AddSvc(3).boxed(),
411 MulSvc(4).boxed(),
412 MulSvc(5).boxed(),
413 ];
414
415 for (i, svc) in services.into_iter().enumerate() {
416 let output = svc.serve(i).await.unwrap();
417 if i < 3 {
418 assert_eq!(output, i * 2 + 1);
419 } else {
420 assert_eq!(output, i * (i + 1));
421 }
422 }
423 }
424
425 #[tokio::test]
426 async fn service_arc() {
427 let svc = crate::std::sync::Arc::new(AddSvc(1));
428
429 let output = svc.serve(1).await.unwrap();
430 assert_eq!(output, 2);
431 }
432
433 #[tokio::test]
434 async fn box_service_arc() {
435 let svc = crate::std::sync::Arc::new(AddSvc(1)).boxed();
436
437 let output = svc.serve(1).await.unwrap();
438 assert_eq!(output, 2);
439 }
440
441 #[tokio::test]
442 async fn reject_svc() {
443 let svc = RejectService::default();
444
445 let err = svc.serve(1).await.unwrap_err();
446 assert_eq!(err.to_string(), RejectError::new().to_string());
447 }
448}