validator/validation/
nested.rs

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}