anchor_syn/codegen/program/
common.rs

1use crate::IxArg;
2use heck::CamelCase;
3use quote::quote;
4
5// Namespace for calculating instruction sighash signatures for any instruction
6// not affecting program state.
7pub const SIGHASH_GLOBAL_NAMESPACE: &str = "global";
8
9// We don't technically use sighash, because the input arguments aren't given.
10// Rust doesn't have method overloading so no need to use the arguments.
11// However, we do namespace methods in the preeimage so that we can use
12// different traits with the same method name.
13pub fn sighash(namespace: &str, name: &str) -> [u8; 8] {
14    let preimage = format!("{namespace}:{name}");
15
16    let mut sighash = [0u8; 8];
17    sighash.copy_from_slice(&crate::hash::hash(preimage.as_bytes()).to_bytes()[..8]);
18    sighash
19}
20
21pub fn gen_discriminator(namespace: &str, name: impl ToString) -> proc_macro2::TokenStream {
22    let discriminator = sighash(namespace, name.to_string().as_str());
23    format!("&{:?}", discriminator).parse().unwrap()
24}
25
26pub fn generate_ix_variant(name: &str, args: &[IxArg]) -> proc_macro2::TokenStream {
27    let ix_arg_names: Vec<&syn::Ident> = args.iter().map(|arg| &arg.name).collect();
28    let ix_name_camel = generate_ix_variant_name(name);
29
30    if args.is_empty() {
31        quote! {
32            #ix_name_camel
33        }
34    } else {
35        quote! {
36            #ix_name_camel {
37                #(#ix_arg_names),*
38            }
39        }
40    }
41}
42
43pub fn generate_ix_variant_name(name: &str) -> proc_macro2::TokenStream {
44    let n = name.to_camel_case();
45    n.parse().unwrap()
46}