quickvariant_macros/
lib.rs1use syn::punctuated::Punctuated;
2
3#[proc_macro]
4pub fn make_variant(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
5 if input.is_empty() {
6 return syn::Error::new_spanned(
7 proc_macro2::TokenStream::from(input),
8 "Macro input cannot be empty. Please specify at least one type."
9 ).to_compile_error().into();
10 }
11 let types = syn::parse_macro_input!(
12 input with Punctuated::<syn::Type, syn::token::Comma>::parse_terminated
13 );
14 let sizes = types.iter().map(|ty| {
15 quote::quote! { std::mem::size_of::<#ty>() }
16 });
17 let aligns = types.iter().map(|ty| {
18 quote::quote! { std::mem::align_of::<#ty>() }
19 });
20 let ids = types.iter().map(|ty| {
21 quote::quote! { std::any::TypeId::of::<#ty>() }
22 });
23 let errmsg = syn::LitStr::new(
24 "Macro input cannot be empty. Please specify at least one type.",
25 proc_macro2::Span::call_site()
26 );
27 quote::quote! {
28 {
29 let max_size = [#(#sizes),*].iter().copied().max().expect(#errmsg);
30 let max_align = [#(#aligns),*].iter().copied().max().expect(#errmsg);
31 let mut types = std::collections::HashSet::new();
32 for ty in [#(#ids),*] {
33 types.insert(ty);
34 }
35 quickvariant::Variant::__new(max_size, max_align, types)
36 }
37 }.into()
38}