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