1use crate::{ValidateArgs, ValidationErrors, ValidationErrorsKind};
2use std::collections::{BTreeMap, HashMap, HashSet};
3pub trait ValidateNested<'v_a> {
4 type Args;
5 fn validate_nested(
6 &self,
7 field_name: &'static str,
8 args: Self::Args,
9 ) -> Result<(), ValidationErrors>;
10}
11
12impl<'v_a, T, U> ValidateNested<'v_a> for &T
13where
14 T: ValidateNested<'v_a, Args = U>,
15{
16 type Args = U;
17
18 fn validate_nested(
19 &self,
20 field_name: &'static str,
21 args: Self::Args,
22 ) -> Result<(), ValidationErrors> {
23 T::validate_nested(self, field_name, args)
24 }
25}
26
27impl<'v_a, T, U> ValidateNested<'v_a> for Option<T>
28where
29 T: ValidateNested<'v_a, Args = U>,
30{
31 type Args = U;
32
33 fn validate_nested(
34 &self,
35 field_name: &'static str,
36 args: Self::Args,
37 ) -> Result<(), ValidationErrors> {
38 if let Some(nested) = self {
39 nested.validate_nested(field_name, args)
40 } else {
41 Ok(())
42 }
43 }
44}
45
46impl<'v_a, T, U> ValidateNested<'v_a> for Vec<T>
47where
48 T: ValidateArgs<'v_a, Args = U> + ValidateNested<'v_a, Args = U>,
49 U: Clone,
50{
51 type Args = U;
52 fn validate_nested(
53 &self,
54 field_name: &'static str,
55 args: Self::Args,
56 ) -> Result<(), ValidationErrors> {
57 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
58
59 for (index, item) in self.iter().enumerate() {
60 if let Err(e) = item.validate_with_args(args.clone()) {
61 vec_err.insert(index, Box::new(e));
62 }
63 }
64
65 let err_kind = ValidationErrorsKind::List(vec_err);
66 let errors = ValidationErrors(HashMap::from([(field_name, err_kind)]));
67
68 if errors.is_empty() {
69 Ok(())
70 } else {
71 Err(errors)
72 }
73 }
74}
75
76impl<'v_a, T, U> ValidateNested<'v_a> for &[T]
77where
78 T: ValidateArgs<'v_a, Args = U> + ValidateNested<'v_a, Args = U>,
79 U: Clone,
80{
81 type Args = U;
82
83 fn validate_nested(
84 &self,
85 field_name: &'static str,
86 args: Self::Args,
87 ) -> Result<(), ValidationErrors> {
88 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
89
90 for (index, item) in self.iter().enumerate() {
91 if let Err(e) = item.validate_with_args(args.clone()) {
92 vec_err.insert(index, Box::new(e));
93 }
94 }
95
96 let err_kind = ValidationErrorsKind::List(vec_err);
97 let errors = ValidationErrors(HashMap::from([(field_name, err_kind)]));
98
99 if errors.is_empty() {
100 Ok(())
101 } else {
102 Err(errors)
103 }
104 }
105}
106
107impl<'v_a, T, const N: usize, U> ValidateNested<'v_a> for [T; N]
108where
109 T: ValidateArgs<'v_a, Args = U> + ValidateNested<'v_a, Args = U>,
110 U: Clone,
111{
112 type Args = U;
113 fn validate_nested(
114 &self,
115 field_name: &'static str,
116 args: Self::Args,
117 ) -> Result<(), ValidationErrors> {
118 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
119
120 for (index, item) in self.iter().enumerate() {
121 if let Err(e) = item.validate_with_args(args.clone()) {
122 vec_err.insert(index, Box::new(e));
123 }
124 }
125
126 let err_kind = ValidationErrorsKind::List(vec_err);
127 let errors = ValidationErrors(HashMap::from([(field_name, err_kind)]));
128
129 if errors.is_empty() {
130 Ok(())
131 } else {
132 Err(errors)
133 }
134 }
135}
136
137impl<'v_a, K, V, S, U> ValidateNested<'v_a> for HashMap<K, V, S>
138where
139 V: ValidateArgs<'v_a, Args = U> + ValidateNested<'v_a, Args = U>,
140 U: Clone,
141{
142 type Args = U;
143 fn validate_nested(
144 &self,
145 field_name: &'static str,
146 args: Self::Args,
147 ) -> Result<(), ValidationErrors> {
148 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
149
150 for (index, (_key, value)) in self.iter().enumerate() {
151 if let Err(e) = value.validate_with_args(args.clone()) {
152 vec_err.insert(index, Box::new(e));
153 }
154 }
155
156 let err_kind = ValidationErrorsKind::List(vec_err);
157 let errors = ValidationErrors(HashMap::from([(field_name, err_kind)]));
158
159 if errors.is_empty() {
160 Ok(())
161 } else {
162 Err(errors)
163 }
164 }
165}
166
167impl<'v_a, T, S, U> ValidateNested<'v_a> for HashSet<T, S>
168where
169 T: ValidateArgs<'v_a, Args = U> + ValidateNested<'v_a, Args = U>,
170 U: Clone,
171{
172 type Args = U;
173 fn validate_nested(
174 &self,
175 field_name: &'static str,
176 args: Self::Args,
177 ) -> Result<(), ValidationErrors> {
178 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
179
180 for (index, value) in self.iter().enumerate() {
181 if let Err(e) = value.validate_with_args(args.clone()) {
182 vec_err.insert(index, Box::new(e));
183 }
184 }
185
186 let err_kind = ValidationErrorsKind::List(vec_err);
187 let errors = ValidationErrors(HashMap::from([(field_name, err_kind)]));
188
189 if errors.is_empty() {
190 Ok(())
191 } else {
192 Err(errors)
193 }
194 }
195}