Skip to main content

static_pubkey/
lib.rs

1//! provides a macro used for compile-time parsing of public key strings into byte arrays for near 0-cost static public keys.
2
3use proc_macro2::Span;
4use quote::quote;
5use syn::{parse_macro_input, LitByte, LitStr};
6
7
8/// parses a string literal public key into a byte array public key
9///
10/// # Arguments
11///
12/// * `input` - A public key string
13///
14/// # Examples
15///
16/// ```
17/// use static_pubkey::static_pubkey;
18/// let key = static_pubkey!("GjphYQcbP1m3FuDyCTUJf2mUMxKPE3j6feWU1rxvC7Ps");
19/// assert!(key.to_string() == "GjphYQcbP1m3FuDyCTUJf2mUMxKPE3j6feWU1rxvC7Ps");
20/// ```
21#[proc_macro]
22pub fn static_pubkey(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
23    use std::convert::TryFrom;
24    let id_literal = parse_macro_input!(input as LitStr);
25    let id_vec = bs58::decode(id_literal.value())
26        .into_vec()
27        .map_err(|_| syn::Error::new_spanned(&id_literal, "failed to decode base58 string"))
28        .unwrap();
29    let id_array = <[u8; 32]>::try_from(<&[u8]>::clone(&&id_vec[..]))
30        .map_err(|_| {
31            syn::Error::new_spanned(
32                &id_literal,
33                format!("pubkey array is not 32 bytes long: len={}", id_vec.len()),
34            )
35        })
36        .unwrap();
37    let bytes = id_array.iter().map(|b| LitByte::new(*b, Span::call_site()));
38    let output = quote! {
39        solana_program::pubkey::Pubkey::new_from_array(
40            [#(#bytes,)*]
41        )
42    };
43    output.into()
44}