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
106#[allow(dead_code)]
107pub(crate) struct MakeErasedRouter<S> {
108    pub(crate) router: Router<S>,
109    pub(crate) into_route: fn(Router<S>, S) -> Route,
110}
111
112impl<S> ErasedIntoRoute<S, Infallible> for MakeErasedRouter<S>
113where
114    S: Clone + Send + Sync + 'static,
115{
116    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
117        Box::new(self.clone())
118    }
119
120    fn into_route(self: Box<Self>, state: S) -> Route {
121        (self.into_route)(self.router, state)
122    }
123
124    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
125        self.router.call_with_state(request, state)
126    }
127}
128
129impl<S> Clone for MakeErasedRouter<S>
130where
131    S: Clone,
132{
133    fn clone(&self) -> Self {
134        Self {
135            router: self.router.clone(),
136            into_route: self.into_route,
137        }
138    }
139}
140
141pub(crate) struct Map<S, E, E2> {
142    pub(crate) inner: Box<dyn ErasedIntoRoute<S, E>>,
143    pub(crate) layer: Box<dyn LayerFn<E, E2>>,
144}
145
146impl<S, E, E2> ErasedIntoRoute<S, E2> for Map<S, E, E2>
147where
148    S: 'static,
149    E: 'static,
150    E2: 'static,
151{
152    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E2>> {
153        Box::new(Self {
154            inner: self.inner.clone_box(),
155            layer: self.layer.clone_box(),
156        })
157    }
158
159    fn into_route(self: Box<Self>, state: S) -> Route<E2> {
160        (self.layer)(self.inner.into_route(state))
161    }
162
163    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E2> {
164        (self.layer)(self.inner.into_route(state)).call(request)
165    }
166}
167
168pub(crate) trait LayerFn<E, E2>: FnOnce(Route<E>) -> Route<E2> + Send {
169    fn clone_box(&self) -> Box<dyn LayerFn<E, E2>>;
170}
171
172impl<F, E, E2> LayerFn<E, E2> for F
173where
174    F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + 'static,
175{
176    fn clone_box(&self) -> Box<dyn LayerFn<E, E2>> {
177        Box::new(self.clone())
178    }
179}