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