Skip to main content

finestre_init_with_size_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput, Data, Fields};
4
5#[proc_macro_derive(InitWithSize, attributes(size_field))]
6pub fn derive_init_with_size(input: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(input as DeriveInput);
8    let struct_name = input.ident;
9
10    // Default to size
11    let mut size_field_name = quote! { size };
12
13    if let Data::Struct(data_struct) = input.data {
14        if let Fields::Named(fields_named) = data_struct.fields {
15            for field in fields_named.named {
16                for attr in &field.attrs {
17                    if attr.path().is_ident("size_field") {
18                        if let Some(ident) = field.ident.as_ref() {
19                            size_field_name = quote! { #ident };
20                        }
21                    }
22                }
23            }
24        }
25    }
26
27    let expanded = quote! {
28        impl #struct_name {
29            pub fn init() -> Self {
30                let mut s: Self = unsafe { std::mem::zeroed() };
31                s.#size_field_name = std::mem::size_of::<Self>() as _;
32                s
33            }
34        }
35    };
36
37    TokenStream::from(expanded)
38}