aboutsummaryrefslogtreecommitdiffstats
path: root/validator_derive
diff options
context:
space:
mode:
Diffstat (limited to 'validator_derive')
-rw-r--r--validator_derive/src/lib.rs8
-rw-r--r--validator_derive/src/quoting.rs17
-rw-r--r--validator_derive/src/validation.rs9
-rw-r--r--validator_derive/tests/complex.rs10
-rw-r--r--validator_derive/tests/phone.rs77
-rw-r--r--validator_derive/tests/run-pass/phone.rs13
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() {}