cote_derive/
lib.rs

1mod config;
2mod r#gen;
3mod value;
4
5use quote::quote;
6use r#gen::CoteGenerator;
7use r#gen::FetchGenerator;
8use r#gen::InferGenerator;
9use r#gen::ValueGenerator;
10use syn::parse_macro_input;
11use syn::spanned::Spanned;
12use syn::DataEnum;
13use syn::DeriveInput;
14
15fn error(spanned: impl Spanned, msg: impl Into<String>) -> syn::Error {
16    syn::Error::new(spanned.span(), msg.into())
17}
18
19#[proc_macro_derive(Cote, attributes(cote, arg, pos, cmd, sub))]
20pub fn parser(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
21    let input: DeriveInput = parse_macro_input!(input);
22    let generator = |input: DeriveInput| -> syn::Result<proc_macro2::TokenStream> {
23        let mut cg = CoteGenerator::new(&input)?;
24
25        cg.gen_impl_for_struct()
26    };
27
28    let ts = generator(input).unwrap_or_else(syn::Error::into_compile_error);
29
30    quote! {
31        #ts
32    }
33    .into()
34}
35
36#[proc_macro_derive(CoteOpt, attributes(infer, fetch))]
37pub fn parser_opt(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
38    let input: DeriveInput = parse_macro_input!(input);
39    let generator = |input| -> syn::Result<proc_macro2::TokenStream> {
40        let fg = FetchGenerator::new(input)?;
41        let ig = InferGenerator::new(input)?;
42        let fg = fg.gen_impl_for_struct()?;
43        let ig = ig.gen_impl_for_struct()?;
44
45        Ok(quote::quote! { #fg #ig })
46    };
47
48    generator(&input)
49        .unwrap_or_else(syn::Error::into_compile_error)
50        .into()
51}
52
53#[proc_macro_derive(CoteVal, attributes(coteval))]
54pub fn parser_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
55    let input: DeriveInput = parse_macro_input!(input);
56    let generator = |input, variants| ValueGenerator::new(input, variants)?.gen_impl_for_enum();
57    let ts = generator(
58        &input,
59        if let syn::Data::Enum(DataEnum { ref variants, .. }) = &input.data {
60            Some(variants)
61        } else {
62            None
63        },
64    )
65    .unwrap_or_else(syn::Error::into_compile_error);
66
67    ts.into()
68}