diff options
| -rw-r--r-- | .github/workflows/ci.yml | 3 | ||||
| -rw-r--r-- | validator/Cargo.toml | 6 | ||||
| -rw-r--r-- | validator/src/lib.rs | 14 | ||||
| -rw-r--r-- | validator/src/types.rs | 5 | ||||
| -rw-r--r-- | validator/src/validation/email.rs | 1 | ||||
| -rw-r--r-- | validator_derive/Cargo.toml | 11 | ||||
| -rw-r--r-- | validator_derive/src/asserts.rs | 2 | ||||
| -rw-r--r-- | validator_derive/src/lib.rs | 56 | ||||
| -rw-r--r-- | validator_derive/src/lit.rs | 7 | ||||
| -rw-r--r-- | validator_derive/src/quoting.rs | 7 | ||||
| -rw-r--r-- | validator_derive/src/validation.rs | 131 | 
11 files changed, 118 insertions, 125 deletions
| diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 450a467..b394359 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,6 +43,3 @@ jobs:          rust-version: nightly      - name: tests validator_derive with all features        run: cd validator_derive && cargo test --all-features -    - name: tests validator_derive with no features -      run: cd validator_derive && cargo test --no-default-features - diff --git a/validator/Cargo.toml b/validator/Cargo.toml index afc282b..b7e43c0 100644 --- a/validator/Cargo.toml +++ b/validator/Cargo.toml @@ -1,6 +1,6 @@  [package]  name = "validator" -version = "0.9.0" +version = "0.10.0"  authors = ["Vincent Prouillet <prouillet.vincent@gmail.com"]  license = "MIT"  description = "Common validation functions (email, url, length, ...) and trait - to be used with `validator_derive`" @@ -10,10 +10,10 @@ keywords = ["validation", "api", "validator"]  edition = "2018"  [dependencies] -url = "1" +url = "2"  regex = "1"  lazy_static = "1" -idna = "0.1" +idna = "0.2"  serde = "1"  serde_derive = "1"  serde_json = "1" diff --git a/validator/src/lib.rs b/validator/src/lib.rs index 7839c2b..5313c41 100644 --- a/validator/src/lib.rs +++ b/validator/src/lib.rs @@ -1,17 +1,3 @@ -extern crate regex; -extern crate url; -#[macro_use] -extern crate lazy_static; -extern crate idna; -extern crate serde; -extern crate serde_json; -#[macro_use] -extern crate serde_derive; -#[cfg(feature = "card")] -extern crate card_validate; -#[cfg(feature = "phone")] -pub extern crate phonenumber; -  mod traits;  mod types;  mod validation; diff --git a/validator/src/types.rs b/validator/src/types.rs index 09e4c7d..f72308c 100644 --- a/validator/src/types.rs +++ b/validator/src/types.rs @@ -3,6 +3,7 @@ use std::collections::{hash_map::Entry::Vacant, BTreeMap, HashMap};  use std::{self, fmt};  use serde::ser::Serialize; +use serde_derive::{Serialize, Deserialize};  use serde_json::{to_value, Value};  #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] @@ -32,7 +33,7 @@ impl std::error::Error for ValidationError {      fn description(&self) -> &str {          &self.code      } -    fn cause(&self) -> Option<&std::error::Error> { +    fn cause(&self) -> Option<&dyn std::error::Error> {          None      }  } @@ -168,7 +169,7 @@ impl std::error::Error for ValidationErrors {      fn description(&self) -> &str {          "Validation failed"      } -    fn cause(&self) -> Option<&std::error::Error> { +    fn cause(&self) -> Option<& dyn std::error::Error> {          None      }  } diff --git a/validator/src/validation/email.rs b/validator/src/validation/email.rs index cd8c6d2..3f71e22 100644 --- a/validator/src/validation/email.rs +++ b/validator/src/validation/email.rs @@ -1,6 +1,7 @@  use idna::domain_to_ascii;  use regex::Regex;  use std::borrow::Cow; +use lazy_static::lazy_static;  use crate::validation::ip::validate_ip; diff --git a/validator_derive/Cargo.toml b/validator_derive/Cargo.toml index 5c515de..4062170 100644 --- a/validator_derive/Cargo.toml +++ b/validator_derive/Cargo.toml @@ -1,12 +1,13 @@  [package]  name = "validator_derive" -version = "0.9.0" +version = "0.10.0"  authors = ["Vincent Prouillet <prouillet.vincent@gmail.com"]  license = "MIT"  description = "Macros 1.1 implementation of #[derive(Validate)]"  homepage = "https://github.com/Keats/validator"  repository = "https://github.com/Keats/validator"  keywords = ["validation", "api", "validator"] +edition = "2018"  [lib]  proc-macro = true @@ -17,11 +18,11 @@ card = ["validator/card"]  unic = ["validator/unic"]  [dependencies] -syn = { version = "0.15", features = ["extra-traits"] } -quote = "0.6" -proc-macro2 = "0.4" +syn = { version = "1", features = ["extra-traits"] } +quote = "1" +proc-macro2 = "1"  if_chain = "1" -validator = { version = "0.9", path = "../validator"} +validator = { version = "0.10", path = "../validator"}  regex = "1"  lazy_static = "1" diff --git a/validator_derive/src/asserts.rs b/validator_derive/src/asserts.rs index a5892a8..023dd0d 100644 --- a/validator_derive/src/asserts.rs +++ b/validator_derive/src/asserts.rs @@ -1,5 +1,7 @@  use regex::Regex; +use lazy_static::lazy_static; +  lazy_static! {      pub static ref COW_TYPE: Regex = Regex::new(r"Cow<'[a-z]+,str>").unwrap();  } diff --git a/validator_derive/src/lib.rs b/validator_derive/src/lib.rs index d8bbb3e..18472a9 100644 --- a/validator_derive/src/lib.rs +++ b/validator_derive/src/lib.rs @@ -1,19 +1,9 @@  #![recursion_limit = "128"] - -#[macro_use] -extern crate if_chain; -#[macro_use] -extern crate lazy_static;  extern crate proc_macro; -extern crate proc_macro2; -#[macro_use] -extern crate quote; -extern crate regex; -#[macro_use] -extern crate syn; -extern crate validator; - -use proc_macro::TokenStream; + +use if_chain::if_chain; +use quote::quote; +use syn::parse_quote;  use quote::ToTokens;  use std::collections::HashMap;  use validator::Validator; @@ -29,7 +19,7 @@ use quoting::{quote_field_validation, quote_schema_validation, FieldQuoter};  use validation::*;  #[proc_macro_derive(Validate, attributes(validate))] -pub fn derive_validation(input: TokenStream) -> TokenStream { +pub fn derive_validation(input: proc_macro::TokenStream) -> proc_macro::TokenStream {      let ast = syn::parse(input).unwrap();      impl_validate(&ast).into()  } @@ -110,11 +100,12 @@ fn find_struct_validation(struct_attrs: &Vec<syn::Attribute>) -> Option<SchemaVa          }          if_chain! { -            if let Some(syn::Meta::List(syn::MetaList { ref nested, .. })) = attr.interpret_meta(); +            if let Ok(syn::Meta::List(syn::MetaList { ref nested, .. })) = attr.parse_meta();              if let syn::NestedMeta::Meta(ref item) = nested[0]; -            if let &syn::Meta::List(syn::MetaList { ref ident, ref nested, .. }) = item; +            if let &syn::Meta::List(syn::MetaList { ref path, ref nested, .. }) = item;              then { +                let ident = path.get_ident().unwrap();                  if ident != "schema" {                      error("Only `schema` is allowed as validator on a struct")                  } @@ -127,9 +118,10 @@ fn find_struct_validation(struct_attrs: &Vec<syn::Attribute>) -> Option<SchemaVa                  for arg in nested {                      if_chain! {                          if let syn::NestedMeta::Meta(ref item) = *arg; -                        if let syn::Meta::NameValue(syn::MetaNameValue { ref ident, ref lit, .. }) = *item; +                        if let syn::Meta::NameValue(syn::MetaNameValue { ref path, ref lit, .. }) = *item;                          then { +                            let ident = path.get_ident().unwrap();                              match ident.to_string().as_ref() {                                  "function" => {                                      function = match lit_to_string(lit) { @@ -251,8 +243,8 @@ fn find_validators_for_field(              has_validate = true;          } -        match attr.interpret_meta() { -            Some(syn::Meta::List(syn::MetaList { ref nested, .. })) => { +        match attr.parse_meta() { +            Ok(syn::Meta::List(syn::MetaList { ref nested, .. })) => {                  let meta_items = nested.iter().collect();                  // original name before serde rename                  if attr.path == parse_quote!(serde) { @@ -267,7 +259,7 @@ fn find_validators_for_field(                      match *meta_item {                          syn::NestedMeta::Meta(ref item) => match *item {                              // email, url, phone, credit_card, non_control_character -                            syn::Meta::Word(ref name) => match name.to_string().as_ref() { +                            syn::Meta::Path(ref name) => match name.get_ident().unwrap().to_string().as_ref() {                                  "email" => {                                      assert_string_type("email", field_type);                                      validators.push(FieldValidation::new(Validator::Email)); @@ -291,12 +283,13 @@ fn find_validators_for_field(                                      assert_string_type("non_control_character", field_type);                                      validators.push(FieldValidation::new(Validator::NonControlCharacter));                                  } -                                _ => panic!("Unexpected validator: {}", name), +                                _ => panic!("Unexpected validator: {:?}", name.get_ident()),                              },                              // custom, contains, must_match, regex                              syn::Meta::NameValue(syn::MetaNameValue { -                                ref ident, ref lit, .. +                                ref path, ref lit, ..                              }) => { +                                let ident = path.get_ident().unwrap();                                  match ident.to_string().as_ref() {                                      "custom" => {                                          match lit_to_string(lit) { @@ -329,8 +322,9 @@ fn find_validators_for_field(                                  };                              }                              // Validators with several args -                            syn::Meta::List(syn::MetaList { ref ident, ref nested, .. }) => { +                            syn::Meta::List(syn::MetaList { ref path, ref nested, .. }) => {                                  let meta_items = nested.iter().cloned().collect(); +                                let ident = path.get_ident().unwrap();                                  match ident.to_string().as_ref() {                                      "length" => {                                          assert_has_len(rust_ident.clone(), field_type); @@ -401,10 +395,11 @@ fn find_validators_for_field(                      };                  }              } -            Some(syn::Meta::Word(_)) => validators.push(FieldValidation::new(Validator::Nested)), -            _ => unreachable!( -                "Got something other than a list of attributes while checking field `{}`", -                field_ident +            Ok(syn::Meta::Path(_)) => validators.push(FieldValidation::new(Validator::Nested)), +            Ok(syn::Meta::NameValue(_)) => panic!("Unexpected name=value argument"), +            Err(e) => unreachable!( +                "Got something other than a list of attributes while checking field `{}`: {:?}", +                field_ident, e              ),          }      } @@ -427,8 +422,9 @@ fn find_original_field_name(meta_items: &Vec<&syn::NestedMeta>) -> Option<String      for meta_item in meta_items {          match **meta_item {              syn::NestedMeta::Meta(ref item) => match *item { -                syn::Meta::Word(_) => continue, -                syn::Meta::NameValue(syn::MetaNameValue { ref ident, ref lit, .. }) => { +                syn::Meta::Path(_) => continue, +                syn::Meta::NameValue(syn::MetaNameValue { ref path, ref lit, .. }) => { +                    let ident = path.get_ident().unwrap();                      if ident == "rename" {                          original_name = Some(lit_to_string(lit).unwrap());                      } diff --git a/validator_derive/src/lit.rs b/validator_derive/src/lit.rs index 41deffc..f5a9386 100644 --- a/validator_derive/src/lit.rs +++ b/validator_derive/src/lit.rs @@ -1,5 +1,6 @@  use proc_macro2;  use syn; +use quote::quote;  pub fn lit_to_string(lit: &syn::Lit) -> Option<String> {      match *lit { @@ -10,15 +11,15 @@ pub fn lit_to_string(lit: &syn::Lit) -> Option<String> {  pub fn lit_to_int(lit: &syn::Lit) -> Option<u64> {      match *lit { -        syn::Lit::Int(ref s) => Some(s.value()), +        syn::Lit::Int(ref s) => Some(s.base10_parse().unwrap()),          _ => None,      }  }  pub fn lit_to_float(lit: &syn::Lit) -> Option<f64> {      match *lit { -        syn::Lit::Float(ref s) => Some(s.value()), -        syn::Lit::Int(ref s) => Some(s.value() as f64), +        syn::Lit::Float(ref s) => Some(s.base10_parse::<f64>().unwrap()), +        syn::Lit::Int(ref s) => Some(s.base10_parse::<f64>().unwrap()),          _ => None,      }  } diff --git a/validator_derive/src/quoting.rs b/validator_derive/src/quoting.rs index 6bfef0c..0ba6af2 100644 --- a/validator_derive/src/quoting.rs +++ b/validator_derive/src/quoting.rs @@ -1,10 +1,11 @@  use proc_macro2::{self, Span};  use syn;  use validator::Validator; +use quote::quote; -use asserts::{COW_TYPE, NUMBER_TYPES}; -use lit::{option_f64_to_tokens, option_u64_to_tokens}; -use validation::{FieldValidation, SchemaValidation}; +use crate::asserts::{COW_TYPE, NUMBER_TYPES}; +use crate::lit::{option_f64_to_tokens, option_u64_to_tokens}; +use crate::validation::{FieldValidation, SchemaValidation};  /// Pass around all the information needed for creating a validation  #[derive(Debug)] diff --git a/validator_derive/src/validation.rs b/validator_derive/src/validation.rs index be8afee..37a2d5a 100644 --- a/validator_derive/src/validation.rs +++ b/validator_derive/src/validation.rs @@ -2,7 +2,7 @@ use syn;  use validator::Validator; -use lit::*; +use crate::lit::*;  #[derive(Debug)]  pub struct SchemaValidation { @@ -41,32 +41,33 @@ pub fn extract_length_validation(      for meta_item in meta_items {          if let syn::NestedMeta::Meta(ref item) = *meta_item { -            if let syn::Meta::NameValue(syn::MetaNameValue { ref ident, ref lit, .. }) = *item { -                match ident.to_string().as_ref() { -                    "message" | "code" => continue, -                    "min" => { -                        min = match lit_to_int(lit) { -                            Some(s) => Some(s), -                            None => error("invalid argument type for `min` of `length` validator: only integers are allowed"), -                        }; -                    }, -                    "max" => { -                        max = match lit_to_int(lit) { -                            Some(s) => Some(s), -                            None => error("invalid argument type for `max` of `length` validator: only integers are allowed"), -                        }; -                    }, -                    "equal" => { -                        equal = match lit_to_int(lit) { -                            Some(s) => Some(s), -                            None => error("invalid argument type for `equal` of `length` validator: only integers are allowed"), -                        }; -                    }, -                    v => error(&format!( -                        "unknown argument `{}` for validator `length` (it only has `min`, `max`, `equal`)", -                        v -                    )) -                } +            if let syn::Meta::NameValue(syn::MetaNameValue { ref path, ref lit, .. }) = *item { +                    let ident = path.get_ident().unwrap(); +                    match ident.to_string().as_ref() { +                        "message" | "code" => continue, +                        "min" => { +                            min = match lit_to_int(lit) { +                                Some(s) => Some(s), +                                None => error("invalid argument type for `min` of `length` validator: only integers are allowed"), +                            }; +                        }, +                        "max" => { +                            max = match lit_to_int(lit) { +                                Some(s) => Some(s), +                                None => error("invalid argument type for `max` of `length` validator: only integers are allowed"), +                            }; +                        }, +                        "equal" => { +                            equal = match lit_to_int(lit) { +                                Some(s) => Some(s), +                                None => error("invalid argument type for `equal` of `length` validator: only integers are allowed"), +                            }; +                        }, +                        v => error(&format!( +                            "unknown argument `{}` for validator `length` (it only has `min`, `max`, `equal`)", +                            v +                        )) +                    }              } else {                  panic!(                      "unexpected item {:?} while parsing `length` validator of field {}", @@ -107,7 +108,8 @@ pub fn extract_range_validation(      for meta_item in meta_items {          match *meta_item {              syn::NestedMeta::Meta(ref item) => match *item { -                syn::Meta::NameValue(syn::MetaNameValue { ref ident, ref lit, .. }) => { +                syn::Meta::NameValue(syn::MetaNameValue { ref path, ref lit, .. }) => { +                    let ident = path.get_ident().unwrap();                      match ident.to_string().as_ref() {                          "message" | "code" => continue,                          "min" => { @@ -123,9 +125,9 @@ pub fn extract_range_validation(                              };                          }                          v => error(&format!( -                        "unknown argument `{}` for validator `range` (it only has `min`, `max`)", -                        v -                    )), +                            "unknown argument `{}` for validator `range` (it only has `min`, `max`)", +                            v +                        )),                      }                  }                  _ => panic!("unexpected item {:?} while parsing `range` validator", item), @@ -157,15 +159,16 @@ pub fn extract_argless_validation(      for meta_item in meta_items {          match *meta_item {              syn::NestedMeta::Meta(ref item) => match *item { -                syn::Meta::NameValue(syn::MetaNameValue { ref ident, .. }) => { -                    match ident.to_string().as_ref() { -                        "message" | "code" => continue, -                        v => panic!( -                            "Unknown argument `{}` for validator `{}` on field `{}`", -                            v, validator_name, field -                        ), +                syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) => { +                        let ident = path.get_ident().unwrap(); +                        match ident.to_string().as_ref() { +                            "message" | "code" => continue, +                            v => panic!( +                                "Unknown argument `{}` for validator `{}` on field `{}`", +                                v, validator_name, field +                            ), +                        }                      } -                }                  _ => panic!("unexpected item {:?} while parsing `range` validator", item),              },              _ => unreachable!(), @@ -203,7 +206,9 @@ pub fn extract_one_arg_validation(      for meta_item in meta_items {          match *meta_item {              syn::NestedMeta::Meta(ref item) => match *item { -                syn::Meta::NameValue(syn::MetaNameValue { ref ident, ref lit, .. }) => { +                syn::Meta::NameValue(syn::MetaNameValue { ref path, ref lit, .. }) => { + +                    let ident = path.get_ident().unwrap();                      match ident.to_string().as_ref() {                          "message" | "code" => continue,                          v if v == val_name => { @@ -259,32 +264,34 @@ fn extract_message_and_code(      for meta_item in meta_items {          if let syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue { -            ref ident, +            ref path,              ref lit,              ..          })) = *meta_item          { -            match ident.to_string().as_ref() { -                "code" => { -                    code = match lit_to_string(lit) { -                        Some(s) => Some(s), -                        None => panic!( -                            "Invalid argument type for `code` for validator `{}` on field `{}`: only a string is allowed", -                            validator_name, field -                        ), -                    }; -                } -                "message" => { -                    message = match lit_to_string(lit) { -                        Some(s) => Some(s), -                        None => panic!( -                            "Invalid argument type for `message` for validator `{}` on field `{}`: only a string is allowed", -                            validator_name, field -                        ), -                    }; -                } -                _ => continue, -            } +                    let ident = path.get_ident().unwrap(); +                    match ident.to_string().as_ref() { +                        "code" => { +                            code = match lit_to_string(lit) { +                                Some(s) => Some(s), +                                None => panic!( +                                    "Invalid argument type for `code` for validator `{}` on field `{}`: only a string is allowed", +                                    validator_name, field +                                ), +                            }; +                        } +                        "message" => { +                            message = match lit_to_string(lit) { +                                Some(s) => Some(s), +                                None => panic!( +                                    "Invalid argument type for `message` for validator `{}` on field `{}`: only a string is allowed", +                                    validator_name, field +                                ), +                            }; +                        } +                        _ => continue, +                    } +          }      } | 
