Skip to main content

paperless_api_macros/
lib.rs

1mod derive_base;
2
3use proc_macro::TokenStream;
4use quote::{format_ident, quote};
5use syn::{DeriveInput, parse_macro_input};
6
7use crate::derive_base::{BaseStruct, ItemStruct};
8
9/// Derives a `Create..` struct for the given input struct.
10#[proc_macro_derive(CreateDto, attributes(dto, api_info))]
11pub fn derive_create_dto(input: TokenStream) -> TokenStream {
12    // Parse the input
13    let input = parse_macro_input!(input as DeriveInput);
14    let input_struct = match BaseStruct::try_from(input) {
15        Ok(val) => val,
16        Err(e) => return e.to_compile_error().into(),
17    };
18
19    // Generate the new struct
20    let new_struct_name = format_ident!("Create{}", input_struct.name);
21    let new_struct = input_struct.generate_new_struct(&new_struct_name, false);
22
23    // Generate the final output with the trait implementation
24    TokenStream::from(quote! {
25        #new_struct
26
27        impl crate::dto::CreateDtoObject for #new_struct_name {}
28    })
29}
30
31/// Derives a `Create..` struct for the given input struct.
32#[proc_macro_derive(UpdateDto, attributes(dto, api_info))]
33pub fn derive_update_dto(input: TokenStream) -> TokenStream {
34    // Parse the input
35    let input = parse_macro_input!(input as DeriveInput);
36    let input_struct = match BaseStruct::try_from(input) {
37        Ok(val) => val,
38        Err(e) => return e.to_compile_error().into(),
39    };
40
41    // Generate the new struct
42    let new_struct_name = format_ident!("Update{}", input_struct.name);
43    let new_struct = input_struct.generate_new_struct(&new_struct_name, true);
44
45    // Generate the final output with the trait implementation
46    TokenStream::from(quote! {
47        #new_struct
48
49        impl crate::dto::UpdateDtoObject for #new_struct_name {}
50    })
51}
52
53/// Derives a `Create..` struct for the given input struct.
54#[proc_macro_derive(Item, attributes(dto, api_info))]
55pub fn derive_item_trait(input: TokenStream) -> TokenStream {
56    // Parse the input
57    let input = parse_macro_input!(input as DeriveInput);
58    let input_struct = match ItemStruct::try_from(input) {
59        Ok(val) => val,
60        Err(e) => return e.to_compile_error().into(),
61    };
62
63    let update_dto = format_ident!("Update{}", input_struct.base_struct.name);
64    let create_dto = format_ident!("Create{}", input_struct.base_struct.name);
65    let id_type_name = format_ident!("{}Id", input_struct.base_struct.name);
66    let id_type_name = quote!(crate::id::#id_type_name);
67
68    let endpoint = input_struct.endpoint.clone();
69    let name = input_struct.base_struct.name;
70
71    // Generate the final output with the trait implementation
72    TokenStream::from(quote! {
73        impl crate::dto::Item for #name {
74            type Id = #id_type_name;
75            type BaseType = #name;
76            type CreateDto = #create_dto;
77            type UpdateDto = #update_dto;
78
79            fn endpoint() -> &'static str {
80                #endpoint
81            }
82
83            fn id(&self) -> Self::Id {
84                self.id
85            }
86        }
87    })
88}