lib.rs 2.5 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.to_string());
  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. /// Creates an event that can be subscribed to by clients. Calling this method
  41. /// will internally borsh serialize the [event](./attr.event.html), base64
  42. /// encode the bytes, and then add a [msg!](../solana_program/macro.msg.html)
  43. /// log to the transaction.
  44. #[proc_macro]
  45. pub fn emit(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
  46. let data: proc_macro2::TokenStream = input.into();
  47. proc_macro::TokenStream::from(quote! {
  48. {
  49. let data = anchor_lang::Event::data(&#data);
  50. let msg_str = &anchor_lang::__private::base64::encode(data);
  51. anchor_lang::solana_program::msg!(msg_str);
  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. }