@@ -51,6 +51,7 @@ use crate::{
51
51
response:: { IntoResponse , Response } ,
52
52
routing:: IntoMakeService ,
53
53
} ;
54
+ use axum_core:: extract:: FromStatelessRequestParts ;
54
55
use std:: { convert:: Infallible , fmt, future:: Future , marker:: PhantomData , pin:: Pin } ;
55
56
use tower:: ServiceExt ;
56
57
use tower_layer:: Layer ;
@@ -203,6 +204,113 @@ where
203
204
}
204
205
}
205
206
207
+ struct AutoDerefSpecialization < T > ( PhantomData < fn ( ) -> * const T > ) ;
208
+
209
+ impl < T > AutoDerefSpecialization < T > {
210
+ fn new ( ) -> Self {
211
+ Self ( PhantomData )
212
+ }
213
+ }
214
+
215
+ trait ViaRequestParts < S > {
216
+ type SelfT ;
217
+ type Rejection ;
218
+
219
+ async fn extract (
220
+ self ,
221
+ req : & mut http:: request:: Parts ,
222
+ state : & S ,
223
+ ) -> Result < Self :: SelfT , Self :: Rejection > ;
224
+ }
225
+
226
+ trait ViaStatelessRequestParts < S > {
227
+ type SelfT ;
228
+ type Rejection ;
229
+
230
+ async fn extract (
231
+ self ,
232
+ req : & mut http:: request:: Parts ,
233
+ state : & S ,
234
+ ) -> Result < Self :: SelfT , Self :: Rejection > ;
235
+ }
236
+
237
+ trait ViaPanic < S > {
238
+ type SelfT ;
239
+ type Rejection ;
240
+
241
+ async fn extract (
242
+ self ,
243
+ req : & mut http:: request:: Parts ,
244
+ state : & S ,
245
+ ) -> Result < Self :: SelfT , Self :: Rejection > ;
246
+ }
247
+
248
+ impl < T , S > ViaRequestParts < S > for & & AutoDerefSpecialization < T >
249
+ where
250
+ T : FromRequestParts < S > ,
251
+ {
252
+ type SelfT = T ;
253
+ type Rejection = T :: Rejection ;
254
+
255
+ async fn extract (
256
+ self ,
257
+ req : & mut http:: request:: Parts ,
258
+ state : & S ,
259
+ ) -> Result < Self :: SelfT , Self :: Rejection > {
260
+ T :: from_request_parts ( req, state) . await
261
+ }
262
+ }
263
+
264
+ impl < T , S > ViaStatelessRequestParts < S > for & & & AutoDerefSpecialization < T >
265
+ where
266
+ T : FromStatelessRequestParts ,
267
+ {
268
+ type SelfT = T ;
269
+ type Rejection = T :: Rejection ;
270
+
271
+ async fn extract (
272
+ self ,
273
+ req : & mut http:: request:: Parts ,
274
+ _state : & S ,
275
+ ) -> Result < Self :: SelfT , Self :: Rejection > {
276
+ T :: from_request_parts ( req) . await
277
+ }
278
+ }
279
+
280
+ impl < T , S > ViaPanic < S > for & AutoDerefSpecialization < T > {
281
+ type SelfT = T ;
282
+ type Rejection = ( ) ;
283
+
284
+ async fn extract (
285
+ self ,
286
+ _req : & mut http:: request:: Parts ,
287
+ _state : & S ,
288
+ ) -> Result < Self :: SelfT , Self :: Rejection > {
289
+ panic ! ( ) ;
290
+ }
291
+ }
292
+
293
+ struct Foo ;
294
+
295
+ impl FromStatelessRequestParts for Foo {
296
+ type Rejection = ( ) ;
297
+
298
+ fn from_request_parts (
299
+ _parts : & mut http:: request:: Parts ,
300
+ ) -> impl Future < Output = Result < Self , Self :: Rejection > > + Send {
301
+ std:: future:: ready ( Ok ( Foo ) )
302
+ }
303
+ }
304
+
305
+ #[ test]
306
+ fn foo ( ) {
307
+ let req = todo ! ( ) ;
308
+ ( & & AutoDerefSpecialization :: < Foo > :: new ( ) ) . extract ( req, & ( ) ) ;
309
+ }
310
+
311
+ trait Something < S , V > { }
312
+ impl < T , S , V > Something < S , V > for T where T : FromRequestParts < S , V > { }
313
+
206
314
macro_rules! impl_handler {
207
315
(
208
316
[ $( $ty: ident) ,* ] , $last: ident
@@ -214,7 +322,7 @@ macro_rules! impl_handler {
214
322
Fut : Future <Output = Res > + Send ,
215
323
S : Send + Sync + ' static ,
216
324
Res : IntoResponse ,
217
- $( $ty: FromRequestParts < S > + Send , ) *
325
+ $( $ty: Send , ) *
218
326
$last: FromRequest <S , M > + Send ,
219
327
{
220
328
type Future = Pin <Box <dyn Future <Output = Response > + Send >>;
@@ -223,7 +331,7 @@ macro_rules! impl_handler {
223
331
let ( mut parts, body) = req. into_parts( ) ;
224
332
Box :: pin( async move {
225
333
$(
226
- let $ty = match $ty:: from_request_parts ( & mut parts, & state) . await {
334
+ let $ty = match ( && & AutoDerefSpecialization :: < $ty> :: new ( ) ) . extract ( & mut parts, & state) . await {
227
335
Ok ( value) => value,
228
336
Err ( rejection) => return rejection. into_response( ) ,
229
337
} ;
0 commit comments