axum/
boxed.rs

1use std::{convert::Infallible, fmt};
2
3use crate::extract::Request;
4use crate::util::AxumMutex;
5use tower::Service;
6
7use crate::{
8    handler::Handler,
9    routing::{future::RouteFuture, Route},
10    Router,
11};
12
13pub(crate) struct BoxedIntoRoute<S, E>(AxumMutex<Box<dyn ErasedIntoRoute<S, E>>>);
14
15impl<S> BoxedIntoRoute<S, Infallible>
16where
17    S: Clone + Send + Sync + 'static,
18{
19    pub(crate) fn from_handler<H, T>(handler: H) -> Self
20    where
21        H: Handler<T, S>,
22        T: 'static,
23    {
24        Self(AxumMutex::new(Box::new(MakeErasedHandler {
25            handler,
26            into_route: |handler, state| Route::new(Handler::with_state(handler, state)),
27        })))
28    }
29}
30
31impl<S, E> BoxedIntoRoute<S, E> {
32    pub(crate) fn map<F, E2>(self, f: F) -> BoxedIntoRoute<S, E2>
33    where
34        S: 'static,
35        E: 'static,
36        F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + 'static,
37        E2: 'static,
38    {
39        BoxedIntoRoute(AxumMutex::new(Box::new(Map {
40            inner: self.0.into_inner().unwrap(),
41            layer: Box::new(f),
42        })))
43    }
44
45    pub(crate) fn into_route(self, state: S) -> Route<E> {
46        self.0.into_inner().unwrap().into_route(state)
47    }
48}
49
50impl<S, E> Clone for BoxedIntoRoute<S, E> {
51    fn clone(&self) -> Self {
52        Self(AxumMutex::new(self.0.lock().unwrap().clone_box()))
53    }
54}
55
56impl<S, E> fmt::Debug for BoxedIntoRoute<S, E> {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        f.debug_tuple("BoxedIntoRoute").finish()
59    }
60}
61
62pub(crate) trait ErasedIntoRoute<S, E>: Send {
63    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E>>;
64
65    fn into_route(self: Box<Self>, state: S) -> Route<E>;
66
67    #[allow(dead_code)]
68    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E>;
69}
70
71pub(crate) struct MakeErasedHandler<H, S> {
72    pub(crate) handler: H,
73    pub(crate) into_route: fn(H, S) -> Route,
74}
75
76impl<H, S> ErasedIntoRoute<S, Infallible> for MakeErasedHandler<H, S>
77where
78    H: Clone + Send + 'static,
79    S: 'static,
80{
81    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
82        Box::new(self.clone())
83    }
84
85    fn into_route(self: Box<Self>, state: S) -> Route {
86        (self.into_route)(self.handler, state)
87    }
88
89    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
90        self.into_route(state).call(request)
91    }
92}
93
94impl<H, S> Clone for MakeErasedHandler<H, S>
95where
96    H: Clone,
97{
98    fn clone(&self) -> Self {
99        Self {
100            handler: self.handler.clone(),
101            into_route: self.into_route,
102        }
103    }
104}
105
106pub(crate) struct MakeErasedRouter<S> {
107    pub(crate) router: Router<S>,
108    pub(crate) into_route: fn(Router<S>, S) -> Route,
109}
110
111impl<S> ErasedIntoRoute<S, Infallible> for MakeErasedRouter<S>
112where
113    S: Clone + Send + Sync + 'static,
114{
115    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
116        Box::new(self.clone())
117    }
118
119    fn into_route(self: Box<Self>, state: S) -> Route {
120        (self.into_route)(self.router, state)
121    }
122
123    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
124        self.router.call_with_state(request, state)
125    }
126}
127
128impl<S> Clone for MakeErasedRouter<S>
129where
130    S: Clone,
131{
132    fn clone(&self) -> Self {
133        Self {
134            router: self.router.clone(),
135            into_route: self.into_route,
136        }
137    }
138}
139
140pub(crate) struct Map<S, E, E2> {
141    pub(crate) inner: Box<dyn ErasedIntoRoute<S, E>>,
142    pub(crate) layer: Box<dyn LayerFn<E, E2>>,
143}
144
145impl<S, E, E2> ErasedIntoRoute<S, E2> for Map<S, E, E2>
146where
147    S: 'static,
148    E: 'static,
149    E2: 'static,
150{
151    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E2>> {
152        Box::new(Self {
153            inner: self.inner.clone_box(),
154            layer: self.layer.clone_box(),
155        })
156    }
157
158    fn into_route(self: Box<Self>, state: S) -> Route<E2> {
159        (self.layer)(self.inner.into_route(state))
160    }
161
162    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E2> {
163        (self.layer)(self.inner.into_route(state)).call(request)
164    }
165}
166
167pub(crate) trait LayerFn<E, E2>: FnOnce(Route<E>) -> Route<E2> + Send {
168    fn clone_box(&self) -> Box<dyn LayerFn<E, E2>>;
169}
170
171impl<F, E, E2> LayerFn<E, E2> for F
172where
173    F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + 'static,
174{
175    fn clone_box(&self) -> Box<dyn LayerFn<E, E2>> {
176        Box::new(self.clone())
177    }
178}