1use proc_macro::{self, TokenStream};
2use quote::quote;
3use syn::{DeriveInput, parse_macro_input};
4
5#[proc_macro_derive(StructTag, attributes(struct_tag))]
6pub fn derive_struct_tag(input: TokenStream) -> TokenStream {
7 let input: DeriveInput = parse_macro_input!(input);
8 let ident = &input.ident;
9
10 let tag: syn::LitInt = input
11 .attrs
12 .into_iter()
13 .find(|attr| attr.path().is_ident("struct_tag"))
14 .expect("struct_tag not found")
15 .parse_args()
16 .expect("Failed to parse struct_tag argument");
17
18 let output = quote! {
19 impl StructTag for #ident {
20 const TAG: u16 = #tag;
21 }
22 };
23
24 output.into()
25}
26
27#[proc_macro_derive(StructRawSize)]
28pub fn derive_size(input: TokenStream) -> TokenStream {
29 let input: DeriveInput = parse_macro_input!(input);
30 let ident = &input.ident;
31
32 let data = match input.data {
33 syn::Data::Struct(data_struct) => data_struct,
34 _ => unimplemented!(),
35 };
36
37 let fields = data.fields.iter().map(|field| {
38 let ident = &field.ident;
39 quote! { self.#ident.get_raw_size() }
40 });
41
42 quote! {
43 impl StructRawSize for #ident {
44 #[inline]
45 fn get_raw_size(&self) -> usize {
46 0 #(+ #fields)*
47 }
48 }
49 }
50 .into()
51}