Skip to main content

typhoon_cpi_generator_macro/
lib.rs

1use {
2    proc_macro::{Span, TokenStream},
3    std::{fs::read_to_string, path::PathBuf},
4    syn::{parse::Parse, parse_macro_input, LitStr},
5    typhoon_cpi_generator::{anchor::gen_cpi, idl::Idl},
6};
7
8#[proc_macro]
9pub fn anchor_cpi(input: TokenStream) -> TokenStream {
10    let idl_file = parse_macro_input!(input as IdlFile);
11    let idl: Idl = match serde_json::from_str(&idl_file.content) {
12        Ok(idl) => idl,
13        Err(err) => {
14            return syn::Error::new(
15                Span::call_site().into(),
16                format!("Failed to parse IDL: {err}"),
17            )
18            .to_compile_error()
19            .into();
20        }
21    };
22
23    gen_cpi(&idl).into()
24}
25struct IdlFile {
26    pub content: String,
27}
28
29impl Parse for IdlFile {
30    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
31        let path: LitStr = input.parse()?;
32        let path_str = path.value();
33
34        let var = std::env::var("CARGO_MANIFEST_DIR")
35            .map_err(|err| syn::Error::new(input.span(), err.to_string()))?;
36        let mut so_path = PathBuf::from(var);
37        so_path.push(path_str);
38
39        let content = read_to_string(so_path)
40            .map_err(|_| syn::Error::new(path.span(), "Unable to read file"))?;
41
42        Ok(IdlFile { content })
43    }
44}