Skip to main content

peer_pressure/
tuple.rs

1//! [Validate] and [Resolve] implementations for tuples.
2
3use 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
111// 26-tuple max should be reasonable, right?
112valid_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);