Skip to content

Add a proc-macro for a string principal constant #691

@ranile

Description

@ranile

Is your feature request related to a problem? Please describe.
Principal::from_text is not const but there's many circumstances in which a principal constant is wanted in code. Principal::from_slice is const but it is much harder to inspect and verify as it just takes a byte slice

Describe the solution you'd like

principal!("...")

Describe alternatives you've considered

Principal::from_slice(&[...]), but as mentioned above, that is less than ideal.

Potential implementation

use candid::Principal;
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, LitStr, parse::Parse, parse::ParseStream};

struct CandidPrincipal(Principal);

impl Parse for CandidPrincipal {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let text = input.parse::<LitStr>()?.value();
        Principal::from_text(&text)
            .map(Self)
            .map_err(|e| syn::Error::new(input.span(), e.to_string()))
    }
}

impl ToTokens for CandidPrincipal {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let bytes = self.0.as_slice();
        tokens.extend(quote! {
            ::candid::Principal::from_slice(&[#(#bytes),*])
        })
    }
}

#[proc_macro]
pub fn principal(tokens: TokenStream) -> TokenStream {
    parse_macro_input!(tokens as CandidPrincipal)
        .into_token_stream()
        .into()
}

syn and quote are dependencies of ic-cdk anyway so this will not have any negative effects on compilation performance

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions