blueprint_core/extract/
tuple.rs1use super::{FromJobCall, FromJobCallParts, JobCall};
2use crate::JobResult;
3use crate::job::call::Parts;
4use crate::job::result::IntoJobResult;
5use core::convert::Infallible;
6
7impl<Ctx> FromJobCallParts<Ctx> for ()
8where
9 Ctx: Send + Sync,
10{
11 type Rejection = Infallible;
12
13 async fn from_job_call_parts(_: &mut Parts, _: &Ctx) -> Result<(), Self::Rejection> {
14 Ok(())
15 }
16}
17
18macro_rules! impl_from_job_call {
19 (
20 [$($ty:ident),*], $last:ident
21 ) => {
22 #[allow(non_snake_case, unused_mut, unused_variables)]
23 impl<Ctx, $($ty,)* $last> FromJobCallParts<Ctx> for ($($ty,)* $last,)
24 where
25 $( $ty: FromJobCallParts<Ctx> + Send, )*
26 $last: FromJobCallParts<Ctx> + Send,
27 Ctx: Send + Sync,
28 {
29 type Rejection = Option<JobResult>;
30
31 async fn from_job_call_parts(parts: &mut Parts, ctx: &Ctx) -> Result<Self, Self::Rejection> {
32 $(
33 let $ty = $ty::from_job_call_parts(parts, ctx)
34 .await
35 .map_err(|err| err.into_job_result())?;
36 )*
37 let $last = $last::from_job_call_parts(parts, ctx)
38 .await
39 .map_err(|err| err.into_job_result())?;
40
41 Ok(($($ty,)* $last,))
42 }
43 }
44
45 #[allow(non_snake_case, unused_mut, unused_variables)]
48 impl<Ctx, $($ty,)* $last> FromJobCall<Ctx> for ($($ty,)* $last,)
49 where
50 $( $ty: FromJobCallParts<Ctx> + Send, )*
51 $last: FromJobCall<Ctx> + Send,
52 Ctx: Send + Sync,
53 {
54 type Rejection = Option<JobResult>;
55
56 async fn from_job_call(call: JobCall, ctx: &Ctx) -> Result<Self, Self::Rejection> {
57 let (mut parts, body) = call.into_parts();
58
59 $(
60 let $ty = $ty::from_job_call_parts(&mut parts, ctx).await.map_err(|err| err.into_job_result())?;
61 )*
62
63 let call = JobCall::from_parts(parts, body);
64
65 let $last = $last::from_job_call(call, ctx).await.map_err(|err| err.into_job_result())?;
66
67 Ok(($($ty,)* $last,))
68 }
69 }
70 };
71}
72
73all_the_tuples!(impl_from_job_call);
74
75#[cfg(test)]
76mod tests {
77 use bytes::Bytes;
78
79 use crate::extract::{FromJobCall, FromJobCallParts};
80 use crate::job::call::Parts as JobCallParts;
81
82 struct JobId;
83
84 impl<Ctx: Sync> FromJobCallParts<Ctx> for JobId {
85 type Rejection = ();
86 async fn from_job_call_parts(
87 _: &mut JobCallParts,
88 _: &Ctx,
89 ) -> Result<Self, Self::Rejection> {
90 Ok(Self)
91 }
92 }
93
94 fn assert_from_job_call<M, T>()
95 where
96 T: FromJobCall<(), M>,
97 {
98 }
99
100 fn assert_from_job_call_parts<T: FromJobCallParts<()>>() {}
101
102 #[test]
103 fn unit() {
104 assert_from_job_call_parts::<()>();
105 assert_from_job_call::<_, ()>();
106 }
107
108 #[test]
109 fn tuple_of_one() {
110 assert_from_job_call_parts::<(JobId,)>();
111 assert_from_job_call::<_, (JobId,)>();
112 assert_from_job_call::<_, (Bytes,)>();
113 }
114
115 #[test]
116 fn tuple_of_two() {
117 assert_from_job_call_parts::<((), ())>();
118 assert_from_job_call::<_, ((), ())>();
119 assert_from_job_call::<_, (JobId, Bytes)>();
120 }
121
122 #[test]
123 fn nested_tuple() {
124 assert_from_job_call_parts::<(((JobId,),),)>();
125 assert_from_job_call::<_, ((((Bytes,),),),)>();
126 }
127}