1mod attrs;
2mod fields;
3mod into_subject;
4mod subject;
5
6use proc_macro::TokenStream;
7use quote::quote;
8use syn::{parse_macro_input, DeriveInput};
9
10#[proc_macro_derive(Subject, attributes(subject))]
11pub fn subject_derive(input: TokenStream) -> TokenStream {
12 let input = parse_macro_input!(input as DeriveInput);
13 let name = &input.ident;
14
15 let fields = fields::from_input(&input).unwrap();
16 let field_infos = fields::names_from_fields(fields);
17 let field_names: Vec<_> = field_infos.iter().map(|f| f.ident).collect();
18 let field_types = fields::types_from_fields(fields);
19
20 let id_fn = into_subject::id_fn();
21 let query_all_fn = into_subject::query_all_fn();
22 let parse_fn = into_subject::parse_fn(&input, &field_names);
23 let to_sql_where_fn = into_subject::to_sql_where_fn(&field_infos);
24 let to_sql_select_fn = into_subject::to_sql_select_fn(&field_infos);
25 let to_payload_fn = into_subject::to_payload_fn(&input);
26 let schema_fn = into_subject::schema_fn(
27 &input,
28 &field_infos,
29 &field_names,
30 &field_types,
31 );
32
33 let subject_expanded = subject::expanded(
34 name,
35 &field_names,
36 &field_types,
37 &field_infos,
38 &input.attrs,
39 );
40
41 quote! {
42 #subject_expanded
43
44 impl fuel_streams_subject::subject::SubjectBuildable for #name {
45 fn new() -> Self {
46 Self {
47 #(#field_names: None,)*
48 }
49 }
50 }
51
52 impl IntoSubject for #name {
53 #id_fn
54 #parse_fn
55 #query_all_fn
56 #to_sql_where_fn
57 #to_sql_select_fn
58 #schema_fn
59 #to_payload_fn
60 }
61 }
62 .into()
63}