Skip to content

Commit

Permalink
refactor: field struct validator.
Browse files Browse the repository at this point in the history
  • Loading branch information
yassun7010 committed Jan 8, 2024
1 parent b8b7889 commit 484bb5a
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 197 deletions.
2 changes: 2 additions & 0 deletions serde_valid_derive/src/field_validate/generic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod custom;
mod enumerate;
mod validate;

pub use custom::extract_generic_custom_validator;
pub use enumerate::extract_generic_enumerate_validator;
pub use validate::extract_generic_validate_validator;
35 changes: 35 additions & 0 deletions serde_valid_derive/src/field_validate/generic/validate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::field_validate::Validator;
use crate::serde::rename::RenameMap;
use crate::types::Field;
use quote::quote;

pub fn extract_generic_validate_validator(
field: &impl Field,
rename_map: &RenameMap,
) -> Result<Validator, crate::Errors> {
let field_ident = field.ident();
let field_name = field.name();
let field_key = field.key();
let rename = rename_map.get(field_name).unwrap_or(&field_key);
let errors = field.errors_variable();

Ok(quote!(
if let Err(__inner_errors) = #field_ident.validate() {
match __inner_errors {
::serde_valid::validation::Errors::Object(__object_errors) => {
#errors.entry(#rename).or_default().push(
::serde_valid::validation::Error::Properties(__object_errors)
);
}
::serde_valid::validation::Errors::Array(__array_errors) => {
#errors.entry(#rename).or_default().push(
::serde_valid::validation::Error::Items(__array_errors)
);
}
::serde_valid::validation::Errors::NewType(__new_type_errors) => {
#errors.entry(#rename).or_default().extend(__new_type_errors);
}
}
}
))
}
138 changes: 129 additions & 9 deletions serde_valid_derive/src/field_validate/meta.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,150 @@
mod meta_list;
mod meta_name_value;
mod meta_path;
mod nested_meta_list;
mod nested_meta_name_value;
mod nested_meta_path;

use crate::field_validate::Validator;
use crate::field_validate::common::{extract_custom_message_tokens, CustomMessageToken};
use crate::field_validate::{
MetaListFieldValidation, MetaNameValueFieldValidation, MetaPathFieldValidation, Validator,
};
use crate::serde::rename::RenameMap;
use crate::types::Field;
use crate::types::SingleIdentPath;
use meta_list::extract_field_validator_from_meta_list;
use meta_name_value::extract_field_validator_from_meta_name_value;
use meta_path::extract_field_validator_from_meta_path;
use std::str::FromStr;

use self::meta_list::extract_field_validator_from_meta_list;
use super::generic::extract_generic_validate_validator;

pub fn extract_field_validator(
field: &impl Field,
attribute: &syn::Attribute,
rename_map: &RenameMap,
) -> Result<Validator, crate::Errors> {
match &attribute.meta {
syn::Meta::List(list) => {
extract_field_validator_from_meta_list(field, attribute, list, rename_map)
}
syn::Meta::Path(_) => extract_field_validator_from_meta_path(field, rename_map),
syn::Meta::List(list) => inner_extract_field_validator(field, attribute, list, rename_map),
syn::Meta::Path(_) => extract_generic_validate_validator(field, rename_map),
syn::Meta::NameValue(name_value) => {
Err(vec![crate::Error::validate_meta_name_value_not_support(
name_value,
)])
}
}
}

fn inner_extract_field_validator(
field: &impl Field,
attribute: &syn::Attribute,
meta_list: &syn::MetaList,
rename_map: &RenameMap,
) -> Result<Validator, crate::Errors> {
let mut errors = vec![];
let nested = meta_list
.parse_args_with(crate::types::CommaSeparatedMetas::parse_terminated)
.map_err(|error| {
vec![crate::Error::validate_attribute_parse_error(
attribute, &error,
)]
})?;

let custom_message = match nested.len() {
0 => Err(vec![crate::Error::field_validation_type_required(
attribute,
)])?,
1 => CustomMessageToken::default(),
2 => match extract_custom_message_tokens(&nested[1]) {
Ok(custom_message) => custom_message,
Err(message_fn_errors) => {
errors.extend(message_fn_errors);
CustomMessageToken::default()
}
},
_ => {
for meta in nested.iter().skip(2) {
errors.push(crate::Error::too_many_list_items(meta));
}
CustomMessageToken::default()
}
};

let meta = &nested[0];

let validation_path = match meta {
syn::Meta::Path(path) => path,
syn::Meta::List(list) => &list.path,
syn::Meta::NameValue(name_value) => &name_value.path,
};

let validation_name = SingleIdentPath::new(validation_path).ident().to_string();

let validator = match (
MetaPathFieldValidation::from_str(&validation_name),
MetaListFieldValidation::from_str(&validation_name),
MetaNameValueFieldValidation::from_str(&validation_name),
meta,
) {
(Ok(validation_type), _, _, syn::Meta::Path(validation)) => {
extract_field_validator_from_meta_path(
field,
validation_type,
validation,
custom_message,
rename_map,
)
}

(_, Ok(validation_type), _, syn::Meta::List(validation)) => {
extract_field_validator_from_meta_list(
field,
validation_type,
validation,
custom_message,
rename_map,
)
}

(_, _, Ok(validation_type), syn::Meta::NameValue(validation)) => {
extract_field_validator_from_meta_name_value(
field,
validation_type,
validation,
custom_message,
rename_map,
)
}

(Ok(_), _, _, _) => Err(vec![crate::Error::meta_path_validation_need_value(
validation_path,
&validation_name,
)]),

(_, Ok(_), _, _) => Err(vec![crate::Error::meta_list_validation_need_value(
validation_path,
&validation_name,
)]),

(_, _, Ok(_), _) => Err(vec![crate::Error::meta_name_value_validation_need_value(
validation_path,
&validation_name,
)]),

_ => Err(vec![crate::Error::field_validation_type_unknown(
validation_path,
&validation_name,
)]),
};

match validator {
Ok(validator) => {
if errors.is_empty() {
Ok(validator)
} else {
Err(errors)
}
}
Err(validator_errors) => {
errors.extend(validator_errors);
Err(errors)
}
}
}
129 changes: 13 additions & 116 deletions serde_valid_derive/src/field_validate/meta/meta_list.rs
Original file line number Diff line number Diff line change
@@ -1,127 +1,24 @@
use super::nested_meta_list::extract_field_validator_from_nested_meta_list;
use super::nested_meta_name_value::extract_field_validator_from_nested_meta_name_value;
use super::nested_meta_path::extract_field_validator_from_nested_meta_path;
use crate::field_validate::common::{extract_custom_message_tokens, CustomMessageToken};
use crate::field_validate::{
MetaListFieldValidation, MetaNameValueFieldValidation, MetaPathFieldValidation, Validator,
use crate::field_validate::common::{CustomMessageToken, MetaListFieldValidation};
use crate::field_validate::generic::{
extract_generic_custom_validator, extract_generic_enumerate_validator,
};
use crate::field_validate::Validator;
use crate::serde::rename::RenameMap;
use crate::types::{Field, SingleIdentPath};
use std::str::FromStr;
use crate::types::Field;

pub fn extract_field_validator_from_meta_list(
field: &impl Field,
attribute: &syn::Attribute,
meta_list: &syn::MetaList,
validation_type: MetaListFieldValidation,
validation: &syn::MetaList,
custom_message: CustomMessageToken,
rename_map: &RenameMap,
) -> Result<Validator, crate::Errors> {
let mut errors = vec![];
let nested = meta_list
.parse_args_with(crate::types::CommaSeparatedMetas::parse_terminated)
.map_err(|error| {
vec![crate::Error::validate_attribute_parse_error(
attribute, &error,
)]
})?;

let custom_message = match nested.len() {
0 => Err(vec![crate::Error::field_validation_type_required(
attribute,
)])?,
1 => CustomMessageToken::default(),
2 => match extract_custom_message_tokens(&nested[1]) {
Ok(custom_message) => custom_message,
Err(message_fn_errors) => {
errors.extend(message_fn_errors);
CustomMessageToken::default()
}
},
_ => {
for meta in nested.iter().skip(2) {
errors.push(crate::Error::too_many_list_items(meta));
}
CustomMessageToken::default()
}
};

let meta = &nested[0];

let validation_path = match meta {
syn::Meta::Path(path) => path,
syn::Meta::List(list) => &list.path,
syn::Meta::NameValue(name_value) => &name_value.path,
};

let validation_name = SingleIdentPath::new(validation_path).ident().to_string();

let validator = match (
MetaPathFieldValidation::from_str(&validation_name),
MetaListFieldValidation::from_str(&validation_name),
MetaNameValueFieldValidation::from_str(&validation_name),
meta,
) {
(Ok(validation_type), _, _, syn::Meta::Path(validation)) => {
extract_field_validator_from_nested_meta_path(
field,
validation_type,
validation,
custom_message,
rename_map,
)
}

(_, Ok(validation_type), _, syn::Meta::List(validation)) => {
extract_field_validator_from_nested_meta_list(
field,
validation_type,
validation,
custom_message,
rename_map,
)
}

(_, _, Ok(validation_type), syn::Meta::NameValue(validation)) => {
extract_field_validator_from_nested_meta_name_value(
field,
validation_type,
validation,
custom_message,
rename_map,
)
}

(Ok(_), _, _, _) => Err(vec![crate::Error::meta_path_validation_need_value(
validation_path,
&validation_name,
)]),

(_, Ok(_), _, _) => Err(vec![crate::Error::meta_list_validation_need_value(
validation_path,
&validation_name,
)]),

(_, _, Ok(_), _) => Err(vec![crate::Error::meta_name_value_validation_need_value(
validation_path,
&validation_name,
)]),

_ => Err(vec![crate::Error::field_validation_type_unknown(
validation_path,
&validation_name,
)]),
};

match validator {
Ok(validator) => {
if errors.is_empty() {
Ok(validator)
} else {
Err(errors)
}
match validation_type {
MetaListFieldValidation::Enumerate => {
extract_generic_enumerate_validator(field, validation, custom_message, rename_map)
}
Err(validator_errors) => {
errors.extend(validator_errors);
Err(errors)
MetaListFieldValidation::Custom => {
extract_generic_custom_validator(field, validation, rename_map)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::field_validate::Validator;
use crate::serde::rename::RenameMap;
use crate::types::Field;

pub fn extract_field_validator_from_nested_meta_name_value(
pub fn extract_field_validator_from_meta_name_value(
field: &impl Field,
validation_type: MetaNameValueFieldValidation,
validation: &syn::MetaNameValue,
Expand Down
Loading

0 comments on commit 484bb5a

Please sign in to comment.