diff options
Diffstat (limited to 'validator_derive')
| -rw-r--r-- | validator_derive/src/lib.rs | 8 | ||||
| -rw-r--r-- | validator_derive/src/quoting.rs | 17 | ||||
| -rw-r--r-- | validator_derive/src/validation.rs | 9 | ||||
| -rw-r--r-- | validator_derive/tests/complex.rs | 10 | ||||
| -rw-r--r-- | validator_derive/tests/phone.rs | 77 | ||||
| -rw-r--r-- | validator_derive/tests/run-pass/phone.rs | 13 |
6 files changed, 130 insertions, 4 deletions
diff --git a/validator_derive/src/lib.rs b/validator_derive/src/lib.rs index 1298006..9cfc381 100644 --- a/validator_derive/src/lib.rs +++ b/validator_derive/src/lib.rs @@ -256,7 +256,7 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S for meta_item in meta_items { match *meta_item { syn::NestedMetaItem::MetaItem(ref item) => match *item { - // email, url + // email, url, phone syn::MetaItem::Word(ref name) => match name.to_string().as_ref() { "email" => { assert_string_type("email", field_type); @@ -266,6 +266,10 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S assert_string_type("url", field_type); validators.push(FieldValidation::new(Validator::Url)); }, + "phone" => { + assert_string_type("phone", field_type); + validators.push(FieldValidation::new(Validator::Phone)); + }, _ => panic!("Unexpected validator: {}", name) }, // custom, contains, must_match, regex @@ -311,7 +315,7 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S assert_has_range(rust_ident.clone(), field_type); validators.push(extract_range_validation(rust_ident.clone(), meta_items)); }, - "email" | "url" => { + "email" | "url" | "phone" => { validators.push(extract_argless_validation(name.to_string(), rust_ident.clone(), meta_items)); }, "custom" => { diff --git a/validator_derive/src/quoting.rs b/validator_derive/src/quoting.rs index 69353e9..24c50d8 100644 --- a/validator_derive/src/quoting.rs +++ b/validator_derive/src/quoting.rs @@ -158,6 +158,22 @@ pub fn quote_range_validation(field_quoter: &FieldQuoter, validation: &FieldVali unreachable!() } +pub fn quote_phone_validation(field_quoter: &FieldQuoter, validation: &FieldValidation) -> quote::Tokens { + let field_name = &field_quoter.name; + let validator_param = field_quoter.quote_validator_param(); + + let quoted_error = quote_error(&validation); + let quoted = quote!( + if !::validator::validate_phone(#validator_param) { + #quoted_error + err.add_param(::std::borrow::Cow::from("value"), &#validator_param); + errors.add(#field_name, err); + } + ); + + field_quoter.wrap_if_option(quoted) +} + pub fn quote_url_validation(field_quoter: &FieldQuoter, validation: &FieldValidation) -> quote::Tokens { let field_name = &field_quoter.name; let validator_param = field_quoter.quote_validator_param(); @@ -293,6 +309,7 @@ pub fn quote_field_validation(field_quoter: &FieldQuoter, validation: &FieldVali Validator::Custom(_) => quote_custom_validation(&field_quoter, validation), Validator::Contains(_) => quote_contains_validation(&field_quoter, validation), Validator::Regex(_) => quote_regex_validation(&field_quoter, validation), + Validator::Phone => quote_phone_validation(&field_quoter, validation), } } diff --git a/validator_derive/src/validation.rs b/validator_derive/src/validation.rs index a3350da..259db70 100644 --- a/validator_derive/src/validation.rs +++ b/validator_derive/src/validation.rs @@ -173,7 +173,7 @@ pub fn extract_range_validation(field: String, meta_items: &Vec<syn::NestedMetaI } } -/// Extract url/email field validation with a code or a message +/// Extract url/email/phone field validation with a code or a message pub fn extract_argless_validation(validator_name: String, field: String, meta_items: &Vec<syn::NestedMetaItem>) -> FieldValidation { let mut code = None; let mut message = None; @@ -213,7 +213,12 @@ pub fn extract_argless_validation(validator_name: String, field: String, meta_it } } - let validator = if validator_name == "email" { Validator::Email } else { Validator::Url }; + let validator = match validator_name.as_ref() { + "email" => Validator::Email, + "phone" => Validator::Phone, + _ => Validator::Url + }; + FieldValidation { message, code: code.unwrap_or_else(|| validator.code().to_string()), diff --git a/validator_derive/tests/complex.rs b/validator_derive/tests/complex.rs index 0bd74fa..b9363e4 100644 --- a/validator_derive/tests/complex.rs +++ b/validator_derive/tests/complex.rs @@ -33,6 +33,8 @@ fn validate_signup(data: &SignupData) -> Result<(), ValidationError> { struct SignupData { #[validate(email)] mail: String, + #[validate(phone)] + phone: String, #[validate(url)] site: String, #[validate(length(min = "1"), custom = "validate_unique_username")] @@ -47,6 +49,7 @@ struct SignupData { fn is_fine_with_many_valid_validations() { let signup = SignupData { mail: "bob@bob.com".to_string(), + phone: "+14152370800".to_string(), site: "http://hello.com".to_string(), first_name: "Bob".to_string(), age: 18, @@ -59,6 +62,7 @@ fn is_fine_with_many_valid_validations() { fn failed_validation_points_to_original_field_name() { let signup = SignupData { mail: "bob@bob.com".to_string(), + phone: "+14152370800".to_string(), site: "http://hello.com".to_string(), first_name: "".to_string(), age: 18, @@ -85,6 +89,8 @@ fn test_can_validate_option_fields_with_lifetime() { range: Option<usize>, #[validate(email)] email: Option<&'a str>, + #[validate(phone)] + phone: Option<&'a str>, #[validate(url)] url: Option<&'a str>, #[validate(contains = "@")] @@ -103,6 +109,7 @@ fn test_can_validate_option_fields_with_lifetime() { name: Some("al"), range: Some(2), email: Some("hi@gmail.com"), + phone: Some("+14152370800"), url: Some("http://google.com"), text: Some("@someone"), re: Some("hi"), @@ -127,6 +134,8 @@ fn test_can_validate_option_fields_without_lifetime() { range: Option<usize>, #[validate(email)] email: Option<String>, + #[validate(phone)] + phone: Option<String>, #[validate(url)] url: Option<String>, #[validate(contains = "@")] @@ -146,6 +155,7 @@ fn test_can_validate_option_fields_without_lifetime() { ids: Some(vec![1, 2, 3]), range: Some(2), email: Some("hi@gmail.com".to_string()), + phone: Some("+14152370800".to_string()), url: Some("http://google.com".to_string()), text: Some("@someone".to_string()), re: Some("hi".to_string()), diff --git a/validator_derive/tests/phone.rs b/validator_derive/tests/phone.rs new file mode 100644 index 0000000..675d4c5 --- /dev/null +++ b/validator_derive/tests/phone.rs @@ -0,0 +1,77 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; + + +#[test] +fn can_validate_phone_ok() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(phone)] + val: String, + } + + let s = TestStruct { + val: "+14152370800".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn bad_phone_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(phone)] + val: String, + } + + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "phone"); +} + +#[test] +fn can_specify_code_for_phone() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(phone(code = "oops"))] + val: String, + } + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); + assert_eq!(errs["val"][0].params["value"], "bob"); +} + +#[test] +fn can_specify_message_for_phone() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(phone(message = "oops"))] + val: String, + } + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/run-pass/phone.rs b/validator_derive/tests/run-pass/phone.rs new file mode 100644 index 0000000..d6dff9e --- /dev/null +++ b/validator_derive/tests/run-pass/phone.rs @@ -0,0 +1,13 @@ +#![feature(proc_macro, attr_literals)] + +#[macro_use] extern crate validator_derive; +extern crate validator; +use validator::Validate; + +#[derive(Validate)] +struct Test { + #[validate(phone)] + s: String, +} + +fn main() {} |
