1use crate::types::{ValidationErrors, ValidationErrorsKind};
2use std::borrow::Cow;
3use std::collections::btree_map::BTreeMap;
4use std::collections::HashMap;
5
6pub trait Validate {
10 fn validate(&self) -> Result<(), ValidationErrors>;
11}
12
13impl<T: Validate> Validate for &T {
14 fn validate(&self) -> Result<(), ValidationErrors> {
15 T::validate(self)
16 }
17}
18
19macro_rules! impl_validate_list {
20 ($container:ty) => {
21 impl<T: Validate> Validate for $container {
22 fn validate(&self) -> Result<(), ValidationErrors> {
23 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
24
25 for (index, item) in self.iter().enumerate() {
26 if let Err(e) = item.validate() {
27 vec_err.insert(index, Box::new(e));
28 }
29 }
30
31 if vec_err.is_empty() {
32 Ok(())
33 } else {
34 let err_kind = ValidationErrorsKind::List(vec_err);
35 let errors = ValidationErrors(std::collections::HashMap::from([(
36 Cow::Borrowed("_tmp_validator"),
37 err_kind,
38 )]));
39 Err(errors)
40 }
41 }
42 }
43 };
44}
45
46impl_validate_list!(std::collections::HashSet<T>);
47impl_validate_list!(std::collections::BTreeSet<T>);
48impl_validate_list!(std::collections::BinaryHeap<T>);
49impl_validate_list!(std::collections::LinkedList<T>);
50impl_validate_list!(std::collections::VecDeque<T>);
51impl_validate_list!(std::vec::Vec<T>);
52impl_validate_list!([T]);
53
54impl<T: Validate, const N: usize> Validate for [T; N] {
55 fn validate(&self) -> Result<(), ValidationErrors> {
56 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
57
58 for (index, item) in self.iter().enumerate() {
59 if let Err(e) = item.validate() {
60 vec_err.insert(index, Box::new(e));
61 }
62 }
63
64 if vec_err.is_empty() {
65 Ok(())
66 } else {
67 let err_kind = ValidationErrorsKind::List(vec_err);
68 let errors = ValidationErrors(std::collections::HashMap::from([(
69 Cow::Borrowed("_tmp_validator"),
70 err_kind,
71 )]));
72 Err(errors)
73 }
74 }
75}
76
77impl<K, V: Validate, S> Validate for &HashMap<K, V, S> {
78 fn validate(&self) -> Result<(), ValidationErrors> {
79 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
80
81 for (index, (_key, value)) in self.iter().enumerate() {
82 if let Err(e) = value.validate() {
83 vec_err.insert(index, Box::new(e));
84 }
85 }
86
87 if vec_err.is_empty() {
88 Ok(())
89 } else {
90 let err_kind = ValidationErrorsKind::List(vec_err);
91 let errors =
92 ValidationErrors(HashMap::from([(Cow::Borrowed("_tmp_validator"), err_kind)]));
93 Err(errors)
94 }
95 }
96}
97
98impl<K, V: Validate> Validate for &BTreeMap<K, V> {
99 fn validate(&self) -> Result<(), ValidationErrors> {
100 let mut vec_err: BTreeMap<usize, Box<ValidationErrors>> = BTreeMap::new();
101
102 for (index, (_key, value)) in self.iter().enumerate() {
103 if let Err(e) = value.validate() {
104 vec_err.insert(index, Box::new(e));
105 }
106 }
107
108 if vec_err.is_empty() {
109 Ok(())
110 } else {
111 let err_kind = ValidationErrorsKind::List(vec_err);
112 let errors =
113 ValidationErrors(HashMap::from([(Cow::Borrowed("_tmp_validator"), err_kind)]));
114 Err(errors)
115 }
116 }
117}
118
119pub trait ValidateArgs<'v_a> {
125 type Args;
126 fn validate_with_args(&self, args: Self::Args) -> Result<(), ValidationErrors>;
127}
128
129impl<'v_a, T, U> ValidateArgs<'v_a> for Option<T>
130where
131 T: ValidateArgs<'v_a, Args = U>,
132{
133 type Args = U;
134
135 fn validate_with_args(&self, args: Self::Args) -> Result<(), ValidationErrors> {
136 if let Some(nested) = self {
137 T::validate_with_args(nested, args)
138 } else {
139 Ok(())
140 }
141 }
142}