aboutsummaryrefslogtreecommitdiffstats
path: root/validator_derive
diff options
context:
space:
mode:
authorVincent Prouillet2017-01-19 13:35:05 +0900
committerVincent Prouillet2017-01-19 13:38:47 +0900
commitc8fb03bdd7391fc7b9fdc56efcc55a5eec08e19c (patch)
tree9e11068da6092c5f072ea95a6265e5391adeca75 /validator_derive
parent696e4273173033a6b1d488416c5433d9c49eb8e9 (diff)
downloadvalidator-c8fb03bdd7391fc7b9fdc56efcc55a5eec08e19c.tar.bz2
Validators work for Option<TYPE>
Diffstat (limited to 'validator_derive')
-rw-r--r--validator_derive/src/lib.rs32
-rw-r--r--validator_derive/tests/test_derive.rs45
2 files changed, 63 insertions, 14 deletions
diff --git a/validator_derive/src/lib.rs b/validator_derive/src/lib.rs
index 177f315..0ad26a9 100644
--- a/validator_derive/src/lib.rs
+++ b/validator_derive/src/lib.rs
@@ -71,10 +71,12 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {
quote!(&self.#field_ident)
};
// same but for the ident used in a if let block
- let optional_validator_param = if field_name.starts_with("Option<&") {
+ let optional_validator_param = quote!(#field_ident);
+ // same but for the ident used in a if let Some variable
+ let optional_pattern_matched = if field_name.starts_with("Option<&") {
quote!(#field_ident)
} else {
- quote!(&#field_ident)
+ quote!(ref #field_ident)
};
for validator in &validators {
@@ -87,14 +89,14 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {
// wrap in if-let if we have an option
if field_name.starts_with("Option<") {
quote!(
- if let Some(#field_ident) = self.#field_ident {
+ if let Some(#optional_pattern_matched) = self.#field_ident {
if !::validator::validate_length(
::validator::Validator::Length {
min: #min_tokens,
max: #max_tokens,
equal: #equal_tokens
},
- #field_ident
+ #optional_validator_param
) {
errors.add(#name, "length");
}
@@ -143,8 +145,8 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {
// wrap in if-let if we have an option
if field_name.starts_with("Option<") {
quote!(
- if let Some(#field_ident) = self.#field_ident {
- if !::validator::validate_email(#field_ident) {
+ if let Some(#optional_pattern_matched) = self.#field_ident {
+ if !::validator::validate_email(#optional_validator_param) {
errors.add(#name, "email");
}
}
@@ -161,8 +163,8 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {
// wrap in if-let if we have an option
if field_name.starts_with("Option<") {
quote!(
- if let Some(#field_ident) = self.#field_ident {
- if !::validator::validate_url(#field_ident) {
+ if let Some(#optional_pattern_matched) = self.#field_ident {
+ if !::validator::validate_url(#optional_validator_param) {
errors.add(#name, "url");
}
}
@@ -188,8 +190,8 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {
// wrap in if-let if we have an option
if field_name.starts_with("Option<") {
quote!(
- if let Some(#field_ident) = self.#field_ident {
- match #fn_ident(#field_ident) {
+ if let Some(#optional_pattern_matched) = self.#field_ident {
+ match #fn_ident(#optional_validator_param) {
::std::option::Option::Some(s) => {
errors.add(#name, &s);
},
@@ -212,7 +214,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {
// wrap in if-let if we have an option
if field_name.starts_with("Option<") {
quote!(
- if let Some(#field_ident) = self.#field_ident {
+ if let Some(#optional_pattern_matched) = self.#field_ident {
if !::validator::validate_contains(#optional_validator_param, &#n) {
errors.add(#name, "contains");
}
@@ -231,8 +233,8 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {
// wrap in if-let if we have an option
if field_name.starts_with("Option<") {
quote!(
- if let Some(#field_ident) = self.#field_ident {
- if !#re_ident.is_match(#field_ident) {
+ if let Some(#optional_pattern_matched) = self.#field_ident {
+ if !#re_ident.is_match(#optional_validator_param) {
errors.add(#name, "regex");
}
}
@@ -539,6 +541,7 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S
"email" => {
if field_type != "String"
&& field_type != "&str"
+ && field_type != "Option<String>"
&& !(field_type.starts_with("Option<") && field_type.ends_with("str>")) {
panic!("`email` validator can only be used on String or &str");
}
@@ -547,6 +550,7 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S
"url" => {
if field_type != "String"
&& field_type != "&str"
+ && field_type != "Option<String>"
&& !(field_type.starts_with("Option<") && field_type.ends_with("str>")) {
panic!("`url` validator can only be used on String or &str");
}
@@ -600,6 +604,8 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S
if name == "length" {
if field_type != "String"
&& !field_type.starts_with("Vec<")
+ && !field_type.starts_with("Option<Vec<")
+ && field_type != "Option<String>"
// a bit ugly
&& !(field_type.starts_with("Option<") && field_type.ends_with("str>"))
&& field_type != "&str" {
diff --git a/validator_derive/tests/test_derive.rs b/validator_derive/tests/test_derive.rs
index 5d61755..d456be6 100644
--- a/validator_derive/tests/test_derive.rs
+++ b/validator_derive/tests/test_derive.rs
@@ -274,7 +274,7 @@ fn test_can_check_regex_validator() {
#[test]
-fn test_can_validate_option_fields() {
+fn test_can_validate_option_fields_with_lifetime() {
lazy_static! {
static ref RE2: Regex = Regex::new(r"[a-z]{2}").unwrap();
}
@@ -312,3 +312,46 @@ fn test_can_validate_option_fields() {
};
assert!(s.validate().is_ok());
}
+
+#[test]
+fn test_can_validate_option_fields_without_lifetime() {
+ lazy_static! {
+ static ref RE2: Regex = Regex::new(r"[a-z]{2}").unwrap();
+ }
+
+ #[derive(Debug, Validate)]
+ struct PutStruct {
+ #[validate(length(min = "1", max = "10"))]
+ name: Option<String>,
+ #[validate(length(min = "1", max = "10"))]
+ ids: Option<Vec<usize>>,
+ #[validate(range(min = "1", max = "10"))]
+ range: Option<usize>,
+ #[validate(email)]
+ email: Option<String>,
+ #[validate(url)]
+ url: Option<String>,
+ #[validate(contains = "@")]
+ text: Option<String>,
+ #[validate(regex = "RE2")]
+ re: Option<String>,
+ #[validate(custom = "check_str")]
+ custom: Option<String>,
+ }
+
+ fn check_str(_: &str) -> Option<String> {
+ None
+ }
+
+ let s = PutStruct {
+ name: Some("al".to_string()),
+ ids: Some(vec![1, 2, 3]),
+ range: Some(2),
+ email: Some("hi@gmail.com".to_string()),
+ url: Some("http://google.com".to_string()),
+ text: Some("@someone".to_string()),
+ re: Some("hi".to_string()),
+ custom: Some("hey".to_string()),
+ };
+ assert!(s.validate().is_ok());
+}