instruction.rs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. use crate::codegen::program::common::*;
  2. use crate::parser;
  3. use crate::Program;
  4. use heck::CamelCase;
  5. use quote::quote;
  6. pub fn generate(program: &Program) -> proc_macro2::TokenStream {
  7. let variants: Vec<proc_macro2::TokenStream> = program
  8. .ixs
  9. .iter()
  10. .map(|ix| {
  11. let name = &ix.raw_method.sig.ident.to_string();
  12. let ix_name_camel =
  13. proc_macro2::Ident::new(&name.to_camel_case(), ix.raw_method.sig.ident.span());
  14. let raw_args: Vec<proc_macro2::TokenStream> = ix
  15. .args
  16. .iter()
  17. .map(|arg| {
  18. format!("pub {}", parser::tts_to_string(&arg.raw_arg))
  19. .parse()
  20. .unwrap()
  21. })
  22. .collect();
  23. let ix_data_trait = {
  24. let sighash_arr = sighash(SIGHASH_GLOBAL_NAMESPACE, name);
  25. let sighash_tts: proc_macro2::TokenStream =
  26. format!("{:?}", sighash_arr).parse().unwrap();
  27. quote! {
  28. impl anchor_lang::Discriminator for #ix_name_camel {
  29. const DISCRIMINATOR: [u8; 8] = #sighash_tts;
  30. }
  31. impl anchor_lang::InstructionData for #ix_name_camel {}
  32. impl anchor_lang::Owner for #ix_name_camel {
  33. fn owner() -> Pubkey {
  34. ID
  35. }
  36. }
  37. }
  38. };
  39. // If no args, output a "unit" variant instead of a struct variant.
  40. if ix.args.is_empty() {
  41. quote! {
  42. /// Instruction.
  43. #[derive(AnchorSerialize, AnchorDeserialize)]
  44. pub struct #ix_name_camel;
  45. #ix_data_trait
  46. }
  47. } else {
  48. quote! {
  49. /// Instruction.
  50. #[derive(AnchorSerialize, AnchorDeserialize)]
  51. pub struct #ix_name_camel {
  52. #(#raw_args),*
  53. }
  54. #ix_data_trait
  55. }
  56. }
  57. })
  58. .collect();
  59. quote! {
  60. /// An Anchor generated module containing the program's set of
  61. /// instructions, where each method handler in the `#[program]` mod is
  62. /// associated with a struct defining the input arguments to the
  63. /// method. These should be used directly, when one wants to serialize
  64. /// Anchor instruction data, for example, when speciying
  65. /// instructions on a client.
  66. pub mod instruction {
  67. use super::*;
  68. #(#variants)*
  69. }
  70. }
  71. }