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        #[automatically_derived]
28        impl crate::dto::CreateDtoObject for #new_struct_name {}
29    })
30}
31
32/// Derives a `Update..` struct for the given input struct.
33#[proc_macro_derive(UpdateDto, attributes(dto, api_info))]
34pub fn derive_update_dto(input: TokenStream) -> TokenStream {
35    // Parse the input
36    let input = parse_macro_input!(input as DeriveInput);
37    let input_struct = match BaseStruct::try_from(input) {
38        Ok(val) => val,
39        Err(e) => return e.to_compile_error().into(),
40    };
41
42    // Generate the new struct
43    let new_struct_name = format_ident!("Update{}", input_struct.name);
44    let new_struct = input_struct.generate_new_struct(&new_struct_name, true);
45
46    // Generate the final output with the trait implementation
47    TokenStream::from(quote! {
48        #new_struct
49
50        #[automatically_derived]
51        impl crate::dto::UpdateDtoObject for #new_struct_name {}
52    })
53}
54
55/// Derives a `Create..` struct for the given input struct.
56#[proc_macro_derive(Item, attributes(dto, api_info))]
57pub fn derive_item_trait(input: TokenStream) -> TokenStream {
58    // Parse the input
59    let input = parse_macro_input!(input as DeriveInput);
60    let input_struct = match ItemStruct::try_from(input) {
61        Ok(val) => val,
62        Err(e) => return e.to_compile_error().into(),
63    };
64
65    let update_dto = format_ident!("Update{}", input_struct.base_struct.name);
66    let create_dto = format_ident!("Create{}", input_struct.base_struct.name);
67    let id_type_name = format_ident!("{}Id", input_struct.base_struct.name);
68    let id_type_name = quote!(crate::id::#id_type_name);
69
70    let endpoint = input_struct.endpoint.clone();
71    let name = input_struct.base_struct.name;
72
73    // Generate the final output with the trait implementation
74    TokenStream::from(quote! {
75        #[automatically_derived]
76        impl crate::dto::Item for #name {
77            type Id = #id_type_name;
78            type BaseType = #name;
79            type CreateDto = #create_dto;
80            type UpdateDto = #update_dto;
81
82            fn endpoint() -> &'static str {
83                #endpoint
84            }
85
86            fn id(&self) -> Self::Id {
87                self.id
88            }
89        }
90    })
91}