baizekit_derive/
lib.rs

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    // 查找被 #[paginate] 标注的字段
43    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}