iota_util_mem_derive/
lib.rs1#![allow(clippy::all)]
19
20extern crate proc_macro2;
21#[macro_use]
22extern crate syn;
23#[macro_use]
24extern crate synstructure;
25
26decl_derive!([MallocSizeOf, attributes(ignore_malloc_size_of)] => malloc_size_of_derive);
27
28fn malloc_size_of_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
29 let match_body = s.each(|binding| {
30 let ignore = binding
31 .ast()
32 .attrs
33 .iter()
34 .any(|attr| match attr.parse_meta().unwrap() {
35 syn::Meta::Path(ref path) | syn::Meta::List(syn::MetaList { ref path, .. })
36 if path.is_ident("ignore_malloc_size_of") =>
37 {
38 panic!(
39 "#[ignore_malloc_size_of] should have an explanation, \
40 e.g. #[ignore_malloc_size_of = \"because reasons\"]"
41 );
42 }
43 syn::Meta::NameValue(syn::MetaNameValue { ref path, .. })
44 if path.is_ident("ignore_malloc_size_of") =>
45 {
46 true
47 }
48 _ => false,
49 });
50 if ignore {
51 None
52 } else if let syn::Type::Array(..) = binding.ast().ty {
53 Some(quote! {
54 for item in #binding.iter() {
55 sum += iota_util_mem::MallocSizeOf::size_of(item, ops);
56 }
57 })
58 } else {
59 Some(quote! {
60 sum += iota_util_mem::MallocSizeOf::size_of(#binding, ops);
61 })
62 }
63 });
64
65 let ast = s.ast();
66 let name = &ast.ident;
67 let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
68 let mut where_clause = where_clause.unwrap_or(&parse_quote!(where)).clone();
69 for param in ast.generics.type_params() {
70 let ident = ¶m.ident;
71 where_clause
72 .predicates
73 .push(parse_quote!(#ident: iota_util_mem::MallocSizeOf));
74 }
75
76 let tokens = quote! {
77 impl #impl_generics iota_util_mem::MallocSizeOf for #name #ty_generics #where_clause {
78 #[inline]
79 #[expect(unused_variables, unused_mut, unreachable_code)]
80 fn size_of(&self, ops: &mut iota_util_mem::MallocSizeOfOps) -> usize {
81 let mut sum = 0;
82 match *self {
83 #match_body
84 }
85 sum
86 }
87 }
88 };
89
90 tokens
91}