From 0d5fe343d9d239d785f3912d7891c2888df08579 Mon Sep 17 00:00:00 2001 From: ya7010 Date: Tue, 6 Jan 2026 17:48:45 +0900 Subject: [PATCH 1/6] feat: use `#[validate(r#enum = ...)`. --- crates/serde_valid/README.md | 2 +- crates/serde_valid/src/lib.rs | 8 +- crates/serde_valid/src/validation.rs | 9 +- crates/serde_valid/src/validation/generic.rs | 4 +- .../generic/{enumerate.rs => enum.rs} | 93 +++--- crates/serde_valid/tests/complex_test.rs | 24 +- crates/serde_valid/tests/custom_test.rs | 2 +- crates/serde_valid/tests/data_enum_test.rs | 202 +++++++++++++ crates/serde_valid/tests/enum_test.rs | 272 ++++++++++-------- crates/serde_valid/tests/enumerate_test.rs | 10 +- crates/serde_valid/tests/hashmap_test.rs | 2 +- crates/serde_valid_derive/src/attribute.rs | 3 + .../src/attribute/field_validate/generic.rs | 4 +- .../generic/{enumerate.rs => enum.rs} | 22 +- .../src/attribute/field_validate/meta.rs | 1 - .../field_validate/meta/meta_name_value.rs | 40 ++- crates/serde_valid_derive/src/error.rs | 10 +- crates/serde_valid_derive/src/warning.rs | 10 +- 18 files changed, 498 insertions(+), 220 deletions(-) rename crates/serde_valid/src/validation/generic/{enumerate.rs => enum.rs} (67%) create mode 100644 crates/serde_valid/tests/data_enum_test.rs rename crates/serde_valid_derive/src/attribute/field_validate/generic/{enumerate.rs => enum.rs} (70%) diff --git a/crates/serde_valid/README.md b/crates/serde_valid/README.md index e71d215c..5be58d89 100644 --- a/crates/serde_valid/README.md +++ b/crates/serde_valid/README.md @@ -61,7 +61,7 @@ Serde Valid support standard validation based JSON Schema. | Array | `#[validate(max_items = 5)]` | [`ValidateMaxItems`] | [maxItems](https://json-schema.org/understanding-json-schema/reference/array#length) | | Array | `#[validate(min_items = 5)]` | [`ValidateMinItems`] | [minItems](https://json-schema.org/understanding-json-schema/reference/array#length) | | Array | `#[validate(unique_items)]` | [`ValidateUniqueItems`] | [uniqueItems](https://json-schema.org/understanding-json-schema/reference/array#uniqueItems) | -| Generic | `#[validate(enumerate = [5, 10, 15])]` | [`ValidateEnumerate`] | [enum](https://json-schema.org/understanding-json-schema/reference/enum) | +| Generic | `#[validate(r#enum = [5, 10, 15])]` | [`ValidateEnum`] | [enum](https://json-schema.org/understanding-json-schema/reference/enum) | In addition, [serde_valid::utils][module@crate::utils] provides a type of validation not described in the JSON schema specification. diff --git a/crates/serde_valid/src/lib.rs b/crates/serde_valid/src/lib.rs index dc6fcce4..9de77812 100644 --- a/crates/serde_valid/src/lib.rs +++ b/crates/serde_valid/src/lib.rs @@ -61,7 +61,7 @@ //! | Array | `#[validate(max_items = 5)]` | [`ValidateMaxItems`] | [maxItems](https://json-schema.org/understanding-json-schema/reference/array#length) | //! | Array | `#[validate(min_items = 5)]` | [`ValidateMinItems`] | [minItems](https://json-schema.org/understanding-json-schema/reference/array#length) | //! | Array | `#[validate(unique_items)]` | [`ValidateUniqueItems`] | [uniqueItems](https://json-schema.org/understanding-json-schema/reference/array#uniqueItems) | -//! | Generic | `#[validate(enumerate = [5, 10, 15])]` | [`ValidateEnumerate`] | [enum](https://json-schema.org/understanding-json-schema/reference/enum) | +//! | Generic | `#[validate(r#enum = [5, 10, 15])]` | [`ValidateEnum`] | [enum](https://json-schema.org/understanding-json-schema/reference/enum) | //! //! In addition, [serde_valid::utils][module@crate::utils] provides a type of validation not described in the JSON schema specification. //! @@ -588,9 +588,9 @@ pub use features::*; use indexmap::IndexMap; use std::{borrow::Cow, collections::HashMap}; pub use validation::{ - ValidateEnumerate, ValidateExclusiveMaximum, ValidateExclusiveMinimum, ValidateMaxItems, - ValidateMaxLength, ValidateMaxProperties, ValidateMaximum, ValidateMinItems, ValidateMinLength, - ValidateMinProperties, ValidateMinimum, ValidateMultipleOf, ValidatePattern, + ValidateEnum, ValidateEnumerate, ValidateExclusiveMaximum, ValidateExclusiveMinimum, + ValidateMaxItems, ValidateMaxLength, ValidateMaxProperties, ValidateMaximum, ValidateMinItems, + ValidateMinLength, ValidateMinProperties, ValidateMinimum, ValidateMultipleOf, ValidatePattern, ValidateUniqueItems, }; diff --git a/crates/serde_valid/src/validation.rs b/crates/serde_valid/src/validation.rs index 25b68659..741a21bb 100644 --- a/crates/serde_valid/src/validation.rs +++ b/crates/serde_valid/src/validation.rs @@ -19,7 +19,7 @@ pub use error::{ ArrayErrors, Error, Errors, IntoError, ItemErrorsMap, ItemVecErrorsMap, ObjectErrors, PropertyErrorsMap, PropertyVecErrorsMap, VecErrors, }; -pub use generic::ValidateEnumerate; +pub use generic::{ValidateEnum, ValidateEnumerate}; use indexmap::IndexMap; pub use numeric::{ ValidateExclusiveMaximum, ValidateExclusiveMinimum, ValidateMaximum, ValidateMinimum, @@ -417,10 +417,7 @@ impl_composited_validation_1args!( // Generic impl_composited_validation_1args!( - pub trait ValidateCompositedEnumerate { - fn validate_composited_enumerate( - &self, - enumerate: T, - ) -> Result<(), Composited>; + pub trait ValidateCompositedEnum { + fn validate_composited_enum(&self, enumerate: T) -> Result<(), Composited>; } ); diff --git a/crates/serde_valid/src/validation/generic.rs b/crates/serde_valid/src/validation/generic.rs index b9c41f18..c96444b2 100644 --- a/crates/serde_valid/src/validation/generic.rs +++ b/crates/serde_valid/src/validation/generic.rs @@ -1,2 +1,2 @@ -mod enumerate; -pub use enumerate::ValidateEnumerate; +mod r#enum; +pub use r#enum::{ValidateEnum, ValidateEnum as ValidateEnumerate}; diff --git a/crates/serde_valid/src/validation/generic/enumerate.rs b/crates/serde_valid/src/validation/generic/enum.rs similarity index 67% rename from crates/serde_valid/src/validation/generic/enumerate.rs rename to crates/serde_valid/src/validation/generic/enum.rs index 81f89839..1fddeb11 100644 --- a/crates/serde_valid/src/validation/generic/enumerate.rs +++ b/crates/serde_valid/src/validation/generic/enum.rs @@ -1,28 +1,30 @@ -use crate::validation::ValidateCompositedEnumerate; +use crate::validation::ValidateCompositedEnum; use crate::EnumerateError; /// Enumerate validation. /// /// See /// +/// Note: `#[validate(enumerate = ...)]` is deprecated; use `#[validate(r#enum = ...)]`. +/// /// ```rust /// use serde_json::json; -/// use serde_valid::{Validate, ValidateEnumerate}; +/// use serde_valid::{Validate, ValidateEnum}; /// /// struct MyType(String); /// -/// impl ValidateEnumerate<&'static str> for MyType { -/// fn validate_enumerate( +/// impl ValidateEnum<&'static str> for MyType { +/// fn validate_enum( /// &self, /// enumerate: &[&'static str], /// ) -> Result<(), serde_valid::EnumerateError> { -/// self.0.validate_enumerate(enumerate) +/// self.0.validate_enum(enumerate) /// } /// } /// /// #[derive(Validate)] /// struct TestStruct { -/// #[validate(enumerate = ["1", "2", "3"])] +/// #[validate(r#enum = ["1", "2", "3"])] /// val: MyType, /// } /// @@ -43,14 +45,19 @@ use crate::EnumerateError; /// .to_string() /// ); /// ``` -pub trait ValidateEnumerate { - fn validate_enumerate(&self, enumerate: &[T]) -> Result<(), EnumerateError>; +pub trait ValidateEnum { + fn validate_enum(&self, enumerate: &[T]) -> Result<(), EnumerateError>; + + #[deprecated(since = "0.1.0", note = "use `validate_enum` instead")] + fn validate_enumerate(&self, enumerate: &[T]) -> Result<(), EnumerateError> { + self.validate_enum(enumerate) + } } macro_rules! impl_validate_generic_enumerate_literal { ($type:ty) => { - impl ValidateEnumerate<$type> for $type { - fn validate_enumerate(&self, enumerate: &[$type]) -> Result<(), EnumerateError> { + impl ValidateEnum<$type> for $type { + fn validate_enum(&self, enumerate: &[$type]) -> Result<(), EnumerateError> { if enumerate.iter().any(|candidate| candidate == self) { Ok(()) } else { @@ -59,15 +66,15 @@ macro_rules! impl_validate_generic_enumerate_literal { } } - impl ValidateCompositedEnumerate<&[$type]> for T + impl ValidateCompositedEnum<&[$type]> for T where - T: ValidateEnumerate<$type>, + T: ValidateEnum<$type>, { - fn validate_composited_enumerate( + fn validate_composited_enum( &self, limit: &[$type], ) -> Result<(), crate::validation::Composited> { - self.validate_enumerate(limit) + self.validate_enum(limit) .map_err(|error| crate::validation::Composited::Single(error)) } } @@ -108,8 +115,8 @@ impl_validate_generic_enumerate_literal!(char); macro_rules! impl_validate_generic_enumerate_str { ($type:ty) => { - impl ValidateEnumerate<&'static str> for $type { - fn validate_enumerate(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> { + impl ValidateEnum<&'static str> for $type { + fn validate_enum(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> { if enumerate.iter().any(|candidate| candidate == self) { Ok(()) } else { @@ -128,8 +135,8 @@ impl_validate_generic_enumerate_str!(std::ffi::OsString); macro_rules! impl_validate_generic_enumerate_path { ($type:ty) => { - impl ValidateEnumerate<&'static str> for $type { - fn validate_enumerate(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> { + impl ValidateEnum<&'static str> for $type { + fn validate_enum(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> { if enumerate .iter() .any(|candidate| &std::path::Path::new(candidate) == self) @@ -146,15 +153,15 @@ macro_rules! impl_validate_generic_enumerate_path { impl_validate_generic_enumerate_path!(&std::path::Path); impl_validate_generic_enumerate_path!(std::path::PathBuf); -impl ValidateCompositedEnumerate<&[&'static str]> for T +impl ValidateCompositedEnum<&[&'static str]> for T where - T: ValidateEnumerate<&'static str>, + T: ValidateEnum<&'static str>, { - fn validate_composited_enumerate( + fn validate_composited_enum( &self, limit: &[&'static str], ) -> Result<(), crate::validation::Composited> { - self.validate_enumerate(limit) + self.validate_enum(limit) .map_err(crate::validation::Composited::Single) } } @@ -165,72 +172,60 @@ mod tests { #[test] fn test_validate_integer_vec_type_is_true() { - assert!(ValidateEnumerate::validate_enumerate(&1, &[1, 2, 3]).is_ok()); + assert!(ValidateEnum::validate_enum(&1, &[1, 2, 3]).is_ok()); } #[test] fn test_validate_integer_vec_type_is_false() { - assert!(ValidateEnumerate::validate_enumerate(&1, &[2, 3, 4]).is_err()); + assert!(ValidateEnum::validate_enum(&1, &[2, 3, 4]).is_err()); } #[test] fn test_validate_float_type_is_true() { - assert!(ValidateEnumerate::validate_enumerate(&0.9, &[0.9, 2.3, -3.0]).is_ok()); + assert!(ValidateEnum::validate_enum(&0.9, &[0.9, 2.3, -3.0]).is_ok()); } #[test] fn test_validate_float_type_is_false() { - assert!(ValidateEnumerate::validate_enumerate(&0.9, &[0.8, 2.3, -3.0]).is_err()); + assert!(ValidateEnum::validate_enum(&0.9, &[0.8, 2.3, -3.0]).is_err()); } #[test] fn test_validate_unsigned_int_type() { - assert!(ValidateEnumerate::validate_enumerate(&1, &[-1, 0, 1, 2, 3]).is_ok()); + assert!(ValidateEnum::validate_enum(&1, &[-1, 0, 1, 2, 3]).is_ok()); } #[test] fn test_validate_str_type() { - assert!(ValidateEnumerate::validate_enumerate(&'a', &['a', 'b', 'c']).is_ok()); + assert!(ValidateEnum::validate_enum(&'a', &['a', 'b', 'c']).is_ok()); } #[test] fn test_validate_string_type() { - assert!(ValidateEnumerate::validate_enumerate(&'a', &['a', 'b', 'c']).is_ok()); + assert!(ValidateEnum::validate_enum(&'a', &['a', 'b', 'c']).is_ok()); } #[test] fn test_validate_os_str_type() { - assert!(ValidateEnumerate::validate_enumerate( - &std::ffi::OsStr::new("a"), - &["a", "b", "c"] - ) - .is_ok()); + assert!(ValidateEnum::validate_enum(&std::ffi::OsStr::new("a"), &["a", "b", "c"]).is_ok()); } #[test] fn test_validate_os_string_type() { - assert!(ValidateEnumerate::validate_enumerate( - &std::ffi::OsString::from("a"), - &["a", "b", "c"] - ) - .is_ok()); + assert!( + ValidateEnum::validate_enum(&std::ffi::OsString::from("a"), &["a", "b", "c"]).is_ok() + ); } #[test] fn test_validate_path_type() { - assert!(ValidateEnumerate::validate_enumerate( - &std::path::Path::new("a"), - &["a", "b", "c"] - ) - .is_ok()); + assert!(ValidateEnum::validate_enum(&std::path::Path::new("a"), &["a", "b", "c"]).is_ok()); } #[test] fn test_validate_path_buf_type() { - assert!(ValidateEnumerate::validate_enumerate( - &std::path::PathBuf::from("a"), - &["a", "b", "c"] - ) - .is_ok()); + assert!( + ValidateEnum::validate_enum(&std::path::PathBuf::from("a"), &["a", "b", "c"]).is_ok() + ); } } diff --git a/crates/serde_valid/tests/complex_test.rs b/crates/serde_valid/tests/complex_test.rs index a058b4e1..eeddccbb 100644 --- a/crates/serde_valid/tests/complex_test.rs +++ b/crates/serde_valid/tests/complex_test.rs @@ -8,7 +8,7 @@ fn sample_rule(_val: i32) -> Result<(), serde_valid::validation::Error> { #[validate(custom = |s| sample_rule(s.int_value))] struct TestStruct<'a> { // Generic validator - #[validate(enumerate = [5, 10, 15])] + #[validate(r#enum = [5, 10, 15])] // Numeric validator #[validate(multiple_of = 5)] #[validate(minimum = 5)] @@ -18,7 +18,7 @@ struct TestStruct<'a> { int_value: i32, // Generic validator - #[validate(enumerate = [5.0, 10.0, 15.0])] + #[validate(r#enum = [5.0, 10.0, 15.0])] // Numeric validator #[validate(multiple_of = 5.0)] #[validate(minimum = 5.0)] @@ -28,7 +28,7 @@ struct TestStruct<'a> { float_value: f32, // Generic validator - #[validate(enumerate = ["12345", "67890"])] + #[validate(r#enum = ["12345", "67890"])] // String validator #[validate(min_length = 5)] #[validate(max_length = 5)] @@ -36,7 +36,7 @@ struct TestStruct<'a> { string_value: String, // Generic validator - #[validate(enumerate = ["12345", "67890"])] + #[validate(r#enum = ["12345", "67890"])] // String validator #[validate(min_length = 5)] #[validate(max_length = 5)] @@ -44,7 +44,7 @@ struct TestStruct<'a> { str_value: &'a str, // Generic validator - #[validate(enumerate = [5, 10, 15])] + #[validate(r#enum = [5, 10, 15])] // Numeric validator #[validate(multiple_of = 5)] #[validate(minimum = 5)] @@ -52,7 +52,7 @@ struct TestStruct<'a> { optional_value: Option, // Generic validator - #[validate(enumerate = [5, 10, 15])] + #[validate(r#enum = [5, 10, 15])] // Array validator #[validate(unique_items)] #[validate(min_items = 3)] @@ -78,7 +78,7 @@ struct TestStruct<'a> { #[derive(Debug, Validate)] struct TestInnerStruct<'a> { // Generic validator - #[validate(enumerate = [5, 10, 15])] + #[validate(r#enum = [5, 10, 15])] // Numeric validator #[validate(multiple_of = 5)] #[validate(minimum = 5)] @@ -88,7 +88,7 @@ struct TestInnerStruct<'a> { inner_int_value: i32, // Generic validator - #[validate(enumerate = [5.0, 10.0, 15.0])] + #[validate(r#enum = [5.0, 10.0, 15.0])] // Numeric validator #[validate(multiple_of = 5.0)] #[validate(minimum = 5.0)] @@ -98,7 +98,7 @@ struct TestInnerStruct<'a> { inner_float_value: f32, // Generic validator - #[validate(enumerate = ["12345", "67890"])] + #[validate(r#enum = ["12345", "67890"])] // String validator #[validate(min_length = 5)] #[validate(max_length = 5)] @@ -106,7 +106,7 @@ struct TestInnerStruct<'a> { inner_string_value: String, // Generic validator - #[validate(enumerate = ["12345", "67890"])] + #[validate(r#enum = ["12345", "67890"])] // String validator #[validate(min_length = 5)] #[validate(max_length = 5)] @@ -114,7 +114,7 @@ struct TestInnerStruct<'a> { inner_str_value: &'a str, // Generic validator - #[validate(enumerate = [5, 10, 15])] + #[validate(r#enum = [5, 10, 15])] // Numeric validator #[validate(multiple_of = 5)] #[validate(minimum = 5)] @@ -122,7 +122,7 @@ struct TestInnerStruct<'a> { inner_optional_value: Option, // Generic validator - #[validate(enumerate = [5, 10, 15])] + #[validate(r#enum = [5, 10, 15])] // Array validator #[validate(unique_items)] #[validate(min_items = 3)] diff --git a/crates/serde_valid/tests/custom_test.rs b/crates/serde_valid/tests/custom_test.rs index 357301db..4cb2fd09 100644 --- a/crates/serde_valid/tests/custom_test.rs +++ b/crates/serde_valid/tests/custom_test.rs @@ -310,7 +310,7 @@ fn filed_custom_validation_using_self() { #[derive(Validate)] struct Pet { - #[validate(enumerate = ["Cat", "Dog"])] + #[validate(r#enum = ["Cat", "Dog"])] kind: String, #[validate(custom = |food| food_validation(&self.kind, food))] diff --git a/crates/serde_valid/tests/data_enum_test.rs b/crates/serde_valid/tests/data_enum_test.rs new file mode 100644 index 00000000..09644c9b --- /dev/null +++ b/crates/serde_valid/tests/data_enum_test.rs @@ -0,0 +1,202 @@ +use serde_json::json; +use serde_valid::Validate; + +#[test] +fn enum_named_enum_validation_is_ok() { + fn ok_enum(_value: &TestEnum) -> Result<(), serde_valid::validation::Error> { + Ok(()) + } + #[derive(Validate)] + #[validate(custom = ok_enum)] + enum TestEnum { + Named { + #[validate] + a: TestStruct, + #[validate] + b: TestStruct, + }, + } + + #[derive(Validate)] + struct TestStruct { + #[validate(minimum = 0)] + #[validate(maximum = 10)] + val: i32, + } + + let s = TestEnum::Named { + a: TestStruct { val: 5 }, + b: TestStruct { val: 5 }, + }; + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_unnamed_variant_validation_is_ok() { + #[derive(Validate)] + enum TestEnum { + UnNamed( + #[validate(minimum = 0)] + #[validate(maximum = 10)] + i32, + #[validate] TestStruct, + ), + } + + #[derive(Validate)] + struct TestStruct { + #[validate(minimum = 0)] + #[validate(maximum = 10)] + val: i32, + } + + let s = TestEnum::UnNamed(5, TestStruct { val: 5 }); + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_newtype_variant_validation_is_ok() { + #[derive(Validate)] + enum TestEnum { + NewType( + #[validate(minimum = 0)] + #[validate(maximum = 10)] + i32, + ), + } + + let s = TestEnum::NewType(15); + assert!(s.validate().is_err()); +} + +#[test] +fn enum_named_enum_validation_is_err() { + fn err_rule(_data: &TestEnum) -> Result<(), serde_valid::validation::Error> { + Err(serde_valid::validation::Error::Custom( + "Rule error.".to_owned(), + )) + } + + #[derive(Validate)] + #[validate(custom = err_rule)] + enum TestEnum { + Named { + #[validate] + a: TestStruct, + #[validate] + b: TestStruct, + }, + } + + #[derive(Validate)] + struct TestStruct { + #[validate(minimum = 0)] + #[validate(maximum = 10)] + val: i32, + } + + let s = TestEnum::Named { + a: TestStruct { val: 12 }, + b: TestStruct { val: 12 }, + }; + assert_eq!( + s.validate().unwrap_err().to_string(), + json!({ + "errors": ["Rule error."], + "properties": { + "a": { + "errors": [], + "properties": { + "val": { + "errors": ["The number must be `<= 10`."] + } + } + }, + "b": { + "errors": [], + "properties": { + "val": { + "errors": ["The number must be `<= 10`."] + } + } + } + } + }) + .to_string() + ); +} + +#[test] +fn enum_unnamed_enum_validation_is_err() { + fn err_rule(_: &TestEnum) -> Result<(), serde_valid::validation::Error> { + Err(serde_valid::validation::Error::Custom( + "Rule error.".to_owned(), + )) + } + + #[derive(Validate)] + #[validate(custom = err_rule)] + enum TestEnum { + Named(#[validate] TestStruct, #[validate] TestStruct), + } + + #[derive(Validate)] + struct TestStruct { + #[validate(minimum = 0)] + #[validate(maximum = 10)] + val: i32, + } + + let s = TestEnum::Named(TestStruct { val: 12 }, TestStruct { val: 12 }); + + assert_eq!( + s.validate().unwrap_err().to_string(), + json!({ + "errors": ["Rule error."], + "items": { + "0": { + "errors": [], + "properties": { + "val": { + "errors": ["The number must be `<= 10`."] + } + } + }, + "1": { + "errors": [], + "properties": { + "val": { + "errors": ["The number must be `<= 10`."] + } + } + } + } + }) + .to_string() + ); +} + +#[test] +fn enum_newtype_variant_validation_is_err() { + fn err_rule(_: &TestEnum) -> Result<(), serde_valid::validation::Error> { + Err(serde_valid::validation::Error::Custom( + "Rule error.".to_owned(), + )) + } + + #[derive(Validate)] + #[validate(custom = err_rule)] + enum TestEnum { + NewType(#[validate(minimum = 5)] u32), + } + + let s = TestEnum::NewType(4); + + assert_eq!( + s.validate().unwrap_err().to_string(), + json!({ + "errors": ["Rule error.", "The number must be `>= 5`."] + }) + .to_string() + ); +} diff --git a/crates/serde_valid/tests/enum_test.rs b/crates/serde_valid/tests/enum_test.rs index 09644c9b..13896d8e 100644 --- a/crates/serde_valid/tests/enum_test.rs +++ b/crates/serde_valid/tests/enum_test.rs @@ -1,124 +1,151 @@ use serde_json::json; -use serde_valid::Validate; +use serde_valid::{Validate, ValidateEnum}; #[test] -fn enum_named_enum_validation_is_ok() { - fn ok_enum(_value: &TestEnum) -> Result<(), serde_valid::validation::Error> { - Ok(()) +fn enum_integer_type() { + #[derive(Validate)] + struct TestStruct { + #[validate(r#enum = [1, 2, 3])] + val: i32, } + + let s = TestStruct { val: 1 }; + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_float_type() { #[derive(Validate)] - #[validate(custom = ok_enum)] - enum TestEnum { - Named { - #[validate] - a: TestStruct, - #[validate] - b: TestStruct, - }, + struct TestStruct { + #[validate(r#enum = [0.3, 1.2, 1.5])] + val: f32, } + let s = TestStruct { val: 0.3 }; + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_str_type() { + #[derive(Validate)] + struct TestStruct<'a> { + #[validate(r#enum = ["a", "b"])] + val: &'a str, + } + + let s = TestStruct { val: "a" }; + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_string_type() { #[derive(Validate)] struct TestStruct { - #[validate(minimum = 0)] - #[validate(maximum = 10)] - val: i32, + #[validate(r#enum = ["a", "b"])] + val: String, } - let s = TestEnum::Named { - a: TestStruct { val: 5 }, - b: TestStruct { val: 5 }, + let s = TestStruct { + val: "a".to_string(), }; assert!(s.validate().is_ok()); } #[test] -fn enum_unnamed_variant_validation_is_ok() { +fn enum_vec_type() { #[derive(Validate)] - enum TestEnum { - UnNamed( - #[validate(minimum = 0)] - #[validate(maximum = 10)] - i32, - #[validate] TestStruct, - ), + struct TestStruct { + #[validate(r#enum = [1, 2, 3, 4, 5])] + val: Vec, } + let s = TestStruct { val: vec![3, 4] }; + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_vec_str_type() { #[derive(Validate)] struct TestStruct { - #[validate(minimum = 0)] - #[validate(maximum = 10)] - val: i32, + #[validate(r#enum = ["1", "2", "3", "4", "5"])] + val: Vec<&'static str>, } - let s = TestEnum::UnNamed(5, TestStruct { val: 5 }); + let s = TestStruct { + val: vec!["3", "4"], + }; assert!(s.validate().is_ok()); } #[test] -fn enum_newtype_variant_validation_is_ok() { +fn enum_vec_string_type() { #[derive(Validate)] - enum TestEnum { - NewType( - #[validate(minimum = 0)] - #[validate(maximum = 10)] - i32, - ), + struct TestStruct { + #[validate(r#enum = ["1", "2", "3", "4", "5"])] + val: Vec, } - let s = TestEnum::NewType(15); - assert!(s.validate().is_err()); + let s = TestStruct { + val: vec!["3".to_owned(), "4".to_owned()], + }; + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_option_type() { + #[derive(Validate)] + struct TestStruct { + #[validate(r#enum = [1, 2, 3])] + val: Option, + } + + let s = TestStruct { val: Some(3) }; + assert!(s.validate().is_ok()); } #[test] -fn enum_named_enum_validation_is_err() { - fn err_rule(_data: &TestEnum) -> Result<(), serde_valid::validation::Error> { - Err(serde_valid::validation::Error::Custom( - "Rule error.".to_owned(), - )) +fn enum_vec_option_type() { + #[derive(Validate)] + struct TestStruct { + #[validate(r#enum = [3])] + val: Vec>, } + let s = TestStruct { val: vec![Some(3)] }; + assert!(s.validate().is_ok()); +} + +#[test] +fn enum_is_err() { #[derive(Validate)] - #[validate(custom = err_rule)] - enum TestEnum { - Named { - #[validate] - a: TestStruct, - #[validate] - b: TestStruct, - }, + struct TestStruct { + #[validate(r#enum = [0.3, 1.2, 1.5])] + val: f32, } + let s = TestStruct { val: 0.1 }; + assert!(s.validate().is_err()); +} + +#[test] +fn enum_err_message() { #[derive(Validate)] struct TestStruct { - #[validate(minimum = 0)] - #[validate(maximum = 10)] + #[validate(r#enum = [1, 2, 3])] val: i32, } - let s = TestEnum::Named { - a: TestStruct { val: 12 }, - b: TestStruct { val: 12 }, - }; + let s = TestStruct { val: 4 }; + assert_eq!( s.validate().unwrap_err().to_string(), json!({ - "errors": ["Rule error."], + "errors": [], "properties": { - "a": { - "errors": [], - "properties": { - "val": { - "errors": ["The number must be `<= 10`."] - } - } - }, - "b": { - "errors": [], - "properties": { - "val": { - "errors": ["The number must be `<= 10`."] - } - } + "val": { + "errors": [ + "The value must be in [1, 2, 3]." + ] } } }) @@ -127,48 +154,54 @@ fn enum_named_enum_validation_is_err() { } #[test] -fn enum_unnamed_enum_validation_is_err() { - fn err_rule(_: &TestEnum) -> Result<(), serde_valid::validation::Error> { - Err(serde_valid::validation::Error::Custom( - "Rule error.".to_owned(), - )) +fn enum_custom_err_message_fn() { + fn error_message(_params: &serde_valid::error::EnumerateError) -> String { + "this is custom message.".to_string() } #[derive(Validate)] - #[validate(custom = err_rule)] - enum TestEnum { - Named(#[validate] TestStruct, #[validate] TestStruct), + struct TestStruct { + #[validate(r#enum = [1, 2, 3], message_fn = error_message)] + val: i32, } + let s = TestStruct { val: 4 }; + + assert_eq!( + s.validate().unwrap_err().to_string(), + json!({ + "errors": [], + "properties": { + "val": { + "errors": [ + "this is custom message." + ] + } + } + }) + .to_string() + ); +} + +#[test] +fn enum_custom_err_message() { #[derive(Validate)] struct TestStruct { - #[validate(minimum = 0)] - #[validate(maximum = 10)] + #[validate(r#enum = [1, 2, 3], message = "this is custom message.")] val: i32, } - let s = TestEnum::Named(TestStruct { val: 12 }, TestStruct { val: 12 }); + let s = TestStruct { val: 4 }; assert_eq!( s.validate().unwrap_err().to_string(), json!({ - "errors": ["Rule error."], - "items": { - "0": { - "errors": [], - "properties": { - "val": { - "errors": ["The number must be `<= 10`."] - } - } - }, - "1": { - "errors": [], - "properties": { - "val": { - "errors": ["The number must be `<= 10`."] - } - } + "errors": [], + "properties": { + "val": { + "errors": [ + "this is custom message." + ] } } }) @@ -177,25 +210,40 @@ fn enum_unnamed_enum_validation_is_err() { } #[test] -fn enum_newtype_variant_validation_is_err() { - fn err_rule(_: &TestEnum) -> Result<(), serde_valid::validation::Error> { - Err(serde_valid::validation::Error::Custom( - "Rule error.".to_owned(), - )) +fn enum_numeric_trait() { + struct MyType(i32); + + impl PartialEq for MyType { + fn eq(&self, other: &i32) -> bool { + self.0.eq(other) + } + } + + impl ValidateEnum for MyType { + fn validate_enum(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumerateError> { + self.0.validate_enum(enumerate) + } } #[derive(Validate)] - #[validate(custom = err_rule)] - enum TestEnum { - NewType(#[validate(minimum = 5)] u32), + struct TestStruct { + #[validate(r#enum = [1, 2, 3], message = "this is custom message.")] + val: MyType, } - let s = TestEnum::NewType(4); + let s = TestStruct { val: MyType(4) }; assert_eq!( s.validate().unwrap_err().to_string(), json!({ - "errors": ["Rule error.", "The number must be `>= 5`."] + "errors": [], + "properties": { + "val": { + "errors": [ + "this is custom message." + ] + } + } }) .to_string() ); diff --git a/crates/serde_valid/tests/enumerate_test.rs b/crates/serde_valid/tests/enumerate_test.rs index cd504cee..239cead7 100644 --- a/crates/serde_valid/tests/enumerate_test.rs +++ b/crates/serde_valid/tests/enumerate_test.rs @@ -1,5 +1,7 @@ +#![allow(deprecated)] + use serde_json::json; -use serde_valid::{Validate, ValidateEnumerate}; +use serde_valid::{Validate, ValidateEnum}; #[test] fn enumerate_integer_type() { @@ -219,9 +221,9 @@ fn enumerate_numeric_trait() { } } - impl ValidateEnumerate for MyType { - fn validate_enumerate(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumerateError> { - self.0.validate_enumerate(enumerate) + impl ValidateEnum for MyType { + fn validate_enum(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumerateError> { + self.0.validate_enum(enumerate) } } diff --git a/crates/serde_valid/tests/hashmap_test.rs b/crates/serde_valid/tests/hashmap_test.rs index 1cf36794..4e1cb2da 100644 --- a/crates/serde_valid/tests/hashmap_test.rs +++ b/crates/serde_valid/tests/hashmap_test.rs @@ -17,7 +17,7 @@ struct TestStruct { hashmap_of_hashmap: HashMap<&'static str, HashMap>, // Generic validator - #[validate(enumerate = [5, 10, 15])] + #[validate(r#enum = [5, 10, 15])] // Numeric validator #[validate(multiple_of = 5)] #[validate(minimum = 5)] diff --git a/crates/serde_valid_derive/src/attribute.rs b/crates/serde_valid_derive/src/attribute.rs index 09fb51b3..7e4886ac 100644 --- a/crates/serde_valid_derive/src/attribute.rs +++ b/crates/serde_valid_derive/src/attribute.rs @@ -14,6 +14,7 @@ macro_rules! count { macro_rules! enum_str { (pub enum $name:ident {}) => { + #[derive(PartialEq, Eq)] pub enum $name { } @@ -41,6 +42,7 @@ macro_rules! enum_str { (pub enum $name:ident { $($variant:ident = $val:literal),*, }) => { + #[derive(PartialEq, Eq)] pub enum $name { $($variant,)* } @@ -116,6 +118,7 @@ enum_str! { MaxProperties = "max_properties", MultipleOf = "multiple_of", Pattern = "pattern", + Enum = "r#enum", Enumerate = "enumerate", Custom = "custom", } diff --git a/crates/serde_valid_derive/src/attribute/field_validate/generic.rs b/crates/serde_valid_derive/src/attribute/field_validate/generic.rs index 983eda92..5331d7d2 100644 --- a/crates/serde_valid_derive/src/attribute/field_validate/generic.rs +++ b/crates/serde_valid_derive/src/attribute/field_validate/generic.rs @@ -1,10 +1,10 @@ mod custom; -mod enumerate; +mod r#enum; mod validate; pub use custom::{ extract_generic_custom_validator_from_meta_list, extract_generic_custom_validator_from_meta_name_value, }; -pub use enumerate::extract_generic_enumerate_validator_from_name_value; +pub use r#enum::extract_generic_enum_validator_from_name_value; pub use validate::extract_generic_validate_validator; diff --git a/crates/serde_valid_derive/src/attribute/field_validate/generic/enumerate.rs b/crates/serde_valid_derive/src/attribute/field_validate/generic/enum.rs similarity index 70% rename from crates/serde_valid_derive/src/attribute/field_validate/generic/enumerate.rs rename to crates/serde_valid_derive/src/attribute/field_validate/generic/enum.rs index c7c13848..c5d51ea0 100644 --- a/crates/serde_valid_derive/src/attribute/field_validate/generic/enumerate.rs +++ b/crates/serde_valid_derive/src/attribute/field_validate/generic/enum.rs @@ -6,17 +6,17 @@ use quote::quote; type Lits<'a> = syn::punctuated::Punctuated; -pub fn extract_generic_enumerate_validator_from_name_value( +pub fn extract_generic_enum_validator_from_name_value( field: &impl Field, name_value: &syn::MetaNameValue, message_format: MessageFormat, rename_map: &RenameMap, ) -> Result { - let lits = get_enumerate_from_name_value(name_value)?; - inner_extract_generic_enumerate_validator(field, &lits, message_format, rename_map) + let lits = get_enum_from_name_value(name_value)?; + inner_extract_generic_enum_validator(field, &lits, message_format, rename_map) } -fn inner_extract_generic_enumerate_validator( +fn inner_extract_generic_enum_validator( field: &impl Field, lits: &Lits, message_format: MessageFormat, @@ -29,7 +29,7 @@ fn inner_extract_generic_enumerate_validator( let errors = field.errors_variable(); Ok(quote!( - if let Err(__composited_error_params) = ::serde_valid::validation::ValidateCompositedEnumerate::validate_composited_enumerate( + if let Err(__composited_error_params) = ::serde_valid::validation::ValidateCompositedEnum::validate_composited_enum( #field_ident, &[#lits], ) { @@ -44,20 +44,18 @@ fn inner_extract_generic_enumerate_validator( )) } -fn get_enumerate_from_name_value( - name_value: &syn::MetaNameValue, -) -> Result, crate::Errors> { +fn get_enum_from_name_value(name_value: &syn::MetaNameValue) -> Result, crate::Errors> { if let syn::Expr::Array(array) = &name_value.value { - let mut enumerate = Lits::new(); + let mut items = Lits::new(); for item in &array.elems { match item { - syn::Expr::Lit(lit) => enumerate.push(lit.lit.clone()), + syn::Expr::Lit(lit) => items.push(lit.lit.clone()), _ => return Err(vec![crate::Error::literal_only(item)]), } } - Ok(enumerate) + Ok(items) } else { - Err(vec![crate::Error::validate_enumerate_need_array( + Err(vec![crate::Error::validate_enum_need_array( &name_value.value, )]) } diff --git a/crates/serde_valid_derive/src/attribute/field_validate/meta.rs b/crates/serde_valid_derive/src/attribute/field_validate/meta.rs index e6be8efe..d2c79dfa 100644 --- a/crates/serde_valid_derive/src/attribute/field_validate/meta.rs +++ b/crates/serde_valid_derive/src/attribute/field_validate/meta.rs @@ -127,7 +127,6 @@ fn inner_extract_field_validator( message_format, rename_map, ) - .map(WithWarnings::new) } (Ok(_), _, _, _) => Err(vec![crate::Error::meta_path_validation_need_value( diff --git a/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs b/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs index 55765422..4286e685 100644 --- a/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs +++ b/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs @@ -1,3 +1,5 @@ +use syn::spanned::Spanned; + use crate::attribute::common::lit::get_lit; use crate::attribute::common::message_format::MessageFormat; use crate::attribute::field_validate::array::{ @@ -5,7 +7,7 @@ use crate::attribute::field_validate::array::{ }; use crate::attribute::field_validate::generic::{ extract_generic_custom_validator_from_meta_name_value, - extract_generic_enumerate_validator_from_name_value, + extract_generic_enum_validator_from_name_value, }; use crate::attribute::field_validate::numeric::{ extract_numeric_exclusive_maximum_validator, extract_numeric_exclusive_minimum_validator, @@ -22,6 +24,7 @@ use crate::attribute::field_validate::string::{ use crate::attribute::{MetaNameValueFieldValidation, Validator}; use crate::serde::rename::RenameMap; use crate::types::Field; +use crate::warning::{Warning, WithWarnings}; pub fn extract_field_validator_from_meta_name_value( field: &impl Field, @@ -29,13 +32,15 @@ pub fn extract_field_validator_from_meta_name_value( validation: &syn::MetaNameValue, message_format: MessageFormat, rename_map: &RenameMap, -) -> Result { +) -> Result, crate::Errors> { match validation_type { MetaNameValueFieldValidation::Minimum => { extract_numeric_minimum_validator(field, &validation.value, message_format, rename_map) + .map(WithWarnings::new) } MetaNameValueFieldValidation::Maximum => { extract_numeric_maximum_validator(field, &validation.value, message_format, rename_map) + .map(WithWarnings::new) } MetaNameValueFieldValidation::ExclusiveMinimum => { extract_numeric_exclusive_minimum_validator( @@ -44,6 +49,7 @@ pub fn extract_field_validator_from_meta_name_value( message_format, rename_map, ) + .map(WithWarnings::new) } MetaNameValueFieldValidation::ExclusiveMaximum => { extract_numeric_exclusive_maximum_validator( @@ -52,22 +58,27 @@ pub fn extract_field_validator_from_meta_name_value( message_format, rename_map, ) + .map(WithWarnings::new) } MetaNameValueFieldValidation::MinLength => { let validation_value = get_lit(&validation.value)?; extract_string_min_length_validator(field, validation_value, message_format, rename_map) + .map(WithWarnings::new) } MetaNameValueFieldValidation::MaxLength => { let validation_value = get_lit(&validation.value)?; extract_string_max_length_validator(field, validation_value, message_format, rename_map) + .map(WithWarnings::new) } MetaNameValueFieldValidation::MinItems => { let validation_value = get_lit(&validation.value)?; extract_array_min_items_validator(field, validation_value, message_format, rename_map) + .map(WithWarnings::new) } MetaNameValueFieldValidation::MaxItems => { let validation_value = get_lit(&validation.value)?; extract_array_max_items_validator(field, validation_value, message_format, rename_map) + .map(WithWarnings::new) } MetaNameValueFieldValidation::MinProperties => { let validation_value = get_lit(&validation.value)?; @@ -77,6 +88,7 @@ pub fn extract_field_validator_from_meta_name_value( message_format, rename_map, ) + .map(WithWarnings::new) } MetaNameValueFieldValidation::MaxProperties => { let validation_value = get_lit(&validation.value)?; @@ -86,6 +98,7 @@ pub fn extract_field_validator_from_meta_name_value( message_format, rename_map, ) + .map(WithWarnings::new) } MetaNameValueFieldValidation::MultipleOf => { let validation_value = get_lit(&validation.value)?; @@ -95,18 +108,36 @@ pub fn extract_field_validator_from_meta_name_value( message_format, rename_map, ) + .map(WithWarnings::new) } MetaNameValueFieldValidation::Pattern => { let validation_value = get_lit(&validation.value)?; extract_string_pattern_validator(field, validation_value, message_format, rename_map) + .map(WithWarnings::new) } + MetaNameValueFieldValidation::Enum => extract_generic_enum_validator_from_name_value( + field, + validation, + message_format, + rename_map, + ) + .map(WithWarnings::new), MetaNameValueFieldValidation::Enumerate => { - extract_generic_enumerate_validator_from_name_value( + let warnings = vec![Warning::Deprecated { + ident: validation.path.segments.first().unwrap().ident.clone(), + note: "🚧 use #[validate(r#enum = ...)] instead of #[validate(enumerate = ...)] 🚧" + .to_string(), + span: validation.path.span(), + }]; + + let validator = extract_generic_enum_validator_from_name_value( field, validation, message_format, rename_map, - ) + )?; + + Ok(WithWarnings::new_with_warnings(validator, warnings)) } MetaNameValueFieldValidation::Custom => { extract_generic_custom_validator_from_meta_name_value( @@ -115,6 +146,7 @@ pub fn extract_field_validator_from_meta_name_value( message_format, rename_map, ) + .map(WithWarnings::new) } } } diff --git a/crates/serde_valid_derive/src/error.rs b/crates/serde_valid_derive/src/error.rs index 28a96b27..71777dbc 100644 --- a/crates/serde_valid_derive/src/error.rs +++ b/crates/serde_valid_derive/src/error.rs @@ -251,7 +251,11 @@ impl Error { pub fn field_validation_type_unknown(path: &syn::Path, unknown: &str) -> Self { let candidates = &(MetaPathFieldValidation::iter().map(|x| x.name())) .chain(MetaListFieldValidation::iter().map(|x| x.name())) - .chain(MetaNameValueFieldValidation::iter().map(|x| x.name())) + .chain( + MetaNameValueFieldValidation::iter() + .filter(|v| v != &MetaNameValueFieldValidation::Enumerate) + .map(|x| x.name()), + ) .unique() .sorted() .collect::>(); @@ -309,10 +313,10 @@ impl Error { ) } - pub fn validate_enumerate_need_array(path: impl Spanned) -> Self { + pub fn validate_enum_need_array(path: impl Spanned) -> Self { Self::new( path.span(), - "#[validate(enumerate = ???)] needs literal array only.", + "#[validate(r#enum = ???)] needs literal array only.", ) } diff --git a/crates/serde_valid_derive/src/warning.rs b/crates/serde_valid_derive/src/warning.rs index 2e057c9e..d01a3fff 100644 --- a/crates/serde_valid_derive/src/warning.rs +++ b/crates/serde_valid_derive/src/warning.rs @@ -107,14 +107,12 @@ impl ToTokens for Warning { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { match self { Self::Deprecated { ident, note, span } => { - let func_name = TokenStream::from_str(&format!( - "__{}_warning", - ident.to_string().to_lowercase() - )) - .unwrap(); + let func_name = + TokenStream::from_str(&format!("__{}", ident.to_string().to_lowercase())) + .unwrap(); quote_spanned!(*span => - #[deprecated(note = #note)] + #[allow(dead_code)] #[allow(clippy::let_unit_value)] fn #func_name() { #[deprecated(note = #note)] From 479bdbfcd3709791962d586fd032b609434dd57a Mon Sep 17 00:00:00 2001 From: ya7010 Date: Tue, 6 Jan 2026 18:10:35 +0900 Subject: [PATCH 2/6] refactor: remove deprecated `validate_enumerate` method and update usage to `ValidateEnumerate` --- crates/serde_valid/src/validation/generic/enum.rs | 5 ----- crates/serde_valid/tests/enumerate_test.rs | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/crates/serde_valid/src/validation/generic/enum.rs b/crates/serde_valid/src/validation/generic/enum.rs index 1fddeb11..f81b43ac 100644 --- a/crates/serde_valid/src/validation/generic/enum.rs +++ b/crates/serde_valid/src/validation/generic/enum.rs @@ -47,11 +47,6 @@ use crate::EnumerateError; /// ``` pub trait ValidateEnum { fn validate_enum(&self, enumerate: &[T]) -> Result<(), EnumerateError>; - - #[deprecated(since = "0.1.0", note = "use `validate_enum` instead")] - fn validate_enumerate(&self, enumerate: &[T]) -> Result<(), EnumerateError> { - self.validate_enum(enumerate) - } } macro_rules! impl_validate_generic_enumerate_literal { diff --git a/crates/serde_valid/tests/enumerate_test.rs b/crates/serde_valid/tests/enumerate_test.rs index 239cead7..105abaac 100644 --- a/crates/serde_valid/tests/enumerate_test.rs +++ b/crates/serde_valid/tests/enumerate_test.rs @@ -1,7 +1,7 @@ #![allow(deprecated)] use serde_json::json; -use serde_valid::{Validate, ValidateEnum}; +use serde_valid::{Validate, ValidateEnumerate}; #[test] fn enumerate_integer_type() { @@ -221,7 +221,7 @@ fn enumerate_numeric_trait() { } } - impl ValidateEnum for MyType { + impl ValidateEnumerate for MyType { fn validate_enum(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumerateError> { self.0.validate_enum(enumerate) } From 37a989c0eb8ccf70c83ce795501e147b2d2977bf Mon Sep 17 00:00:00 2001 From: ya7010 Date: Tue, 6 Jan 2026 18:13:15 +0900 Subject: [PATCH 3/6] refactor: rename `EnumerateError` to `EnumError` and update all references --- crates/serde_valid/src/error.rs | 2 +- crates/serde_valid/src/lib.rs | 6 ++--- crates/serde_valid/src/validation.rs | 7 +++-- .../serde_valid/src/validation/composited.rs | 2 +- crates/serde_valid/src/validation/error.rs | 4 +-- .../src/validation/generic/enum.rs | 26 +++++++++---------- crates/serde_valid/tests/enum_test.rs | 4 +-- crates/serde_valid/tests/enumerate_test.rs | 6 ++--- 8 files changed, 28 insertions(+), 29 deletions(-) diff --git a/crates/serde_valid/src/error.rs b/crates/serde_valid/src/error.rs index be35215e..6ea20c6e 100644 --- a/crates/serde_valid/src/error.rs +++ b/crates/serde_valid/src/error.rs @@ -239,7 +239,7 @@ struct_error_params!( struct_error_params!( #[derive(Debug, Clone)] #[default_message = "The value must be in [{:}]."] - pub struct EnumerateError { + pub struct EnumError { pub enumerate: Vec, } ); diff --git a/crates/serde_valid/src/lib.rs b/crates/serde_valid/src/lib.rs index 9de77812..9c238ae4 100644 --- a/crates/serde_valid/src/lib.rs +++ b/crates/serde_valid/src/lib.rs @@ -579,9 +579,9 @@ pub mod utils; pub mod validation; pub use error::{ - EnumerateError, Error, ExclusiveMaximumError, ExclusiveMinimumError, MaxItemsError, - MaxLengthError, MaxPropertiesError, MaximumError, MinItemsError, MinLengthError, - MinPropertiesError, MinimumError, MultipleOfError, PatternError, UniqueItemsError, + EnumError, Error, ExclusiveMaximumError, ExclusiveMinimumError, MaxItemsError, MaxLengthError, + MaxPropertiesError, MaximumError, MinItemsError, MinLengthError, MinPropertiesError, + MinimumError, MultipleOfError, PatternError, UniqueItemsError, }; #[allow(unused_imports)] pub use features::*; diff --git a/crates/serde_valid/src/validation.rs b/crates/serde_valid/src/validation.rs index 741a21bb..ed318300 100644 --- a/crates/serde_valid/src/validation.rs +++ b/crates/serde_valid/src/validation.rs @@ -8,9 +8,8 @@ mod object; mod string; use crate::{ - EnumerateError, ExclusiveMaximumError, ExclusiveMinimumError, MaxLengthError, - MaxPropertiesError, MaximumError, MinLengthError, MinPropertiesError, MinimumError, - MultipleOfError, PatternError, + EnumError, ExclusiveMaximumError, ExclusiveMinimumError, MaxLengthError, MaxPropertiesError, + MaximumError, MinLengthError, MinPropertiesError, MinimumError, MultipleOfError, PatternError, }; pub use composited::Composited; @@ -418,6 +417,6 @@ impl_composited_validation_1args!( // Generic impl_composited_validation_1args!( pub trait ValidateCompositedEnum { - fn validate_composited_enum(&self, enumerate: T) -> Result<(), Composited>; + fn validate_composited_enum(&self, enumerate: T) -> Result<(), Composited>; } ); diff --git a/crates/serde_valid/src/validation/composited.rs b/crates/serde_valid/src/validation/composited.rs index f50712b3..5fdc39ff 100644 --- a/crates/serde_valid/src/validation/composited.rs +++ b/crates/serde_valid/src/validation/composited.rs @@ -1,7 +1,7 @@ use crate::validation::error::IntoError; use crate::error::{ - EnumerateError, ExclusiveMaximumError, ExclusiveMinimumError, MaxItemsError, MaxLengthError, + EnumError, ExclusiveMaximumError, ExclusiveMinimumError, MaxItemsError, MaxLengthError, MaxPropertiesError, MaximumError, MinItemsError, MinLengthError, MinPropertiesError, MinimumError, MultipleOfError, PatternError, UniqueItemsError, }; diff --git a/crates/serde_valid/src/validation/error.rs b/crates/serde_valid/src/validation/error.rs index dfd87a5c..de87a478 100644 --- a/crates/serde_valid/src/validation/error.rs +++ b/crates/serde_valid/src/validation/error.rs @@ -8,7 +8,7 @@ mod object_errors; use std::borrow::Cow; pub use crate::error::{ - EnumerateError, ExclusiveMaximumError, ExclusiveMinimumError, MaxItemsError, MaxLengthError, + EnumError, ExclusiveMaximumError, ExclusiveMinimumError, MaxItemsError, MaxLengthError, MaxPropertiesError, MaximumError, MinItemsError, MinLengthError, MinPropertiesError, MinimumError, MultipleOfError, PatternError, UniqueItemsError, }; @@ -77,7 +77,7 @@ pub enum Error { #[error("{0}")] #[serde(serialize_with = "serialize_error_message")] - Enumerate(Message), + Enumerate(Message), #[error("{0}")] #[serde(serialize_with = "serialize_error_message")] diff --git a/crates/serde_valid/src/validation/generic/enum.rs b/crates/serde_valid/src/validation/generic/enum.rs index f81b43ac..c62da8dc 100644 --- a/crates/serde_valid/src/validation/generic/enum.rs +++ b/crates/serde_valid/src/validation/generic/enum.rs @@ -1,5 +1,5 @@ use crate::validation::ValidateCompositedEnum; -use crate::EnumerateError; +use crate::EnumError; /// Enumerate validation. /// @@ -17,7 +17,7 @@ use crate::EnumerateError; /// fn validate_enum( /// &self, /// enumerate: &[&'static str], -/// ) -> Result<(), serde_valid::EnumerateError> { +/// ) -> Result<(), serde_valid::EnumError> { /// self.0.validate_enum(enumerate) /// } /// } @@ -46,17 +46,17 @@ use crate::EnumerateError; /// ); /// ``` pub trait ValidateEnum { - fn validate_enum(&self, enumerate: &[T]) -> Result<(), EnumerateError>; + fn validate_enum(&self, candidates: &[T]) -> Result<(), EnumError>; } macro_rules! impl_validate_generic_enumerate_literal { ($type:ty) => { impl ValidateEnum<$type> for $type { - fn validate_enum(&self, enumerate: &[$type]) -> Result<(), EnumerateError> { - if enumerate.iter().any(|candidate| candidate == self) { + fn validate_enum(&self, candidates: &[$type]) -> Result<(), EnumError> { + if candidates.iter().any(|candidate| candidate == self) { Ok(()) } else { - Err(EnumerateError::new(enumerate)) + Err(EnumError::new(candidates)) } } } @@ -68,7 +68,7 @@ macro_rules! impl_validate_generic_enumerate_literal { fn validate_composited_enum( &self, limit: &[$type], - ) -> Result<(), crate::validation::Composited> { + ) -> Result<(), crate::validation::Composited> { self.validate_enum(limit) .map_err(|error| crate::validation::Composited::Single(error)) } @@ -111,11 +111,11 @@ impl_validate_generic_enumerate_literal!(char); macro_rules! impl_validate_generic_enumerate_str { ($type:ty) => { impl ValidateEnum<&'static str> for $type { - fn validate_enum(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> { - if enumerate.iter().any(|candidate| candidate == self) { + fn validate_enum(&self, candidates: &[&'static str]) -> Result<(), EnumError> { + if candidates.iter().any(|candidate| candidate == self) { Ok(()) } else { - Err(EnumerateError::new(enumerate)) + Err(EnumError::new(candidates)) } } } @@ -131,14 +131,14 @@ impl_validate_generic_enumerate_str!(std::ffi::OsString); macro_rules! impl_validate_generic_enumerate_path { ($type:ty) => { impl ValidateEnum<&'static str> for $type { - fn validate_enum(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> { + fn validate_enum(&self, enumerate: &[&'static str]) -> Result<(), EnumError> { if enumerate .iter() .any(|candidate| &std::path::Path::new(candidate) == self) { Ok(()) } else { - Err(EnumerateError::new(enumerate)) + Err(EnumError::new(enumerate)) } } } @@ -155,7 +155,7 @@ where fn validate_composited_enum( &self, limit: &[&'static str], - ) -> Result<(), crate::validation::Composited> { + ) -> Result<(), crate::validation::Composited> { self.validate_enum(limit) .map_err(crate::validation::Composited::Single) } diff --git a/crates/serde_valid/tests/enum_test.rs b/crates/serde_valid/tests/enum_test.rs index 13896d8e..b7d3642f 100644 --- a/crates/serde_valid/tests/enum_test.rs +++ b/crates/serde_valid/tests/enum_test.rs @@ -155,7 +155,7 @@ fn enum_err_message() { #[test] fn enum_custom_err_message_fn() { - fn error_message(_params: &serde_valid::error::EnumerateError) -> String { + fn error_message(_params: &serde_valid::error::EnumError) -> String { "this is custom message.".to_string() } @@ -220,7 +220,7 @@ fn enum_numeric_trait() { } impl ValidateEnum for MyType { - fn validate_enum(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumerateError> { + fn validate_enum(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumError> { self.0.validate_enum(enumerate) } } diff --git a/crates/serde_valid/tests/enumerate_test.rs b/crates/serde_valid/tests/enumerate_test.rs index 105abaac..d59c7a8d 100644 --- a/crates/serde_valid/tests/enumerate_test.rs +++ b/crates/serde_valid/tests/enumerate_test.rs @@ -157,7 +157,7 @@ fn enumerate_err_message() { #[test] fn enumerate_custom_err_message_fn() { - fn error_message(_params: &serde_valid::error::EnumerateError) -> String { + fn error_message(_params: &serde_valid::error::EnumError) -> String { "this is custom message.".to_string() } @@ -222,8 +222,8 @@ fn enumerate_numeric_trait() { } impl ValidateEnumerate for MyType { - fn validate_enum(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumerateError> { - self.0.validate_enum(enumerate) + fn validate_enum(&self, items: &[i32]) -> Result<(), serde_valid::EnumError> { + self.0.validate_enum(items) } } From cd55d4d3c427dc4f7483e5d1b3a7db744473a247 Mon Sep 17 00:00:00 2001 From: ya7010 Date: Tue, 6 Jan 2026 18:14:42 +0900 Subject: [PATCH 4/6] refactor: rename `Enumerate` to `Enum` in error handling and localization --- crates/serde_valid/src/error.rs | 2 +- crates/serde_valid/src/features/fluent/localize.rs | 2 +- crates/serde_valid/src/features/fluent/try_localize.rs | 2 +- crates/serde_valid/src/validation/composited.rs | 2 +- crates/serde_valid/src/validation/error.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/serde_valid/src/error.rs b/crates/serde_valid/src/error.rs index 6ea20c6e..92cae6cd 100644 --- a/crates/serde_valid/src/error.rs +++ b/crates/serde_valid/src/error.rs @@ -240,6 +240,6 @@ struct_error_params!( #[derive(Debug, Clone)] #[default_message = "The value must be in [{:}]."] pub struct EnumError { - pub enumerate: Vec, + pub candidates: Vec, } ); diff --git a/crates/serde_valid/src/features/fluent/localize.rs b/crates/serde_valid/src/features/fluent/localize.rs index d2cd3524..bf10c427 100644 --- a/crates/serde_valid/src/features/fluent/localize.rs +++ b/crates/serde_valid/src/features/fluent/localize.rs @@ -115,7 +115,7 @@ impl Localize for crate::validation::Error { Self::UniqueItems(message) => message.localize(bundle), Self::MinProperties(message) => message.localize(bundle), Self::MaxProperties(message) => message.localize(bundle), - Self::Enumerate(message) => message.localize(bundle), + Self::Enum(message) => message.localize(bundle), Self::Custom(message) => LocalizedError::String(message.to_string()), Self::Items(message) => LocalizedError::Items(message.localize(bundle)), Self::Properties(message) => LocalizedError::Properties(message.localize(bundle)), diff --git a/crates/serde_valid/src/features/fluent/try_localize.rs b/crates/serde_valid/src/features/fluent/try_localize.rs index 0acd11b6..f00e2ba5 100644 --- a/crates/serde_valid/src/features/fluent/try_localize.rs +++ b/crates/serde_valid/src/features/fluent/try_localize.rs @@ -183,7 +183,7 @@ impl TryLocalize for crate::validation::Error { Self::UniqueItems(message) => message.try_localize(bundle), Self::MinProperties(message) => message.try_localize(bundle), Self::MaxProperties(message) => message.try_localize(bundle), - Self::Enumerate(message) => message.try_localize(bundle), + Self::Enum(message) => message.try_localize(bundle), Self::Custom(message) => Ok(LocalizedError::String(message.to_string())), Self::Items(message) => Ok(LocalizedError::Items(message.try_localize(bundle)?)), Self::Properties(message) => { diff --git a/crates/serde_valid/src/validation/composited.rs b/crates/serde_valid/src/validation/composited.rs index 5fdc39ff..bbb1b8c7 100644 --- a/crates/serde_valid/src/validation/composited.rs +++ b/crates/serde_valid/src/validation/composited.rs @@ -55,7 +55,7 @@ macro_rules! impl_into_error { } // Global -impl_into_error!(Enumerate); +impl_into_error!(Enum); // Numeric impl_into_error!(Maximum); diff --git a/crates/serde_valid/src/validation/error.rs b/crates/serde_valid/src/validation/error.rs index de87a478..30b0df5f 100644 --- a/crates/serde_valid/src/validation/error.rs +++ b/crates/serde_valid/src/validation/error.rs @@ -77,7 +77,7 @@ pub enum Error { #[error("{0}")] #[serde(serialize_with = "serialize_error_message")] - Enumerate(Message), + Enum(Message), #[error("{0}")] #[serde(serialize_with = "serialize_error_message")] From 4979e7774849fdfdf7ddd1fd3693cd9cd36fc476 Mon Sep 17 00:00:00 2001 From: ya7010 Date: Tue, 6 Jan 2026 18:15:33 +0900 Subject: [PATCH 5/6] refactor: remove `ValidateEnumerate` and update references to `ValidateEnum` --- crates/serde_valid/src/lib.rs | 6 +++--- crates/serde_valid/src/validation.rs | 2 +- crates/serde_valid/src/validation/generic.rs | 2 +- crates/serde_valid/tests/enumerate_test.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/serde_valid/src/lib.rs b/crates/serde_valid/src/lib.rs index 9c238ae4..3708c1d9 100644 --- a/crates/serde_valid/src/lib.rs +++ b/crates/serde_valid/src/lib.rs @@ -588,9 +588,9 @@ pub use features::*; use indexmap::IndexMap; use std::{borrow::Cow, collections::HashMap}; pub use validation::{ - ValidateEnum, ValidateEnumerate, ValidateExclusiveMaximum, ValidateExclusiveMinimum, - ValidateMaxItems, ValidateMaxLength, ValidateMaxProperties, ValidateMaximum, ValidateMinItems, - ValidateMinLength, ValidateMinProperties, ValidateMinimum, ValidateMultipleOf, ValidatePattern, + ValidateEnum, ValidateExclusiveMaximum, ValidateExclusiveMinimum, ValidateMaxItems, + ValidateMaxLength, ValidateMaxProperties, ValidateMaximum, ValidateMinItems, ValidateMinLength, + ValidateMinProperties, ValidateMinimum, ValidateMultipleOf, ValidatePattern, ValidateUniqueItems, }; diff --git a/crates/serde_valid/src/validation.rs b/crates/serde_valid/src/validation.rs index ed318300..4b22402d 100644 --- a/crates/serde_valid/src/validation.rs +++ b/crates/serde_valid/src/validation.rs @@ -18,7 +18,7 @@ pub use error::{ ArrayErrors, Error, Errors, IntoError, ItemErrorsMap, ItemVecErrorsMap, ObjectErrors, PropertyErrorsMap, PropertyVecErrorsMap, VecErrors, }; -pub use generic::{ValidateEnum, ValidateEnumerate}; +pub use generic::ValidateEnum; use indexmap::IndexMap; pub use numeric::{ ValidateExclusiveMaximum, ValidateExclusiveMinimum, ValidateMaximum, ValidateMinimum, diff --git a/crates/serde_valid/src/validation/generic.rs b/crates/serde_valid/src/validation/generic.rs index c96444b2..5bfcc886 100644 --- a/crates/serde_valid/src/validation/generic.rs +++ b/crates/serde_valid/src/validation/generic.rs @@ -1,2 +1,2 @@ mod r#enum; -pub use r#enum::{ValidateEnum, ValidateEnum as ValidateEnumerate}; +pub use r#enum::ValidateEnum; diff --git a/crates/serde_valid/tests/enumerate_test.rs b/crates/serde_valid/tests/enumerate_test.rs index d59c7a8d..65195300 100644 --- a/crates/serde_valid/tests/enumerate_test.rs +++ b/crates/serde_valid/tests/enumerate_test.rs @@ -1,7 +1,7 @@ #![allow(deprecated)] use serde_json::json; -use serde_valid::{Validate, ValidateEnumerate}; +use serde_valid::{Validate, ValidateEnum}; #[test] fn enumerate_integer_type() { @@ -221,7 +221,7 @@ fn enumerate_numeric_trait() { } } - impl ValidateEnumerate for MyType { + impl ValidateEnum for MyType { fn validate_enum(&self, items: &[i32]) -> Result<(), serde_valid::EnumError> { self.0.validate_enum(items) } From 794c04517173f7cb730e726fe1682dbc13f7c9d2 Mon Sep 17 00:00:00 2001 From: ya7010 Date: Tue, 6 Jan 2026 18:18:18 +0900 Subject: [PATCH 6/6] refactor: rename `enumerate` to `candidates` in validation methods for consistency --- crates/serde_valid/src/validation.rs | 2 +- crates/serde_valid/src/validation/generic/enum.rs | 10 +++++----- crates/serde_valid/tests/enum_test.rs | 4 ++-- .../attribute/field_validate/meta/meta_name_value.rs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/serde_valid/src/validation.rs b/crates/serde_valid/src/validation.rs index 4b22402d..a35cf54b 100644 --- a/crates/serde_valid/src/validation.rs +++ b/crates/serde_valid/src/validation.rs @@ -417,6 +417,6 @@ impl_composited_validation_1args!( // Generic impl_composited_validation_1args!( pub trait ValidateCompositedEnum { - fn validate_composited_enum(&self, enumerate: T) -> Result<(), Composited>; + fn validate_composited_enum(&self, candidates: T) -> Result<(), Composited>; } ); diff --git a/crates/serde_valid/src/validation/generic/enum.rs b/crates/serde_valid/src/validation/generic/enum.rs index c62da8dc..c0ed11df 100644 --- a/crates/serde_valid/src/validation/generic/enum.rs +++ b/crates/serde_valid/src/validation/generic/enum.rs @@ -16,9 +16,9 @@ use crate::EnumError; /// impl ValidateEnum<&'static str> for MyType { /// fn validate_enum( /// &self, -/// enumerate: &[&'static str], +/// candidates: &[&'static str], /// ) -> Result<(), serde_valid::EnumError> { -/// self.0.validate_enum(enumerate) +/// self.0.validate_enum(candidates) /// } /// } /// @@ -131,14 +131,14 @@ impl_validate_generic_enumerate_str!(std::ffi::OsString); macro_rules! impl_validate_generic_enumerate_path { ($type:ty) => { impl ValidateEnum<&'static str> for $type { - fn validate_enum(&self, enumerate: &[&'static str]) -> Result<(), EnumError> { - if enumerate + fn validate_enum(&self, candidates: &[&'static str]) -> Result<(), EnumError> { + if candidates .iter() .any(|candidate| &std::path::Path::new(candidate) == self) { Ok(()) } else { - Err(EnumError::new(enumerate)) + Err(EnumError::new(candidates)) } } } diff --git a/crates/serde_valid/tests/enum_test.rs b/crates/serde_valid/tests/enum_test.rs index b7d3642f..33222fe4 100644 --- a/crates/serde_valid/tests/enum_test.rs +++ b/crates/serde_valid/tests/enum_test.rs @@ -220,8 +220,8 @@ fn enum_numeric_trait() { } impl ValidateEnum for MyType { - fn validate_enum(&self, enumerate: &[i32]) -> Result<(), serde_valid::EnumError> { - self.0.validate_enum(enumerate) + fn validate_enum(&self, candidates: &[i32]) -> Result<(), serde_valid::EnumError> { + self.0.validate_enum(candidates) } } diff --git a/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs b/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs index 4286e685..f456579d 100644 --- a/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs +++ b/crates/serde_valid_derive/src/attribute/field_validate/meta/meta_name_value.rs @@ -125,7 +125,7 @@ pub fn extract_field_validator_from_meta_name_value( MetaNameValueFieldValidation::Enumerate => { let warnings = vec![Warning::Deprecated { ident: validation.path.segments.first().unwrap().ident.clone(), - note: "🚧 use #[validate(r#enum = ...)] instead of #[validate(enumerate = ...)] 🚧" + note: "🚧 Please use `#[validate(r#enum = ...)]` instead of `#[validate(enumerate = ...)]` 🚧" .to_string(), span: validation.path.span(), }];