rama_core/layer/
map_response.rs

1use crate::{Context, Layer, Service};
2use rama_utils::macros::define_inner_service_accessors;
3use std::fmt;
4
5/// Maps this service's response value to a different value.
6///
7/// This method can be used to change the `Response` type of the service
8/// into a different type. It is similar to the [`Result::map`]
9/// method. You can use this method to chain along a computation once the
10/// service's response has been resolved.
11pub struct MapResponse<S, F> {
12    inner: S,
13    f: F,
14}
15
16impl<S, F> Clone for MapResponse<S, F>
17where
18    S: Clone,
19    F: Clone,
20{
21    fn clone(&self) -> Self {
22        MapResponse {
23            inner: self.inner.clone(),
24            f: self.f.clone(),
25        }
26    }
27}
28
29impl<S, F> fmt::Debug for MapResponse<S, F>
30where
31    S: fmt::Debug,
32{
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        f.debug_struct("MapResponse")
35            .field("inner", &self.inner)
36            .field("f", &format_args!("{}", std::any::type_name::<F>()))
37            .finish()
38    }
39}
40
41/// A [`Layer`] that produces a [`MapResponse`] service.
42///
43/// [`Layer`]: crate::Layer
44pub struct MapResponseLayer<F> {
45    f: F,
46}
47
48impl<F> Clone for MapResponseLayer<F>
49where
50    F: Clone,
51{
52    fn clone(&self) -> Self {
53        MapResponseLayer { f: self.f.clone() }
54    }
55}
56
57impl<F> fmt::Debug for MapResponseLayer<F>
58where
59    F: fmt::Debug,
60{
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        f.debug_struct("MapResponseLayer")
63            .field("f", &format_args!("{}", std::any::type_name::<F>()))
64            .finish()
65    }
66}
67
68impl<S, F> MapResponse<S, F> {
69    /// Creates a new `MapResponse` service.
70    pub const fn new(inner: S, f: F) -> Self {
71        MapResponse { f, inner }
72    }
73
74    define_inner_service_accessors!();
75}
76
77impl<S, F, State, Request, Response> Service<State, Request> for MapResponse<S, F>
78where
79    S: Service<State, Request>,
80    F: FnOnce(S::Response) -> Response + Clone + Send + Sync + 'static,
81    State: Clone + Send + Sync + 'static,
82    Request: Send + 'static,
83    Response: Send + 'static,
84{
85    type Response = Response;
86    type Error = S::Error;
87
88    async fn serve(
89        &self,
90        ctx: Context<State>,
91        req: Request,
92    ) -> Result<Self::Response, Self::Error> {
93        match self.inner.serve(ctx, req).await {
94            Ok(resp) => Ok((self.f.clone())(resp)),
95            Err(err) => Err(err),
96        }
97    }
98}
99
100impl<F> MapResponseLayer<F> {
101    /// Creates a new [`MapResponseLayer`] layer.
102    pub const fn new(f: F) -> Self {
103        MapResponseLayer { f }
104    }
105}
106
107impl<S, F> Layer<S> for MapResponseLayer<F>
108where
109    F: Clone,
110{
111    type Service = MapResponse<S, F>;
112
113    fn layer(&self, inner: S) -> Self::Service {
114        MapResponse {
115            f: self.f.clone(),
116            inner,
117        }
118    }
119
120    fn into_layer(self, inner: S) -> Self::Service {
121        MapResponse { f: self.f, inner }
122    }
123}