1extern crate proc_macro;
35
36use proc_macro::TokenStream;
37use quote::quote;
38use syn::{Data, DeriveInput, Fields, parse_macro_input};
39
40mod common;
41
42#[cfg(feature = "mongo")]
43mod mongo_macro;
44#[cfg(feature = "postgres")]
45mod postgres_macro;
46
47#[cfg(feature = "postgres")]
48#[proc_macro_derive(Repository, attributes(entity, id, table))]
49pub fn repository_derive(input: TokenStream) -> TokenStream {
50 postgres_macro::repository_derive(input)
51}
52
53#[cfg(feature = "mongo")]
54#[proc_macro_derive(MongoRepository, attributes(entity, id, collection))]
55pub fn mongo_repository_derive(input: TokenStream) -> TokenStream {
56 mongo_macro::mongo_repository_derive(input)
57}
58
59#[proc_macro_derive(Entity)]
60pub fn derive_entity(input: TokenStream) -> TokenStream {
61 let ast = parse_macro_input!(input as DeriveInput);
62 let name = &ast.ident;
63
64 let fields: Vec<_> = match &ast.data {
65 Data::Struct(data) => match &data.fields {
66 Fields::Named(fields_named) => fields_named
67 .named
68 .iter()
69 .filter(|f| f.ident.as_ref().unwrap() != "id")
70 .collect(),
71 _ => panic!("Entity derive only supports named fields"),
72 },
73 _ => panic!("Entity derive only supports structs"),
74 };
75
76 let column_names: Vec<_> = fields
77 .iter()
78 .map(|f| f.ident.as_ref().unwrap().to_string())
79 .collect();
80 let field_idents: Vec<_> = fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();
81
82 let gene = quote! {
83 impl #name {
84 pub fn columns() -> &'static [&'static str] {
85 &[#(#column_names),*]
86 }
87
88 pub fn values<'e>(&'e self) -> Vec<&'e (impl sqlx::Encode<'e, sqlx::Postgres> + sqlx::Type<sqlx::Postgres>)> {
89 vec![#(&self.#field_idents),*]
90 }
91 }
92 };
93
94 gene.into()
95}