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