From 2fa3ddfbeeeee5c7718a6989a1f112e560b6f5b9 Mon Sep 17 00:00:00 2001 From: yassun7010 Date: Thu, 20 Jun 2024 23:16:13 +0900 Subject: [PATCH] feat: add readme and add test cases. --- serde_valid/README.md | 41 +++++++++++++++++++ serde_valid/src/lib.rs | 41 +++++++++++++++++++ serde_valid/src/validation/custom.rs | 13 ++++-- .../field_validate/generic/custom.rs | 4 +- .../variant_validate/generic/custom.rs | 4 +- 5 files changed, 96 insertions(+), 7 deletions(-) diff --git a/serde_valid/README.md b/serde_valid/README.md index 8f0b1ed..e1fa270 100644 --- a/serde_valid/README.md +++ b/serde_valid/README.md @@ -265,6 +265,47 @@ let s = Data { assert!(s.validate().is_ok()); ``` +## Multi Errors Validation +If you want to return multiple errors in the use custom validation method, you can use `#[validate(custom)]` same as single error. + +```rust +use serde_valid::Validate; + +fn user_validation(_val: &i32) -> Result<(), Vec> { // <-- Just change the return type from `Result<(), Error>` to `Result<(), Vec>` !! + Ok(()) +} + +#[derive(Validate)] +struct Data { + #[validate(custom(user_validation))] + val: i32, +} + +let s = Data { val: 1 }; + +assert!(s.validate().is_ok()); +``` + +And you can also use closure. + +```rust +use serde_valid::Validate; + +fn user_validation(_val: &i32, param1: bool) -> Result<(), serde_valid::validation::Error> { + Ok(()) +} + +#[derive(Validate)] +struct Data { + #[validate(custom(|v| user_validation(v, true)))] + val: i32, +} + +let s = Data { val: 1 }; + +assert!(s.validate().is_ok()); +``` + ## Multi Fields Validation ### Custom Validation Now, you can use `#[validate(custom)]` for multi fields validation. diff --git a/serde_valid/src/lib.rs b/serde_valid/src/lib.rs index e1dcb73..277aeba 100644 --- a/serde_valid/src/lib.rs +++ b/serde_valid/src/lib.rs @@ -275,6 +275,47 @@ //! assert!(s.validate().is_ok()); //! ``` //! +//! ## Multi Errors Validation +//! If you want to return multiple errors in the use custom validation method, you can use `#[validate(custom)]` same as single error. +//! +//! ```rust +//! use serde_valid::Validate; +//! +//! fn user_validation(_val: &i32) -> Result<(), Vec> { // <-- Just change the return type from `Result<(), Error>` to `Result<(), Vec>` !! +//! Ok(()) +//! } +//! +//! #[derive(Validate)] +//! struct Data { +//! #[validate(custom(user_validation))] +//! val: i32, +//! } +//! +//! let s = Data { val: 1 }; +//! +//! assert!(s.validate().is_ok()); +//! ``` +//! +//! And you can also use closure. +//! +//! ```rust +//! use serde_valid::Validate; +//! +//! fn user_validation(_val: &i32, param1: bool) -> Result<(), serde_valid::validation::Error> { +//! Ok(()) +//! } +//! +//! #[derive(Validate)] +//! struct Data { +//! #[validate(custom(|v| user_validation(v, true)))] +//! val: i32, +//! } +//! +//! let s = Data { val: 1 }; +//! +//! assert!(s.validate().is_ok()); +//! ``` +//! //! ## Multi Fields Validation //! ### Custom Validation //! Now, you can use `#[validate(custom)]` for multi fields validation. diff --git a/serde_valid/src/validation/custom.rs b/serde_valid/src/validation/custom.rs index 6b838ae..1f1f3ee 100644 --- a/serde_valid/src/validation/custom.rs +++ b/serde_valid/src/validation/custom.rs @@ -1,12 +1,19 @@ /// This function is used to avoid [rustc(E0282)](https://doc.rust-lang.org/error_codes/E0282.html) error in `#[validate(custom)]` validator on the struct. #[inline] -pub fn wrap_closure_validation( - data: T, - f: impl FnOnce(T) -> Result<(), M>, +pub fn wrap_closure_validation( + data: &T, + f: impl FnOnce(&T) -> Result<(), M>, ) -> Result<(), Vec> { f(data).map_err(|e| e.into_vec_errors()) } +#[inline] +pub fn wrap_into_vec_errors( + result: Result<(), M>, +) -> Result<(), Vec> { + result.map_err(|e| e.into_vec_errors()) +} + pub trait IntoVecErrors { fn into_vec_errors(self) -> Vec; } diff --git a/serde_valid_derive/src/attribute/field_validate/generic/custom.rs b/serde_valid_derive/src/attribute/field_validate/generic/custom.rs index 6627a19..eb8ad72 100644 --- a/serde_valid_derive/src/attribute/field_validate/generic/custom.rs +++ b/serde_valid_derive/src/attribute/field_validate/generic/custom.rs @@ -35,11 +35,11 @@ pub fn extract_generic_custom_validator( }?; Ok(quote!( - if let Err(__error) = #custom_fn_name(#field_ident) { + if let Err(__errors) = serde_valid::validation::custom::wrap_into_vec_errors(#custom_fn_name(#field_ident)) { #errors .entry(#rename) .or_default() - .push(__error); + .extend(__errors); }; )) } diff --git a/serde_valid_derive/src/attribute/variant_validate/generic/custom.rs b/serde_valid_derive/src/attribute/variant_validate/generic/custom.rs index 9386f08..8223f78 100644 --- a/serde_valid_derive/src/attribute/variant_validate/generic/custom.rs +++ b/serde_valid_derive/src/attribute/variant_validate/generic/custom.rs @@ -75,8 +75,8 @@ fn extract_variant_custom_from_closure( closure: &syn::ExprClosure, ) -> Result { Ok(quote!( - if let Err(__error) = serde_valid::helpers::wrap_closure_validation(self, #closure) { - __rule_vec_errors.push(__error); + if let Err(__errors) = serde_valid::validation::custom::wrap_closure_validation(self, #closure) { + __rule_vec_errors.extend(__errors); }; )) }