forked from solana-foundation/anchor
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinstruction.rs
More file actions
93 lines (87 loc) · 3.41 KB
/
instruction.rs
File metadata and controls
93 lines (87 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::codegen::program::common::*;
use crate::parser;
use crate::Program;
use heck::CamelCase;
use quote::{quote, quote_spanned};
pub fn generate(program: &Program) -> proc_macro2::TokenStream {
let variants: Vec<proc_macro2::TokenStream> = program
.ixs
.iter()
.map(|ix| {
let name = &ix.raw_method.sig.ident.to_string();
let ix_cfgs = &ix.cfgs;
let Ok(ix_name_camel) = syn::parse_str::<syn::Ident>(&name.to_camel_case()) else {
return quote_spanned! { ix.raw_method.sig.ident.span()=>
compile_error!("failed to parse ix method name after conversion to camelCase");
};
};
let raw_args: Vec<proc_macro2::TokenStream> = ix
.args
.iter()
.map(|arg| {
format!("pub {}", parser::tts_to_string(&arg.raw_arg))
.parse()
.unwrap()
})
.collect();
let impls = {
let discriminator = match ix.overrides.as_ref() {
Some(overrides) if overrides.discriminator.is_some() => {
overrides.discriminator.as_ref().unwrap().to_owned()
}
// TODO: Remove `interface_discriminator`
_ => match &ix.interface_discriminator {
Some(disc) => format!("&{disc:?}").parse().unwrap(),
_ => gen_discriminator(SIGHASH_GLOBAL_NAMESPACE, name),
},
};
quote! {
#(#ix_cfgs)*
impl anchor_lang::Discriminator for #ix_name_camel {
const DISCRIMINATOR: &'static [u8] = #discriminator;
}
#(#ix_cfgs)*
impl anchor_lang::InstructionData for #ix_name_camel {}
#(#ix_cfgs)*
impl anchor_lang::Owner for #ix_name_camel {
fn owner() -> Pubkey {
ID
}
}
}
};
// If no args, output a "unit" variant instead of a struct variant.
if ix.args.is_empty() {
quote! {
#(#ix_cfgs)*
/// Instruction.
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct #ix_name_camel;
#impls
}
} else {
quote! {
#(#ix_cfgs)*
/// Instruction.
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct #ix_name_camel {
#(#raw_args),*
}
#impls
}
}
})
.collect();
quote! {
/// An Anchor generated module containing the program's set of
/// instructions, where each method handler in the `#[program]` mod is
/// associated with a struct defining the input arguments to the
/// method. These should be used directly, when one wants to serialize
/// Anchor instruction data, for example, when specifying
/// instructions on a client.
pub mod instruction {
use super::*;
#(#variants)*
}
}
}