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