use quote::quote;
pub struct Garde;
impl super::Integration for Garde {
fn name(&self) -> &'static str {
"garde"
}
fn supports_validate_non_nullable(&self) -> bool {
true
}
fn validate_non_nullable(
&self,
context: &super::NonNullableContext<'_>,
) -> proc_macro2::TokenStream {
let super::NonNullableContext { ident, flag, .. } = *context;
let validate_check = quote::quote_spanned! {flag.span()=>
const _: fn() = || {
fn garde_validate<T: garde::Validate>() {}
garde_validate::<#ident>();
};
};
quote! {
#validate_check
impl #ident {
pub fn validate_non_nullable(&self) -> Result<(), garde::Report> {
let mut report = match garde::Validate::validate(self) {
Ok(()) => garde::Report::new(),
Err(report) => report,
};
for field in self.rejected_nulls() {
report.append(garde::Path::new(field), garde::Error::new("cannot be set to null"));
}
if report.is_empty() {
Ok(())
} else {
Err(report)
}
}
}
}
}
fn query_params(&self, _context: &super::Context<'_>) -> super::TypeAdditions {
super::TypeAdditions {
derives: vec![quote!(garde::Validate)],
attributes: quote!(#[garde(allow_unvalidated)]),
}
}
fn page_size(&self, _context: &super::Context<'_>) -> proc_macro2::TokenStream {
quote!(#[garde(range(min = 1))])
}
fn sort(&self, context: &super::Context<'_>) -> proc_macro2::TokenStream {
let crate::conventions::FiltersNames {
sort_field,
sort_details,
..
} = context.names;
quote! {
#[garde(
length(min = 1, max = #sort_field::COUNT as usize),
custom(#sort_details::garde_unique_sort)
)]
}
}
fn sortable_items(&self, context: &super::Context<'_>) -> proc_macro2::TokenStream {
let crate::conventions::FiltersNames {
sort_field,
sort_details,
..
} = context.names;
quote! {
impl #sort_details {
pub fn garde_unique_sort(sort: &Option<Vec<Self>>, _context: &()) -> garde::Result {
let Some(sort) = sort else {
return Ok(());
};
let fields: std::collections::HashSet<#sort_field> = sort.iter().map(|details| details.field).collect();
if sort.len() == fields.len() {
Ok(())
} else {
Err(garde::Error::new("Duplicate sort field"))
}
}
}
}
}
}