type_census_derive/
lib.rs

1use darling::FromDeriveInput;
2use proc_macro::{self, TokenStream};
3use quote::quote;
4use syn::{parse_macro_input, DeriveInput};
5
6#[derive(FromDeriveInput, Default)]
7#[darling(default, attributes(Tabulate), forward_attrs(allow, doc, cfg))]
8struct Opts {
9    #[darling(rename = "Counter")]
10    counter: Option<syn::TypePath>,
11}
12
13#[proc_macro_derive(Tabulate, attributes(Tabulate))]
14pub fn derive(input: TokenStream) -> TokenStream {
15    let input = parse_macro_input!(input);
16    let opts = Opts::from_derive_input(&input).expect("Wrong options");
17    let DeriveInput { ident, .. } = input;
18
19    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
20
21    let counter_ty = match opts.counter {
22        Some(counter_ty) => quote! { #counter_ty },
23        None => quote! { type_census::counter::RelaxedCounter },
24    };
25
26    let output = quote! {
27        #[automatically_derived]
28        impl #impl_generics type_census::Tabulate for #ident #ty_generics #where_clause {
29            type Counter = #counter_ty;
30            fn counter() -> &'static #counter_ty {
31                static COUNTER: #counter_ty = <#counter_ty as type_census::counter::Counter>::ZERO;
32                &COUNTER
33            }
34        }
35    };
36    output.into()
37}