bolt_attribute_bolt_account/
lib.rs1use proc_macro::TokenStream;
2use quote::quote;
3use syn::spanned::Spanned;
4use syn::{parse_macro_input, parse_quote, Attribute, DeriveInput, Lit, Meta, NestedMeta};
5
6#[proc_macro_attribute]
20pub fn bolt_account(attr: TokenStream, item: TokenStream) -> TokenStream {
21 let attr = parse_macro_input!(attr as Meta);
22 let mut input = parse_macro_input!(item as DeriveInput);
23
24 let component_id_value = match attr {
25 Meta::NameValue(meta_name_value) if meta_name_value.path.is_ident("component_id") => {
26 if let Lit::Str(lit) = meta_name_value.lit {
27 Some(lit.value())
28 } else {
29 None
30 }
31 }
32 Meta::List(meta) => meta.nested.into_iter().find_map(|nested_meta| {
33 if let NestedMeta::Meta(Meta::NameValue(meta_name_value)) = nested_meta {
34 if meta_name_value.path.is_ident("component_id") {
35 if let Lit::Str(lit) = meta_name_value.lit {
36 Some(lit.value())
37 } else {
38 None
39 }
40 } else {
41 None
42 }
43 } else {
44 None
45 }
46 }),
47 _ => {
48 let error = syn::Error::new(attr.span(), "Missing required attribute `component_id`");
49 return error.to_compile_error().into();
50 }
51 };
52
53 let component_id_value = match component_id_value {
54 Some(value) => value,
55 None => {
56 let error = syn::Error::new(input.span(), "The `component_id` attribute is required");
57 return error.to_compile_error().into();
58 }
59 };
60
61 let additional_derives: Attribute = parse_quote! { #[derive(InitSpace, Default)] };
62 input.attrs.push(additional_derives);
63
64 let name = &input.ident;
65 let expanded = quote! {
66 #input
67
68 #[automatically_derived]
69 impl ComponentTraits for #name {
70 fn seed() -> &'static [u8] {
71 #component_id_value.as_bytes()
72 }
73
74 fn size() -> usize {
75 8 + <#name>::INIT_SPACE
76 }
77 }
78 };
79 expanded.into()
80}