dbstruct_derive/
lib.rs

1use proc_macro_error::{abort, emit_error, proc_macro_error};
2use syn::parse_macro_input;
3
4mod model;
5use model::Model;
6mod ir;
7use ir::Ir;
8mod codegen;
9use codegen::codegen;
10mod errors;
11use errors::{GetSpan, Help};
12
13/* TODO: dummy stream? (see proc-macro-error) <dvdsk noreply@davidsk.dev> */
14
15#[proc_macro_attribute]
16#[proc_macro_error]
17pub fn dbstruct(
18    attr: proc_macro::TokenStream,
19    item: proc_macro::TokenStream,
20) -> proc_macro::TokenStream {
21    let input = parse_macro_input!(item as syn::ItemStruct);
22
23    let model = match Model::try_from(input, attr.into()) {
24        Ok(model) => model,
25        Err(err) => emit_and_abort(err),
26    };
27
28    let ir = Ir::from(model);
29    let code = codegen(ir);
30    code.into()
31}
32
33fn emit_and_abort(err: model::Error) -> ! {
34    match err {
35        model::Error::DbKey(e) => {
36            abort!(e.span(), "{}", e)
37        }
38        model::Error::Field(mut errs) => {
39            let last = errs.pop().expect("minimum err vec len is one");
40            for e in errs {
41                emit_error!(e.span(), e.to_string(); help =? e.help(););
42            }
43            abort!(last.span(),last.to_string(); help =? last.help(););
44        }
45        model::Error::Attribute(e) => {
46            abort!(e.span(), e.to_string(); help =? e.help(););
47        }
48        model::Error::Backend(e) => {
49            abort!(e.span(), e.to_string(); help =? e.help(););
50        }
51    }
52}
53