diff options
Diffstat (limited to 'validator_derive')
| -rw-r--r-- | validator_derive/Cargo.toml | 4 | ||||
| -rw-r--r-- | validator_derive/src/lib.rs | 35 | ||||
| -rw-r--r-- | validator_derive/tests/test_derive.rs | 33 | 
3 files changed, 48 insertions, 24 deletions
| diff --git a/validator_derive/Cargo.toml b/validator_derive/Cargo.toml index da556a7..e5234f9 100644 --- a/validator_derive/Cargo.toml +++ b/validator_derive/Cargo.toml @@ -22,5 +22,5 @@ serde_json = "0.8"  compiletest_rs = "0.2"  [dependencies.validator] -# path = "../validator" -version = "0.2.0" +path = "../validator" +# version = "0.2.0" diff --git a/validator_derive/src/lib.rs b/validator_derive/src/lib.rs index 9725ab6..7a21ac8 100644 --- a/validator_derive/src/lib.rs +++ b/validator_derive/src/lib.rs @@ -75,7 +75,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                              },                              &self.#field_ident                          ) { -                            errors.entry(#name.to_string()).or_insert_with(|| vec![]).push("length".to_string()); +                            errors.add(#name, "length");                          }                      )                  }, @@ -85,21 +85,21 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                              ::validator::Validator::Range {min: #min, max: #max},                              self.#field_ident as f64                          ) { -                            errors.entry(#name.to_string()).or_insert_with(|| vec![]).push("range".to_string()); +                            errors.add(#name, "range");                          }                      )                  },                  &Validator::Email => {                      quote!(                          if !::validator::validate_email(&self.#field_ident) { -                            errors.entry(#name.to_string()).or_insert_with(|| vec![]).push("email".to_string()); +                            errors.add(#name, "email");                          }                      )                  }                  &Validator::Url => {                      quote!(                          if !::validator::validate_url(&self.#field_ident) { -                            errors.entry(#name.to_string()).or_insert_with(|| vec![]).push("url".to_string()); +                            errors.add(#name, "url");                          }                      )                  }, @@ -107,7 +107,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                      let other_ident = syn::Ident::new(f.clone());                      quote!(                          if !::validator::validate_must_match(&self.#field_ident, &self.#other_ident) { -                            errors.entry(#name.to_string()).or_insert_with(|| vec![]).push("no_match".to_string()); +                            errors.add(#name, "no_match");                          }                      )                  }, @@ -116,12 +116,19 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                      quote!(                          match #fn_ident(&self.#field_ident) {                              ::std::option::Option::Some(s) => { -                                errors.entry(#name.to_string()).or_insert_with(|| vec![]).push(s) +                                errors.add(#name, &s);                              },                              ::std::option::Option::None => (),                          };                      )                  }, +                &Validator::Contains(ref n) => { +                    quote!( +                        if !::validator::validate_contains(&self.#field_ident, &#n) { +                            errors.add(#name, "contains"); +                        } +                    ) +                },              });          }      } @@ -135,7 +142,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                      if errors.is_empty() {                          match #fn_ident(self) {                              ::std::option::Option::Some((key, val)) => { -                                errors.entry(key).or_insert_with(|| vec![]).push(val) +                                errors.add(&key, &val);                              },                              ::std::option::Option::None => (),                          } @@ -145,7 +152,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                  quote!(                      match #fn_ident(self) {                          ::std::option::Option::Some((key, val)) => { -                            errors.entry(key).or_insert_with(|| vec![]).push(val) +                            errors.add(&key, &val);                          },                          ::std::option::Option::None => (),                      } @@ -159,8 +166,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {      let impl_ast = quote!(          impl Validate for #ident {              fn validate(&self) -> ::std::result::Result<(), ::validator::Errors> { -                use std::collections::HashMap; -                let mut errors = HashMap::new(); +                let mut errors = ::validator::Errors::new();                  #(#validations)* @@ -416,7 +422,7 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S                                  },                                  _ => panic!("Unexpected word validator: {}", name)                              }, -                            // custom +                            // custom, contains, must_match                              syn::MetaItem::NameValue(ref name, ref val) => {                                  match name.to_string().as_ref() {                                      "custom" => { @@ -425,6 +431,12 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S                                              None => error("invalid argument for `custom` validator: only strings are allowed"),                                          };                                      }, +                                    "contains" => { +                                        match lit_to_string(val) { +                                            Some(s) => validators.push(Validator::Contains(s)), +                                            None => error("invalid argument for `contains` validator: only strings are allowed"), +                                        }; +                                    },                                      "must_match" => {                                          match lit_to_string(val) {                                              Some(s) => { @@ -555,6 +567,7 @@ fn lit_to_float(lit: &syn::Lit) -> Option<f64> {  fn lit_to_bool(lit: &syn::Lit) -> Option<bool> {      match *lit {          syn::Lit::Bool(ref s) => Some(*s), +        // TODO: remove when attr_literals is stable          syn::Lit::Str(ref s, _) => if s == "true" { Some(true) } else { Some(false) },          _ => None,      } diff --git a/validator_derive/tests/test_derive.rs b/validator_derive/tests/test_derive.rs index 9b9bad7..c7e78cc 100644 --- a/validator_derive/tests/test_derive.rs +++ b/validator_derive/tests/test_derive.rs @@ -56,7 +56,7 @@ struct SignupData2 {  #[derive(Debug, Validate, Deserialize)]  #[validate(schema(function = "validate_signup3"))]  struct SignupData3 { -    #[validate(email)] +    #[validate(email, contains = "bob")]      mail: String,      #[validate(range(min = "18", max = "20"))]      age: u32, @@ -96,7 +96,7 @@ fn test_bad_email_fails_validation() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("mail"));      assert_eq!(errs["mail"], vec!["email".to_string()]);  } @@ -111,7 +111,7 @@ fn test_bad_url_fails_validation() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("site"));      assert_eq!(errs["site"], vec!["url".to_string()]);  } @@ -126,8 +126,7 @@ fn test_bad_length_fails_validation_and_points_to_original_name() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); -    println!("{:?}", errs); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("firstName"));      assert_eq!(errs["firstName"], vec!["length".to_string()]);  } @@ -143,7 +142,7 @@ fn test_bad_range_fails_validation() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("age"));      assert_eq!(errs["age"], vec!["range".to_string()]);  } @@ -158,7 +157,7 @@ fn test_can_have_multiple_errors() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("age"));      assert!(errs.contains_key("firstName"));      assert_eq!(errs["age"], vec!["range".to_string()]); @@ -175,7 +174,7 @@ fn test_custom_validation_error() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("firstName"));      assert_eq!(errs["firstName"], vec!["terrible_username".to_string()]);  } @@ -209,7 +208,7 @@ fn test_can_fail_struct_validation_new_key() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("all"));      assert_eq!(errs["all"], vec!["stupid_rule".to_string()]);  } @@ -222,7 +221,7 @@ fn test_can_fail_struct_validation_existing_key() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("mail"));      assert_eq!(errs["mail"], vec!["email".to_string(), "stupid_rule".to_string()]);  } @@ -235,8 +234,20 @@ fn test_skip_struct_validation_by_default_if_errors() {      };      let res = signup.validate();      assert!(res.is_err()); -    let errs = res.unwrap_err(); +    let errs = res.unwrap_err().inner();      assert!(errs.contains_key("mail"));      assert_eq!(errs["mail"], vec!["email".to_string()]); +} +#[test] +fn test_can_fail_contains_validation() { +    let signup = SignupData3 { +        mail: "bo@gmail.com".to_string(), +        age: 18, +    }; +    let res = signup.validate(); +    assert!(res.is_err()); +    let errs = res.unwrap_err().inner(); +    assert!(errs.contains_key("mail")); +    assert_eq!(errs["mail"], vec!["contains".to_string()]);  } | 
