lib.rs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. use bolt_utils::metadata::add_bolt_metadata;
  2. use proc_macro::TokenStream;
  3. use quote::quote;
  4. use syn::{parse_macro_input, Attribute, DeriveInput};
  5. /// This macro is used to defined a struct as a BOLT component and automatically implements the
  6. /// `ComponentDeserialize` and `AccountDeserialize` traits for the struct.
  7. ///
  8. /// #[component]
  9. /// pub struct Position {
  10. /// pub x: i64,
  11. /// pub y: i64,
  12. /// pub z: i64,
  13. /// }
  14. /// ```
  15. #[proc_macro_attribute]
  16. pub fn component_deserialize(_attr: TokenStream, item: TokenStream) -> TokenStream {
  17. let mut input = parse_macro_input!(item as DeriveInput);
  18. // Add the AnchorDeserialize and AnchorSerialize derives to the struct
  19. let additional_derives: Attribute = syn::parse_quote! { #[derive(bolt_lang::InitSpace, bolt_lang::AnchorDeserialize, bolt_lang::AnchorSerialize, Clone, Copy)] };
  20. input.attrs.push(additional_derives);
  21. let name = &input.ident.clone();
  22. // Assume that the component_id is the same as the struct name, minus the "Component" prefix
  23. let name_str = name.to_string();
  24. let component_id = name_str.strip_prefix("Component").unwrap_or("");
  25. let mut owner_definition = quote! {};
  26. if !component_id.is_empty() {
  27. add_bolt_metadata(&mut input);
  28. owner_definition = quote! {
  29. use std::str::FromStr;
  30. #[automatically_derived]
  31. impl Owner for #name {
  32. fn owner() -> Pubkey {
  33. Pubkey::from_str(#component_id).unwrap()
  34. }
  35. }
  36. };
  37. }
  38. let expanded = quote! {
  39. #input
  40. #[automatically_derived]
  41. impl bolt_lang::ComponentDeserialize for #name{
  42. fn from_account_info(account: &bolt_lang::AccountInfo) -> bolt_lang::Result<#name> {
  43. #name::try_deserialize_unchecked(&mut &*(*account.data.borrow()).as_ref()).map_err(Into::into)
  44. }
  45. }
  46. #[automatically_derived]
  47. impl bolt_lang::AccountDeserialize for #name {
  48. fn try_deserialize(buf: &mut &[u8]) -> bolt_lang::Result<Self> {
  49. Self::try_deserialize_unchecked(buf)
  50. }
  51. fn try_deserialize_unchecked(buf: &mut &[u8]) -> bolt_lang::Result<Self> {
  52. let mut data: &[u8] = &buf[8..];
  53. bolt_lang::AnchorDeserialize::deserialize(&mut data)
  54. .map_err(|_| bolt_lang::AccountDidNotDeserializeErrorCode.into())
  55. }
  56. }
  57. #[automatically_derived]
  58. impl bolt_lang::AccountSerialize for #name {
  59. fn try_serialize<W>(&self, _writer: &mut W) -> Result<()> {
  60. Ok(())
  61. }
  62. }
  63. #[automatically_derived]
  64. impl anchor_lang::Discriminator for #name {
  65. const DISCRIMINATOR: &'static [u8] = &[1, 1, 1, 1, 1, 1, 1, 1];
  66. }
  67. #owner_definition
  68. };
  69. expanded.into()
  70. }