val_test/
lib.rs

1//! It is validate with message, rules and ValidationResult <br/>
2
3
4//! Example below: <br/> <br/> <br/>
5//! <pre>
6//!  let rules_hash: HashMap<&str, Vec<Rules>> = rule_map![<br/>
7//!        "ros" => vec![Rules::In {value: "123,asd,123".to_string()}],<br/>
8//!        "ross" => vec![Rules::GreaterThan {field:"as".to_string()}]<br/>
9//!     ];<br/></pre>
10#[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, //+
23        Required, //+
24        Array, //+
25        Between { min: i64, max: i64 }, //+
26        Boolean, //+
27        Date,  // ----------
28        Email, //+
29        InArray { field: String }, //+
30        GreaterThan { field: String }, //+
31        LessThan { field: String }, //+
32        In { value: String }, //+
33        NotIn { value: String }, //+
34        Equal { field: String }, // +
35        EqualString { value: String }, // +
36        Json, // -------------------------------------
37        Max { value: i64 }, //+
38        Min { value: i64 }, //+
39        String, //+
40        NoneExist { field: String }, // +
41    }
42
43    // ":field must be greater than :val"
44    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::Json => {
146            //     if !serde_json::from_str(&real_value.unwrap().to_string().as_str()).is_ok() {
147            //         msg = rule_messages(Rules::Json)
148            //     }
149            // }
150            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}