1use serde_json::Value;
2
3use crate::error::{value_type_name, IssueCode, PathSegment, VldError};
4use crate::schema::VldSchema;
5
6macro_rules! impl_tuple_schema {
7 ($count:expr; $(($idx:tt, $T:ident, $v:ident)),+) => {
8 impl<$($T: VldSchema),+> VldSchema for ($($T,)+) {
9 type Output = ($($T::Output,)+);
10
11 fn parse_value(&self, value: &Value) -> Result<Self::Output, VldError> {
12 let arr = value.as_array().ok_or_else(|| {
13 VldError::single(
14 IssueCode::InvalidType {
15 expected: "array".to_string(),
16 received: value_type_name(value),
17 },
18 format!("Expected array (tuple), received {}", value_type_name(value)),
19 )
20 })?;
21
22 if arr.len() != $count {
23 return Err(VldError::single(
24 IssueCode::Custom { code: "invalid_tuple_length".to_string() },
25 format!("Expected tuple of {} elements, received {}", $count, arr.len()),
26 ));
27 }
28
29 let mut __errors = VldError::new();
30
31 $(
32 let $v = match self.$idx.parse_value(&arr[$idx]) {
33 Ok(v) => Some(v),
34 Err(e) => {
35 __errors = __errors.merge(e.with_prefix(PathSegment::Index($idx)));
36 None
37 }
38 };
39 )+
40
41 if !__errors.is_empty() {
42 return Err(__errors);
43 }
44
45 Ok(($($v.unwrap(),)+))
46 }
47 }
48 };
49}
50
51impl_tuple_schema!(1; (0, A, _a));
52impl_tuple_schema!(2; (0, A, _a), (1, B, _b));
53impl_tuple_schema!(3; (0, A, _a), (1, B, _b), (2, C, _c));
54impl_tuple_schema!(4; (0, A, _a), (1, B, _b), (2, C, _c), (3, D, _d));
55impl_tuple_schema!(5; (0, A, _a), (1, B, _b), (2, C, _c), (3, D, _d), (4, E, _e));
56impl_tuple_schema!(6; (0, A, _a), (1, B, _b), (2, C, _c), (3, D, _d), (4, E, _e), (5, F, _f));