diff options
| author | Caroline Glassberg-Powell | 2019-04-28 18:45:40 +0100 |
|---|---|---|
| committer | Caroline Glassberg-Powell | 2019-04-28 19:01:08 +0100 |
| commit | 6e8effdaa2b47f4056a00d301a9e7a5a1a2fd8dc (patch) | |
| tree | 781b99ec57192adb777681243b8161fd37a10bae /validator_derive | |
| parent | 4b9fe3939b106c151bff11e490a41212559f9a4a (diff) | |
| download | validator-6e8effdaa2b47f4056a00d301a9e7a5a1a2fd8dc.tar.bz2 | |
Issue #69: Change `range` to require only one arg
Currently range is hard-coded to take both max and min. This is
unhelpful in cases where we may only want to check one of the bounds.
Update so that it behaves more like the `length` validator and can take
either max or min, as well as both. Also ensure that at least one of
them is supplied.
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() {} |
