1#[macro_export]
11macro_rules! rule_map {
12 ($( $key: expr => $val: expr ),*) => {{
13 let mut map = std::collections::HashMap::new();
14 $( map.insert($key, $val); )*
15 map
16 }}
17}
18
19pub mod validate {
20 #[derive(Eq, PartialEq, Hash, Clone)]
21 pub enum Rules {
22 Numeric, Required, Array, Between { min: i64, max: i64 }, Boolean, Date, Email, InArray { field: String }, GreaterThan { field: String }, LessThan { field: String }, In { value: String }, NotIn { value: String }, Equal { field: String }, EqualString { value: String }, Json, Max { value: i64 }, Min { value: i64 }, String, NoneExist { field: String }, }
42
43 pub fn rule_messages(rule: Rules) -> String {
45 match rule {
46 Rules::Numeric => format!(":field must be numeric."),
47 Rules::Required => format!(":field is required."),
48 Rules::Array => format!(":field must be an array."),
49 Rules::Between { min, max } => format!(":field must be between {} and {}.", min, max),
50 Rules::Boolean => format!(":field must be boolean."),
51 Rules::Date => format!(":field must be date."),
52 Rules::Email => format!(":field must be an email."),
53 Rules::InArray { field } => format!(":field must be in {}", field),
54 Rules::GreaterThan { field } => format!(":field must be greater than {}", field),
55 Rules::LessThan { field } => format!(":field must be less than {}", field),
56 Rules::Equal { field } => format!(":field must be equal to {}", field),
57 Rules::EqualString { value } => format!(":field must be equal to {}", value),
58 Rules::Json => format!("Fields must be in an JSON."),
59 Rules::Max { value } => format!("Length of :field must be less than {}", value),
60 Rules::Min { value } => format!("Length of :field must be greater than {}", value),
61 Rules::String => format!(":field must be string."),
62 Rules::NoneExist { field } => format!("{} not exists.", field),
63 Rules::In { value } => format!(":field not exists in {}", value),
64 Rules::NotIn { value } => format!(":field exists in {}", value),
65 }
66 }
67
68 pub struct Message {
69 pub messages: Vec<String>,
70 }
71
72 #[derive(Debug)]
73 pub struct ValidationResult {
74 pub(crate) message: Option<String>,
75 pub(crate) field: Option<String>,
76 pub(crate) valid: bool,
77 }
78}
79
80pub mod validator {
81 use crate::validate::*;
82 use serde_json::Value;
83 use std::collections::HashMap;
84
85 pub fn validate(json: Value, rules: HashMap<&str, Vec<Rules>>) -> HashMap<&str, Vec<String>> {
86 let mut errors: HashMap<&str, Vec<String>> = HashMap::new();
87
88 for rule in rules.iter() {
89 let res = required(rules.get(rule.0).unwrap().to_vec(), rule.0, json.clone()).1;
90 if res.len()>0 {
91 errors.insert(rule.0,res );
92 }
93 }
94
95 return errors;
96 }
97
98 fn required(rules: Vec<Rules>, field: &str, json: Value) -> (&str, Vec<String>) {
99 let mut errors: Vec<String> = Vec::new();
100 for rul in rules.iter() {
101 let real_value = json.get(field);
102 let is_none = real_value == None;
103 if is_none {
104 errors.push(rule_messages(rul.clone()))
105 } else {
106 let res = error_checker(rul.clone(), field, json.clone());
107 if !res.is_empty() {
108 errors.push(res);
109 }
110 }
111 }
112 (field, errors)
113 }
114
115 fn error_checker(rule: Rules, field: &str, json: Value) -> String {
116 use regex::Regex;
117 let mut msg = "".to_string();
118 let real_value = json.get(field);
119 match rule {
120 Rules::Required => {
121 if real_value.unwrap().is_null() {
122 msg = rule_messages(Rules::Required)
123 }
124 }
125 Rules::Numeric => {
126 if !real_value.unwrap().is_number() {
127 msg = rule_messages(Rules::Numeric)
128 }
129 }
130 Rules::Array => {
131 if !real_value.unwrap().is_array() {
132 msg = rule_messages(Rules::Array)
133 }
134 }
135 Rules::Boolean => {
136 if !real_value.unwrap().is_boolean() {
137 msg = rule_messages(Rules::Numeric)
138 }
139 }
140 Rules::String => {
141 if !real_value.unwrap().is_string() {
142 msg = rule_messages(Rules::String)
143 }
144 }
145 Rules::Email => {
151 let email_regex = Regex::new(r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})").unwrap();
152 let is_email = email_regex.is_match(&&*real_value.unwrap().to_string().as_str().replace('"', ""));
153 if !is_email {
154 msg = rule_messages(Rules::Email)
155 }
156 }
157 Rules::In { value } => {
158 let arr = value.split(',').collect::<Vec<&str>>();
159 if !arr.contains(&&*real_value.unwrap().to_string().as_str().replace('"', "")) {
160 msg = rule_messages(Rules::In { value })
161 }
162 }
163 Rules::Between { min, max } => {
164 let vl = real_value.unwrap().to_owned().as_i64();
165 if vl> Option::from(max) || vl< Option::from(min) {
166 msg = rule_messages(Rules::Between { min, max })
167 }
168 }
169 Rules::Min {value} => {
170 let vl = real_value.unwrap().to_owned().to_string();
171 if vl.len()< value as usize {
172 msg = rule_messages(Rules::Min { value })
173 }
174 }
175 Rules::Max {value } => {
176 let vl = real_value.unwrap().to_owned().to_string();
177 if vl.len()> value as usize {
178 msg = rule_messages(Rules::Max { value })
179 }
180 }
181 Rules::EqualString { value } => {
182 if real_value.unwrap().to_string().as_str().replace('"', "") == value {
183 msg = rule_messages(Rules::EqualString {value})
184 }
185 }
186 Rules::NotIn { value } => {
187 let arr = value.split(',').collect::<Vec<&str>>();
188 if arr.contains(&&*real_value.unwrap().to_string().as_str().replace('"', "")) {
189 msg = rule_messages(Rules::NotIn { value })
190 }
191 }
192 Rules::GreaterThan { field } => {
193 let second = json.get(field.clone());
194 if second != None {
195 if real_value.unwrap().to_owned().as_f64() < second.unwrap().to_owned().as_f64() {
196 msg = rule_messages(Rules::GreaterThan { field })
197 }
198 } else {
199 msg = rule_messages(Rules::NoneExist { field })
200 }
201 }
202 Rules::Equal { field } => {
203 let second = json.get(field.clone());
204 if second != None {
205 if real_value.unwrap().to_owned().as_f64() == second.unwrap().to_owned().as_f64() {
206 msg = rule_messages(Rules::Equal { field })
207 }
208 } else {
209 msg = rule_messages(Rules::NoneExist { field })
210 }
211 }
212 Rules::LessThan { field } => {
213 let second = json.get(field.clone());
214 if second != None {
215 if real_value.unwrap().to_owned().as_f64() > second.unwrap().to_owned().as_f64() {
216 msg = rule_messages(Rules::LessThan { field })
217 }
218 } else {
219 msg = rule_messages(Rules::NoneExist { field })
220 }
221 }
222 _ => {
223 msg = "Unknown error.".to_string()
224 }
225 }
226 msg.replace(":field", field)
227 }
228}