axum/
boxed.rs

1use std::{convert::Infallible, fmt};
2
3use crate::extract::Request;
4use tower::Service;
5
6use crate::{
7    handler::Handler,
8    routing::{future::RouteFuture, Route},
9    Router,
10};
11
12pub(crate) struct BoxedIntoRoute<S, E>(Box<dyn ErasedIntoRoute<S, E>>);
13
14impl<S> BoxedIntoRoute<S, Infallible>
15where
16    S: Clone + Send + Sync + 'static,
17{
18    pub(crate) fn from_handler<H, T>(handler: H) -> Self
19    where
20        H: Handler<T, S>,
21        T: 'static,
22    {
23        Self(Box::new(MakeErasedHandler {
24            handler,
25            into_route: |handler, state| Route::new(Handler::with_state(handler, state)),
26        }))
27    }
28}
29
30impl<S, E> BoxedIntoRoute<S, E> {
31    pub(crate) fn map<F, E2>(self, f: F) -> BoxedIntoRoute<S, E2>
32    where
33        S: 'static,
34        E: 'static,
35        F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + Sync + 'static,
36        E2: 'static,
37    {
38        BoxedIntoRoute(Box::new(Map {
39            inner: self.0,
40            layer: Box::new(f),
41        }))
42    }
43
44    pub(crate) fn into_route(self, state: S) -> Route<E> {
45        self.0.into_route(state)
46    }
47}
48
49impl<S, E> Clone for BoxedIntoRoute<S, E> {
50    fn clone(&self) -> Self {
51        Self(self.0.clone_box())
52    }
53}
54
55impl<S, E> fmt::Debug for BoxedIntoRoute<S, E> {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        f.debug_tuple("BoxedIntoRoute").finish()
58    }
59}
60
61pub(crate) trait ErasedIntoRoute<S, E>: Send + Sync {
62    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E>>;
63
64    fn into_route(self: Box<Self>, state: S) -> Route<E>;
65
66    #[allow(dead_code)]
67    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E>;
68}
69
70pub(crate) struct MakeErasedHandler<H, S> {
71    pub(crate) handler: H,
72    pub(crate) into_route: fn(H, S) -> Route,
73}
74
75impl<H, S> ErasedIntoRoute<S, Infallible> for MakeErasedHandler<H, S>
76where
77    H: Clone + Send + Sync + 'static,
78    S: 'static,
79{
80    fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
81        Box::new(self.clone())
82    }
83
84    fn into_route(self: Box<Self>, state: S) -> Route {
85        (self.into_route)(self.handler, state)
86    }
87
88    fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
89        self.into_route(state).call(request)
90    }
91}
92
93impl<H, S> Clone for MakeErasedHandler<H, S>
94where
95    H: Clone,
96{
97    fn clone(&self) -> Self {
98        Self {
99            handler: self.handler.clone(),
100            into_route: self.into_route,
101        }
102    }
103}
104
105#[allow(dead_code)]
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 + Sync {
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 + Sync + 'static,
174{
175    fn clone_box(&self) -> Box<dyn LayerFn<E, E2>> {
176        Box::new(self.clone())
177    }
178}