1use core::future::Future;
2use core::marker::PhantomData;
3use poem::Request;
4use poem::web::headers::Header;
5use poem::web::{FromRequest, Json, Path, Query, RequestBody, TypedHeader};
6use serde::de::DeserializeOwned;
7
8pub struct PoemPathInput<Input>(PhantomData<Input>);
10pub struct PoemQueryInput<Input>(PhantomData<Input>);
12pub struct PoemBodyInput<Input>(PhantomData<Input>);
14pub struct PoemHeaderInput<Input>(PhantomData<Input>);
16pub struct PoemRequestInput<Input>(PhantomData<Input>);
18
19pub(crate) trait PoemInputAlg<Output> {
20 fn extract(request: &Request, body: &mut RequestBody) -> impl Future<Output = poem::Result<Output>> + Send;
21}
22
23macro_rules! poem_input {
24 ($marker:ident, $extractor:ident) => {
25 impl<Input> PoemInputAlg<Input> for $marker<Input>
26 where
27 Input: DeserializeOwned + Send,
28 {
29 async fn extract(request: &Request, body: &mut RequestBody) -> poem::Result<Input> {
30 Ok($extractor::<Input>::from_request(request, body).await?.0)
31 }
32 }
33 };
34}
35
36poem_input!(PoemPathInput, Path);
37poem_input!(PoemQueryInput, Query);
38poem_input!(PoemBodyInput, Json);
39
40impl<Input> PoemInputAlg<Input> for PoemHeaderInput<Input>
41where
42 Input: Header + Send,
43{
44 async fn extract(request: &Request, body: &mut RequestBody) -> poem::Result<Input> {
45 Ok(TypedHeader::<Input>::from_request(request, body).await?.0)
46 }
47}
48
49impl<Input> PoemInputAlg<Input> for PoemRequestInput<Input>
50where
51 Input: for<'a> FromRequest<'a> + Send,
52{
53 fn extract(request: &Request, body: &mut RequestBody) -> impl Future<Output = poem::Result<Input>> + Send {
54 Input::from_request(request, body)
55 }
56}
57
58pub(crate) trait PoemInputsAlg<Outputs> {
59 fn extract(request: &Request, body: &mut RequestBody) -> impl Future<Output = poem::Result<Outputs>> + Send;
60}
61
62impl PoemInputsAlg<()> for () {
63 async fn extract(_request: &Request, _body: &mut RequestBody) -> poem::Result<()> {
64 Ok(())
65 }
66}
67
68macro_rules! poem_inputs {
69 ($($input:ident => $output:ident),+ $(,)?) => {
70 impl<$($input, $output),+> PoemInputsAlg<($($output,)+)> for ($($input,)+)
71 where
72 $($input: PoemInputAlg<$output>, $output: Send,)+
73 {
74 async fn extract(request: &Request, body: &mut RequestBody) -> poem::Result<($($output,)+)> {
75 Ok(($($input::extract(request, body).await?,)+))
76 }
77 }
78 };
79}
80
81poem_inputs!(I1 => O1);
82poem_inputs!(I1 => O1, I2 => O2);
83poem_inputs!(I1 => O1, I2 => O2, I3 => O3);
84poem_inputs!(I1 => O1, I2 => O2, I3 => O3, I4 => O4);
85poem_inputs!(I1 => O1, I2 => O2, I3 => O3, I4 => O4, I5 => O5);
86poem_inputs!(I1 => O1, I2 => O2, I3 => O3, I4 => O4, I5 => O5, I6 => O6);
87poem_inputs!(I1 => O1, I2 => O2, I3 => O3, I4 => O4, I5 => O5, I6 => O6, I7 => O7);
88poem_inputs!(I1 => O1, I2 => O2, I3 => O3, I4 => O4, I5 => O5, I6 => O6, I7 => O7, I8 => O8);