lib.rs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. extern crate proc_macro;
  2. use quote::quote;
  3. use syn::parse_macro_input;
  4. /// The event attribute allows a struct to be used with
  5. /// [emit!](./macro.emit.html) so that programs can log significant events in
  6. /// their programs that clients can subscribe to. Currently, this macro is for
  7. /// structs only.
  8. #[proc_macro_attribute]
  9. pub fn event(
  10. _args: proc_macro::TokenStream,
  11. input: proc_macro::TokenStream,
  12. ) -> proc_macro::TokenStream {
  13. let event_strct = parse_macro_input!(input as syn::ItemStruct);
  14. let event_name = &event_strct.ident;
  15. let discriminator: proc_macro2::TokenStream = {
  16. let discriminator_preimage = format!("event:{}", event_name);
  17. let mut discriminator = [0u8; 8];
  18. discriminator.copy_from_slice(
  19. &anchor_syn::hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..8],
  20. );
  21. format!("{:?}", discriminator).parse().unwrap()
  22. };
  23. proc_macro::TokenStream::from(quote! {
  24. #[derive(anchor_lang::__private::EventIndex, AnchorSerialize, AnchorDeserialize)]
  25. #event_strct
  26. impl anchor_lang::Event for #event_name {
  27. fn data(&self) -> Vec<u8> {
  28. let mut d = #discriminator.to_vec();
  29. d.append(&mut self.try_to_vec().unwrap());
  30. d
  31. }
  32. }
  33. impl anchor_lang::Discriminator for #event_name {
  34. fn discriminator() -> [u8; 8] {
  35. #discriminator
  36. }
  37. }
  38. })
  39. }
  40. /// Logs an event that can be subscribed to by clients.
  41. /// Uses the [`sol_log_data`](https://docs.rs/solana-program/latest/solana_program/log/fn.sol_log_data.html)
  42. /// syscall which results in the following log:
  43. /// ```ignore
  44. /// Program data: <Base64EncodedEvent>
  45. /// ```
  46. #[proc_macro]
  47. pub fn emit(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
  48. let data: proc_macro2::TokenStream = input.into();
  49. proc_macro::TokenStream::from(quote! {
  50. {
  51. anchor_lang::solana_program::log::sol_log_data(&[&anchor_lang::Event::data(&#data)]);
  52. }
  53. })
  54. }
  55. // EventIndex is a marker macro. It functionally does nothing other than
  56. // allow one to mark fields with the `#[index]` inert attribute, which is
  57. // used to add metadata to IDLs.
  58. #[proc_macro_derive(EventIndex, attributes(index))]
  59. pub fn derive_event(_item: proc_macro::TokenStream) -> proc_macro::TokenStream {
  60. proc_macro::TokenStream::from(quote! {})
  61. }