aboutsummaryrefslogtreecommitdiffstats
path: root/validator_derive/src/quoting.rs
diff options
context:
space:
mode:
Diffstat (limited to 'validator_derive/src/quoting.rs')
-rw-r--r--validator_derive/src/quoting.rs70
1 files changed, 56 insertions, 14 deletions
diff --git a/validator_derive/src/quoting.rs b/validator_derive/src/quoting.rs
index 20ca7a7..b47db6a 100644
--- a/validator_derive/src/quoting.rs
+++ b/validator_derive/src/quoting.rs
@@ -40,13 +40,25 @@ impl FieldQuoter {
}
}
+ pub fn quote_validator_field(&self) -> proc_macro2::TokenStream {
+ let ident = &self.ident;
+
+ if self._type.starts_with("Option<") || self._type.starts_with("Vec<") {
+ quote!(#ident)
+ } else if COW_TYPE.is_match(&self._type.as_ref()) {
+ quote!(self.#ident.as_ref())
+ } else {
+ quote!(self.#ident)
+ }
+ }
+
pub fn get_optional_validator_param(&self) -> proc_macro2::TokenStream {
let ident = &self.ident;
if self._type.starts_with("Option<&") || self._type.starts_with("Option<Option<&")
|| NUMBER_TYPES.contains(&self._type.as_ref()) {
- quote!(#ident)
+ quote!(#ident)
} else {
- quote!(ref #ident)
+ quote!(ref #ident)
}
}
@@ -71,6 +83,27 @@ impl FieldQuoter {
tokens
}
+
+
+ /// Wrap the quoted output of a validation with a for loop if
+ /// the field type is a vector
+ pub fn wrap_if_vector(&self, tokens: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
+ let field_ident = &self.ident;
+ let field_name = &self.name;
+ if self._type.starts_with("Vec<") {
+ return quote!(
+ if !::validator::ValidationErrors::has_error(&result, #field_name) {
+ let results: Vec<_> = self.#field_ident.iter().map(|#field_ident| {
+ let mut result = ::std::result::Result::Ok(());
+ #tokens
+ result
+ }).collect();
+ result = ::validator::ValidationErrors::merge_all(result, #field_name, results);
+ })
+ }
+
+ tokens
+ }
}
/// Quote an actual end-user error creation automatically
@@ -326,24 +359,33 @@ pub fn quote_regex_validation(field_quoter: &FieldQuoter, validation: &FieldVali
unreachable!();
}
-pub fn quote_field_validation(field_quoter: &FieldQuoter, validation: &FieldValidation) -> proc_macro2::TokenStream {
+pub fn quote_nested_validation(field_quoter: &FieldQuoter) -> proc_macro2::TokenStream {
+ let field_name = &field_quoter.name;
+ let validator_field = field_quoter.quote_validator_field();
+ let quoted = quote!(result = ::validator::ValidationErrors::merge(result, #field_name, #validator_field.validate()););
+ field_quoter.wrap_if_option(field_quoter.wrap_if_vector(quoted))
+}
+
+pub fn quote_field_validation(field_quoter: &FieldQuoter, validation: &FieldValidation,
+ validations: &mut Vec<proc_macro2::TokenStream>,
+ nested_validations: &mut Vec<proc_macro2::TokenStream>) {
match validation.validator {
- Validator::Length {..} => quote_length_validation(&field_quoter, validation),
- Validator::Range {..} => quote_range_validation(&field_quoter, validation),
- Validator::Email => quote_email_validation(&field_quoter, validation),
- Validator::Url => quote_url_validation(&field_quoter, validation),
- Validator::MustMatch(_) => quote_must_match_validation(&field_quoter, validation),
- Validator::Custom(_) => quote_custom_validation(&field_quoter, validation),
- Validator::Contains(_) => quote_contains_validation(&field_quoter, validation),
- Validator::Regex(_) => quote_regex_validation(&field_quoter, validation),
+ Validator::Length {..} => validations.push(quote_length_validation(&field_quoter, validation)),
+ Validator::Range {..} => validations.push(quote_range_validation(&field_quoter, validation)),
+ Validator::Email => validations.push(quote_email_validation(&field_quoter, validation)),
+ Validator::Url => validations.push(quote_url_validation(&field_quoter, validation)),
+ Validator::MustMatch(_) => validations.push(quote_must_match_validation(&field_quoter, validation)),
+ Validator::Custom(_) => validations.push(quote_custom_validation(&field_quoter, validation)),
+ Validator::Contains(_) => validations.push(quote_contains_validation(&field_quoter, validation)),
+ Validator::Regex(_) => validations.push(quote_regex_validation(&field_quoter, validation)),
#[cfg(feature = "card")]
- Validator::CreditCard => quote_credit_card_validation(&field_quoter, validation),
+ Validator::CreditCard => validations.push(quote_credit_card_validation(&field_quoter, validation)),
#[cfg(feature = "phone")]
- Validator::Phone => quote_phone_validation(&field_quoter, validation),
+ Validator::Phone => validations.push(quote_phone_validation(&field_quoter, validation)),
+ Validator::Nested => nested_validations.push(quote_nested_validation(&field_quoter)),
}
}
-
pub fn quote_schema_validation(validation: Option<SchemaValidation>) -> proc_macro2::TokenStream {
if let Some(v) = validation {
let fn_ident = syn::Ident::new(&v.function, Span::call_site());