1extern crate proc_macro;
3use proc_macro::TokenStream;
4use proc_macro2::Span;
5use quote::quote;
6
7#[proc_macro_derive(DbEnum)]
8pub fn derive_db_enum(input: TokenStream) -> TokenStream {
9 rorm_macro_impl::derive_db_enum(input.into(), rorm_macro_impl::MacroConfig::default()).into()
10}
11
12#[proc_macro_derive(Model, attributes(rorm))]
13pub fn derive_model(input: TokenStream) -> TokenStream {
14 rorm_macro_impl::derive_model(input.into(), rorm_macro_impl::MacroConfig::default()).into()
15}
16
17#[proc_macro_derive(Patch, attributes(rorm))]
18pub fn derive_patch(input: TokenStream) -> TokenStream {
19 rorm_macro_impl::derive_patch(input.into(), rorm_macro_impl::MacroConfig::default()).into()
20}
21
22#[proc_macro_attribute]
23pub fn rorm_main(args: TokenStream, item: TokenStream) -> TokenStream {
24 let main = syn::parse_macro_input!(item as syn::ItemFn);
25 let feature = syn::parse::<syn::LitStr>(args)
26 .unwrap_or_else(|_| syn::LitStr::new("rorm-main", Span::call_site()));
27
28 (if main.sig.ident == "main" {
29 quote! {
30 #[cfg(feature = #feature)]
31 fn main() -> Result<(), String> {
32 let mut file = ::std::fs::File::create(".models.json").map_err(|err| err.to_string())?;
33 ::rorm::write_models(&mut file)?;
34 return Ok(());
35 }
36 #[cfg(not(feature = #feature))]
37 #main
38 }
39 } else {
40 quote! {
41 compile_error!("only allowed on main function");
42 #main
43 }
44 }).into()
45}
46
47#[proc_macro]
57pub fn impl_tuple(args: TokenStream) -> TokenStream {
58 use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenTree as TT};
60
61 let args = Vec::from_iter(args);
62 let [TT::Ident(macro_ident), TT::Punct(comma), TT::Literal(start), TT::Punct(fst_dot), TT::Punct(snd_dot), TT::Literal(end)] =
63 &args[..]
64 else {
65 panic!()
66 };
67 if *comma != ','
68 || *fst_dot != '.'
69 || *snd_dot != '.' && matches!(fst_dot.spacing(), Spacing::Alone)
70 {
71 panic!();
72 }
73
74 let start: usize = start.to_string().parse().unwrap();
75 let end: usize = end.to_string().parse().unwrap();
76
77 let mut tokens = TokenStream::default();
78 for until in start..end {
79 let mut impl_args = TokenStream::new();
80 for index in 0..until {
81 impl_args.extend([
82 TT::Literal(Literal::usize_unsuffixed(index)),
83 TT::Punct(Punct::new(':', Spacing::Alone)),
84 TT::Ident(Ident::new(&format!("T{index}"), Span::call_site())),
85 TT::Punct(Punct::new(',', Spacing::Alone)),
86 ]);
87 }
88 tokens.extend([
89 TT::Ident(macro_ident.clone()),
90 TT::Punct(Punct::new('!', Spacing::Alone)),
91 TT::Group(Group::new(Delimiter::Parenthesis, impl_args)),
92 TT::Punct(Punct::new(';', Spacing::Alone)),
93 ]);
94 }
95 tokens
96}