1use baizekit_seaorm::curd::derive::{derive_curd_impl, CurdMacroOptions};
2use darling::FromDeriveInput;
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, Data, DeriveInput};
6
7use crate::derive_with::{derive_with_impl, Input};
8
9mod derive_with;
10
11#[proc_macro_derive(With)]
12pub fn derive_with(tokens: TokenStream) -> TokenStream {
13 let input = parse_macro_input!(tokens as DeriveInput);
14 let input = match Input::from_derive_input(&input) {
15 Ok(v) => v,
16 Err(e) => return e.write_errors().into(),
17 };
18
19 match derive_with_impl(input) {
20 Ok(expanded) => TokenStream::from(expanded),
21 Err(e) => TokenStream::from(e.write_errors()),
22 }
23}
24
25#[proc_macro_derive(Curd, attributes(curd))]
26pub fn derive_curd(input: TokenStream) -> TokenStream {
27 let input = parse_macro_input!(input as DeriveInput);
28 let options = match CurdMacroOptions::from_derive_input(&input) {
29 Ok(c) => c,
30 Err(e) => return e.write_errors().into(),
31 };
32
33 derive_curd_impl(options).into()
34}
35
36#[proc_macro_derive(PaginatedFilter, attributes(paginate))]
37pub fn derive_paginated_filter(input: TokenStream) -> TokenStream {
38 let opts = parse_macro_input!(input as DeriveInput);
39
40 let struct_name = &opts.ident;
41
42 let field_name = if let Data::Struct(data_struct) = &opts.data {
44 data_struct
45 .fields
46 .iter()
47 .find(|f| f.attrs.iter().any(|attr| attr.path().is_ident("paginate")))
48 .map(|f| f.ident.as_ref().unwrap())
49 } else {
50 None
51 };
52
53 let Some(field_name) = field_name else {
54 return syn::Error::new_spanned(struct_name, "Expected one named field with #[paginate] attribute")
55 .to_compile_error()
56 .into();
57 };
58
59 let expanded = quote! {
60 impl PaginatedFilter for #struct_name {
61 fn pagination(&self) -> Option<Pagination> {
62 self.#field_name.clone()
63 }
64 }
65 };
66
67 expanded.into()
68}