diff --git a/validator_derive/src/lib.rs b/validator_derive/src/lib.rs index 44a896e2..6869d50d 100644 --- a/validator_derive/src/lib.rs +++ b/validator_derive/src/lib.rs @@ -336,7 +336,9 @@ pub fn derive_validation(input: proc_macro::TokenStream) -> proc_macro::TokenStr validation_fields = validation_fields .iter_mut() .map(|f| { + if !f.has_validate_instruction() { f.nested = Some(true); + } f.to_owned() }) .collect(); diff --git a/validator_derive/src/types.rs b/validator_derive/src/types.rs index 54cbcf1b..39244992 100644 --- a/validator_derive/src/types.rs +++ b/validator_derive/src/types.rs @@ -219,6 +219,27 @@ impl ValidateField { ), } } + + /// Check to see if the field has validation instruction + pub fn has_validate_instruction(&self) -> bool { + [ + self.credit_card.is_some(), + self.contains.is_some(), + self.does_not_contain.is_some(), + self.email.is_some(), + self.ip.is_some(), + self.length.is_some(), + self.must_match.is_some(), + self.non_control_character.is_some(), + self.range.is_some(), + self.required.is_some(), + self.url.is_some(), + self.regex.is_some(), + !self.custom.is_empty(), + ] + .into_iter() + .any(|b| b) + } } // Structs to hold the validation information and to provide attributes diff --git a/validator_derive_tests/tests/compile-fail/nest_all_fields_wo_validation.rs b/validator_derive_tests/tests/compile-fail/nest_all_fields_wo_validation.rs new file mode 100644 index 00000000..6176a8b4 --- /dev/null +++ b/validator_derive_tests/tests/compile-fail/nest_all_fields_wo_validation.rs @@ -0,0 +1,15 @@ +use validator::Validate; + +#[derive(Validate)] +#[validate(nest_all_fields)] +struct Test { + nested: Nested, + unchecked: u8, +} + +#[derive(Validate)] +struct Nested { + value: String, +} + +fn main() {} diff --git a/validator_derive_tests/tests/compile-fail/nest_all_fields_wo_validation.stderr b/validator_derive_tests/tests/compile-fail/nest_all_fields_wo_validation.stderr new file mode 100644 index 00000000..549ea08f --- /dev/null +++ b/validator_derive_tests/tests/compile-fail/nest_all_fields_wo_validation.stderr @@ -0,0 +1,10 @@ +error[E0599]: the method `validate` exists for reference `&u8`, but its trait bounds were not satisfied + --> tests/compile-fail/nest_all_fields_wo_validation.rs:3:10 + | +3 | #[derive(Validate)] + | ^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `u8: Validate` + which is required by `&u8: Validate` + = note: this error originates in the derive macro `Validate` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/validator_derive_tests/tests/nest_all_fields.rs b/validator_derive_tests/tests/nest_all_fields.rs index c4ac2edf..c3020d6a 100644 --- a/validator_derive_tests/tests/nest_all_fields.rs +++ b/validator_derive_tests/tests/nest_all_fields.rs @@ -54,3 +54,42 @@ fn nest_all_fields_attribute_works() { assert!(test.validate().is_ok()); } + +#[test] +fn nest_all_fields_attribute_ignores_validated_fields() { + #[derive(Validate)] + #[validate(nest_all_fields)] + struct Test { + #[validate(skip)] + _a: Nested, + b: NestedValidated, + #[validate(range(min = 10))] + c: u8, + } + + struct Nested { + _val: String, + } + + #[derive(Validate)] + struct NestedValidated { + #[validate(length(min = 5, max = 10))] + val: String, + } + + let test = Test { + _a: Nested { _val: "test".to_string() }, + b: NestedValidated { val: "valid str".to_string() }, + c: 11, + }; + + assert!(test.validate().is_ok()); + + let test_invalid = Test { + _a: Nested { _val: "test".to_string() }, + b: NestedValidated { val: "valid str".to_string() }, + c: 0, + }; + + assert!(test_invalid.validate().is_err()); +}