diff options
| -rw-r--r-- | validator_derive/src/lib.rs | 32 | ||||
| -rw-r--r-- | validator_derive/tests/test_derive.rs | 45 |
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()); +} |
