diff options
| author | Vincent Prouillet | 2017-01-18 21:35:01 +0900 | 
|---|---|---|
| committer | Vincent Prouillet | 2017-01-19 13:38:47 +0900 | 
| commit | 1fd1b3d708a2737c2a678df8a37e719c29c754bc (patch) | |
| tree | 67cb2b347ee2dab46bce64fdcfcb1f77a59e9a19 /validator_derive | |
| parent | 8f54c9228d8cf8e2bede37ddc9958db7ce4c63a8 (diff) | |
| download | validator-1fd1b3d708a2737c2a678df8a37e719c29c754bc.tar.bz2 | |
Make it work with lifetimes
Diffstat (limited to 'validator_derive')
| -rw-r--r-- | validator_derive/Cargo.toml | 4 | ||||
| -rw-r--r-- | validator_derive/src/lib.rs | 45 | ||||
| -rw-r--r-- | validator_derive/tests/compile-fail/length/wrong_type.rs | 2 | ||||
| -rw-r--r-- | validator_derive/tests/run-pass/lifetime.rs | 19 | ||||
| -rw-r--r-- | validator_derive/tests/test_derive.rs | 12 | 
5 files changed, 68 insertions, 14 deletions
| diff --git a/validator_derive/Cargo.toml b/validator_derive/Cargo.toml index fc4a3be..3cbe9a8 100644 --- a/validator_derive/Cargo.toml +++ b/validator_derive/Cargo.toml @@ -24,5 +24,5 @@ regex = "0.2"  lazy_static = "0.2"  [dependencies.validator] -# path = "../validator" -version = "0.3.0" +path = "../validator" +# version = "0.3.0" diff --git a/validator_derive/src/lib.rs b/validator_derive/src/lib.rs index 68a4b2e..dafa49e 100644 --- a/validator_derive/src/lib.rs +++ b/validator_derive/src/lib.rs @@ -13,10 +13,14 @@ use quote::ToTokens;  use validator::{Validator}; -static RANGE_TYPES: [&'static str; 12] = [ +static RANGE_TYPES: [&'static str; 24] = [      "usize", "u8", "u16", "u32", "u64",      "isize", "i8", "i16", "i32", "i64",      "f32", "f64", + +    "Option<size>", "Option<8>", "Option<16>", "Option<32>", "Option<64>", +    "Option<size>", "Option<8>", "Option<16>", "Option<32>", "Option<64>", +    "Option<32>", "Option<64>",  ];  #[derive(Debug)] @@ -59,7 +63,14 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {          };          let (name, validators) = find_validators_for_field(field, &field_types); +        let validator_param = if field_types.get(&field_ident.to_string()).unwrap().starts_with("&") { +          quote!(self.#field_ident) +        } else { +          quote!(&self.#field_ident) +        }; +          for validator in &validators { +            println!("field: {}, types: {:?}", field_ident, field_types);              validations.push(match validator {                  &Validator::Length {min, max, equal} =>  {                      // Can't interpolate None @@ -73,7 +84,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                                  max: #max_tokens,                                  equal: #equal_tokens                              }, -                            &self.#field_ident +                            #validator_param                          ) {                              errors.add(#name, "length");                          } @@ -91,14 +102,14 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                  },                  &Validator::Email => {                      quote!( -                        if !::validator::validate_email(&self.#field_ident) { +                        if !::validator::validate_email(#validator_param) {                              errors.add(#name, "email");                          }                      )                  }                  &Validator::Url => {                      quote!( -                        if !::validator::validate_url(&self.#field_ident) { +                        if !::validator::validate_url(#validator_param) {                              errors.add(#name, "url");                          }                      ) @@ -114,7 +125,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                  &Validator::Custom(ref f) => {                      let fn_ident = syn::Ident::new(f.clone());                      quote!( -                        match #fn_ident(&self.#field_ident) { +                        match #fn_ident(#validator_param) {                              ::std::option::Option::Some(s) => {                                  errors.add(#name, &s);                              }, @@ -124,7 +135,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                  },                  &Validator::Contains(ref n) => {                      quote!( -                        if !::validator::validate_contains(&self.#field_ident, &#n) { +                        if !::validator::validate_contains(#validator_param, &#n) {                              errors.add(#name, "contains");                          }                      ) @@ -132,7 +143,7 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {                  &Validator::Regex(ref re) => {                      let re_ident = syn::Ident::new(re.clone());                      quote!( -                        if !#re_ident.is_match(&self.#field_ident) { +                        if !#re_ident.is_match(#validator_param) {                              errors.add(#name, "regex");                          }                      ) @@ -171,8 +182,11 @@ fn expand_validation(ast: &syn::MacroInput) -> quote::Tokens {      };      let ident = &ast.ident; + +    // Helper is provided for handling complex generic types correctly and effortlessly +    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();      let impl_ast = quote!( -        impl Validate for #ident { +        impl #impl_generics Validate for #ident #ty_generics #where_clause {              fn validate(&self) -> ::std::result::Result<(), ::validator::Errors> {                  let mut errors = ::validator::Errors::new(); @@ -276,7 +290,6 @@ fn find_fields_type(fields: &Vec<syn::Field>) -> HashMap<String, String> {              Some(ref s) => s.to_string(),              None => unreachable!(),          }; -          let field_type = match field.ty {              syn::Ty::Path(_, ref p) => {                  let mut tokens = quote::Tokens::new(); @@ -284,8 +297,18 @@ fn find_fields_type(fields: &Vec<syn::Field>) -> HashMap<String, String> {                  tokens.to_string().replace(' ', "")              }, +            syn::Ty::Rptr(ref l, ref p) => { +                let mut tokens = quote::Tokens::new(); +                p.ty.to_tokens(&mut tokens); +                let mut name = tokens.to_string().replace(' ', ""); +                if l.is_some() { +                    name.insert(0, '&') +                } +                name +            },              _ => panic!("Type `{:?}` of field `{}` not supported", field.ty, field_name)          }; +        //println!("{:?}", field_type);          types.insert(field_name, field_type);      } @@ -474,9 +497,9 @@ fn find_validators_for_field(field: &syn::Field, field_types: &HashMap<String, S                              syn::MetaItem::List(ref name, ref meta_items) => {                                  // Some sanity checking first                                  if name == "length" { -                                    if field_type != "String" && !field_type.starts_with("Vec<") { +                                    if field_type != "String" && !field_type.starts_with("Vec<") && field_type != "&str" {                                          error(&format!( -                                            "Validator `length` can only be used on types `String` or `Vec` but found `{}`", +                                            "Validator `length` can only be used on types `String`, `&str` or `Vec` but found `{}`",                                              field_type                                          ));                                      } diff --git a/validator_derive/tests/compile-fail/length/wrong_type.rs b/validator_derive/tests/compile-fail/length/wrong_type.rs index e8a28ca..12dbb61 100644 --- a/validator_derive/tests/compile-fail/length/wrong_type.rs +++ b/validator_derive/tests/compile-fail/length/wrong_type.rs @@ -6,7 +6,7 @@ use validator::Validate;  #[derive(Validate)]  //~^ ERROR: custom derive attribute panicked -//~^^ HELP: Invalid attribute #[validate] on field `s`: Validator `length` can only be used on types `String` or `Vec` but found `usize` +//~^^ HELP: Invalid attribute #[validate] on field `s`: Validator `length` can only be used on types `String`, `&str` or `Vec` but found `usize`  struct Test {      #[validate(length())]      s: usize, diff --git a/validator_derive/tests/run-pass/lifetime.rs b/validator_derive/tests/run-pass/lifetime.rs new file mode 100644 index 0000000..8547a1a --- /dev/null +++ b/validator_derive/tests/run-pass/lifetime.rs @@ -0,0 +1,19 @@ +#![feature(attr_literals)] + +#[macro_use] extern crate validator_derive; +extern crate validator; +use validator::Validate; + +#[derive(Validate)] +struct Test<'a> { +    #[validate(length(min = 1))] +    s: &'a str, +    #[validate(length(min = 1, max = 2))] +    s2: &'a str, +    #[validate(length(equal = 1))] +    s3: &'a str, +    #[validate(length(max = 1))] +    s4: &'a str, +} + +fn main() {} diff --git a/validator_derive/tests/test_derive.rs b/validator_derive/tests/test_derive.rs index 4e6c088..7ff542b 100644 --- a/validator_derive/tests/test_derive.rs +++ b/validator_derive/tests/test_derive.rs @@ -271,3 +271,15 @@ fn test_can_check_regex_validator() {      let s2 = RegexStruct {name: "AL".to_string()};      assert!(s2.validate().is_err());  } + +// +//#[test] +//fn test_can_validate_option_fields() { +//    #[derive(Debug, Validate)] +//    struct PutStruct<'a> { +//        #[validate(length(min = "1", max = "10"))] +//        name: Option<&'a str>, +//    } +//    let s = PutStruct {name: Some("al")}; +//    assert!(s.validate().is_ok()); +//} | 
