diff options
Diffstat (limited to 'validator_derive')
| -rw-r--r-- | validator_derive/src/lit.rs | 7 | ||||
| -rw-r--r-- | validator_derive/src/quoting.rs | 21 | ||||
| -rw-r--r-- | validator_derive/src/validation.rs | 43 | ||||
| -rw-r--r-- | validator_derive/tests/compile-fail/range/missing_arg.rs | 15 | ||||
| -rw-r--r-- | validator_derive/tests/compile-fail/range/no_args.rs | 2 | ||||
| -rw-r--r-- | validator_derive/tests/run-pass/range.rs | 4 |
6 files changed, 47 insertions, 45 deletions
diff --git a/validator_derive/src/lit.rs b/validator_derive/src/lit.rs index 14e3f56..de0e21e 100644 --- a/validator_derive/src/lit.rs +++ b/validator_derive/src/lit.rs @@ -46,3 +46,10 @@ pub fn option_u64_to_tokens(opt: Option<u64>) -> proc_macro2::TokenStream { None => quote!(::std::option::Option::None), } } + +pub fn option_f64_to_tokens(opt: Option<f64>) -> proc_macro2::TokenStream { + match opt { + Some(ref t) => quote!(::std::option::Option::Some(#t)), + None => quote!(::std::option::Option::None), + } +} diff --git a/validator_derive/src/quoting.rs b/validator_derive/src/quoting.rs index f94d8fc..fa97623 100644 --- a/validator_derive/src/quoting.rs +++ b/validator_derive/src/quoting.rs @@ -3,7 +3,7 @@ use syn; use validator::Validator; use asserts::{COW_TYPE, NUMBER_TYPES}; -use lit::option_u64_to_tokens; +use lit::{option_f64_to_tokens, option_u64_to_tokens}; use validation::{FieldValidation, SchemaValidation}; /// Pass around all the information needed for creating a validation @@ -183,12 +183,25 @@ pub fn quote_range_validation( let quoted_ident = field_quoter.quote_validator_param(); if let Validator::Range { min, max } = validation.validator { + // Can't interpolate None + let min_tokens = option_f64_to_tokens(min); + let max_tokens = option_f64_to_tokens(max); + + let min_err_param_quoted = if let Some(v) = min { + quote!(err.add_param(::std::borrow::Cow::from("min"), &#v);) + } else { + quote!() + }; + let max_err_param_quoted = if let Some(v) = max { + quote!(err.add_param(::std::borrow::Cow::from("max"), &#v);) + } else { + quote!() + }; + let quoted_error = quote_error(&validation); - let min_err_param_quoted = quote!(err.add_param(::std::borrow::Cow::from("min"), &#min);); - let max_err_param_quoted = quote!(err.add_param(::std::borrow::Cow::from("max"), &#max);); let quoted = quote!( if !::validator::validate_range( - ::validator::Validator::Range {min: #min, max: #max}, + ::validator::Validator::Range {min: #min_tokens, max: #max_tokens}, #quoted_ident as f64 ) { #quoted_error diff --git a/validator_derive/src/validation.rs b/validator_derive/src/validation.rs index a9762db..d9ad5a5 100644 --- a/validator_derive/src/validation.rs +++ b/validator_derive/src/validation.rs @@ -95,8 +95,8 @@ pub fn extract_range_validation( field: String, meta_items: &Vec<syn::NestedMeta>, ) -> FieldValidation { - let mut min = 0.0; - let mut max = 0.0; + let mut min = None; + let mut max = None; let (message, code) = extract_message_and_code("range", &field, meta_items); @@ -104,45 +104,38 @@ pub fn extract_range_validation( panic!("Invalid attribute #[validate] on field `{}`: {}", field, msg); }; - // whether it has both `min` and `max` - let mut has_min = false; - let mut has_max = false; - 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, .. }) => match ident - .to_string() - .as_ref() - { - "message" | "code" => continue, - "min" => { - min = match lit_to_float(lit) { - Some(s) => s, + syn::Meta::NameValue(syn::MetaNameValue { ref ident, ref lit, .. }) => { + match ident.to_string().as_ref() { + "message" | "code" => continue, + "min" => { + min = match lit_to_float(lit) { + Some(s) => Some(s), None => error("invalid argument type for `min` of `range` validator: only integers are allowed") }; - has_min = true; - } - "max" => { - max = match lit_to_float(lit) { - Some(s) => s, + } + "max" => { + max = match lit_to_float(lit) { + Some(s) => Some(s), None => error("invalid argument type for `max` of `range` validator: only integers are allowed") }; - has_max = true; - } - v => error(&format!( + } + v => error(&format!( "unknown argument `{}` for validator `range` (it only has `min`, `max`)", v )), - }, + } + } _ => panic!("unexpected item {:?} while parsing `range` validator", item), }, _ => unreachable!(), } } - if !has_min || !has_max { - error("Validator `range` requires 2 arguments: `min` and `max`"); + if !min.is_some() && !max.is_some() { + error("Validator `range` requires at least 1 argument out of `min` and `max`"); } let validator = Validator::Range { min, max }; diff --git a/validator_derive/tests/compile-fail/range/missing_arg.rs b/validator_derive/tests/compile-fail/range/missing_arg.rs deleted file mode 100644 index 3aed1f0..0000000 --- a/validator_derive/tests/compile-fail/range/missing_arg.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(attr_literals)] - -#[macro_use] extern crate validator_derive; -extern crate validator; -use validator::Validate; - -#[derive(Validate)] -//~^ ERROR: proc-macro derive panicked -//~^^ HELP: Invalid attribute #[validate] on field `s`: Validator `range` requires 2 arguments: `min` and `max` -struct Test { - #[validate(range(min = 2.0))] - s: i32, -} - -fn main() {} diff --git a/validator_derive/tests/compile-fail/range/no_args.rs b/validator_derive/tests/compile-fail/range/no_args.rs index c2bdd03..b097b0a 100644 --- a/validator_derive/tests/compile-fail/range/no_args.rs +++ b/validator_derive/tests/compile-fail/range/no_args.rs @@ -4,7 +4,7 @@ use validator::Validate; #[derive(Validate)] //~^ ERROR: proc-macro derive panicked -//~^^ HELP: Invalid attribute #[validate] on field `s`: Validator `range` requires 2 arguments: `min` and `max` +//~^^ HELP: Invalid attribute #[validate] on field `s`: Validator `range` requires at least 1 argument out of `min` and `max` struct Test { #[validate(range())] s: i32, diff --git a/validator_derive/tests/run-pass/range.rs b/validator_derive/tests/run-pass/range.rs index e35f3df..520dd64 100644 --- a/validator_derive/tests/run-pass/range.rs +++ b/validator_derive/tests/run-pass/range.rs @@ -24,6 +24,10 @@ struct Test { s8: u8, #[validate(range(min = 18.0, max = 22))] s9: Option<u8>, + #[validate(range(min = 18.0))] + s10: Option<u8>, + #[validate(range(max = 18.0))] + s11: Option<u8>, } fn main() {} |
