1use crate::{Validate, ValidateFrom};
4
5#[cfg(feature = "async")]
6use crate::{Resolve, ResolveFrom};
7
8macro_rules! valid_for_tuple {
9 ($T1:ty) => {};
10 ($T1:ident, $($T:ident),+) => {
11 valid_for_tuple!(@inner $T1, $($T),+);
12 valid_for_tuple!($($T),+);
13 };
14 (@inner $($T:ident),+) => {
15 #[allow(non_snake_case)]
16 impl<Ctx: ?Sized, Err, $($T: Validate<Context = Ctx, Error = Err>),+> Validate for ($($T),+) {
17 type Context = Ctx;
18 type Output = ($(<$T as Validate>::Output),+);
19 type Error = Err;
20
21 fn validate_in_context(self, ctx: &Self::Context) -> Result<Self::Output, Self::Error> {
22 let ($($T),+) = self;
23
24 Ok(($($T.validate_in_context(ctx)?),+))
25 }
26 }
27 };
28}
29
30macro_rules! valid_from_for_tuple {
31 ($T1:ident $R1:ident) => {};
32 ($T1:ident $R1:ident, $($T:ident $R:ident),+) => {
33 valid_from_for_tuple!(@inner $T1 $R1, $($T $R),+);
34 valid_from_for_tuple!($($T $R),+);
35 };
36 (@inner $($T:ident $R:ident),+) => {
37 #[allow(non_snake_case)]
38 impl<Ctx: ?Sized, Err, $($T,)+ $($R,)+> ValidateFrom<($($R),+)> for ($($T),+)
39 where
40 $($T: ValidateFrom<$R, Context = Ctx, Error = Err>,)+
41 {
42 type Context = Ctx;
43 type Error = Err;
44
45 fn validate_from_in_context(
46 raw: ($($R),+),
47 ctx: &Self::Context,
48 ) -> Result<Self, Self::Error> {
49 let ($($R,)+) = raw;
50
51 Ok(($($T::validate_from_in_context($R, ctx)?),+))
52 }
53 }
54 };
55}
56
57#[cfg(feature = "async")]
58macro_rules! resolve_for_tuple {
59 ($T1:ty) => {};
60 ($T1:ident, $($T:ident),+) => {
61 resolve_for_tuple!(@inner $T1, $($T),+);
62 resolve_for_tuple!($($T),+);
63 };
64 (@inner $($T:ident),+) => {
65 #[allow(non_snake_case)]
66 impl<Ctx: ?Sized, Err, $($T: Resolve<Context = Ctx, Error = Err>),+> Resolve for ($($T),+) {
67 type Context = Ctx;
68 type Output = ($(<$T as Resolve>::Output),+);
69 type Error = Err;
70
71 async fn resolve_in_context(
72 self,
73 ctx: &Self::Context,
74 ) -> Result<Self::Output, Self::Error> {
75 let ($($T),+) = self;
76
77 Ok(($($T.resolve_in_context(ctx).await?),+))
78 }
79 }
80 };
81}
82
83#[cfg(feature = "async")]
84macro_rules! resolve_from_for_tuple {
85 ($T1:ident $R1:ident) => {};
86 ($T1:ident $R1:ident, $($T:ident $R:ident),+) => {
87 resolve_from_for_tuple!(@inner $T1 $R1, $($T $R),+);
88 resolve_from_for_tuple!($($T $R),+);
89 };
90 (@inner $($T:ident $R:ident),+) => {
91 #[allow(non_snake_case)]
92 impl<Ctx: ?Sized, Err, $($T,)+ $($R,)+> ResolveFrom<($($R),+)> for ($($T),+)
93 where
94 $($T: ResolveFrom<$R, Context = Ctx, Error = Err>,)+
95 {
96 type Context = Ctx;
97 type Error = Err;
98
99 async fn resolve_from_in_context(
100 raw: ($($R),+),
101 ctx: &Self::Context,
102 ) -> Result<Self, Self::Error> {
103 let ($($R,)+) = raw;
104
105 Ok(($($T::resolve_from_in_context($R, ctx).await?),+))
106 }
107 }
108 };
109}
110
111valid_for_tuple!(
113 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
114);
115
116valid_from_for_tuple!(
117 A RA, B RB, C RC, D RD, E RE, F RF, G RG, H RH, I RI, J RJ, K RK, L RL, M RM,
118 N RN, O RO, P RP, Q RQ, R RR, S RS, T RT, U RU, V RV, W RW, X RX, Y RY, Z RZ
119);
120
121#[cfg(feature = "async")]
122resolve_for_tuple!(
123 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
124);
125
126#[cfg(feature = "async")]
127resolve_from_for_tuple!(
128 A RA, B RB, C RC, D RD, E RE, F RF, G RG, H RH, I RI, J RJ, K RK, L RL, M RM,
129 N RN, O RO, P RP, Q RQ, R RR, S RS, T RT, U RU, V RV, W RW, X RX, Y RY, Z RZ
130);