1extern crate proc_macro;
2extern crate proc_macro2;
3extern crate syn;
4extern crate quote;
5
6use proc_macro::TokenStream;
7use proc_macro2::{Ident, Span};
8use quote::{quote, ToTokens};
9use syn::{parse_macro_input, ItemFn, Abi, Token, LitStr};
10
11#[proc_macro_attribute]
12pub fn c_api_prefix(attr: TokenStream, func: TokenStream) -> TokenStream {
13 let mut input = parse_macro_input!(func as ItemFn);
14
15 let prefix = attr.to_string();
16 let name = input.sig.ident.to_string();
17
18 input.sig.ident = get_name(prefix, name);
19
20 input.sig.abi = abi_setting();
21 let tokens = input.to_token_stream();
22 TokenStream::from(
23 quote!{
24 #[no_mangle]
25 #tokens
26 }
27 )
28}
29
30fn abi_setting() -> Option<Abi> {
31 Some(Abi {
32 extern_token: Token),
33 name: Some(LitStr::new("C", Span::call_site()))
34 })
35}
36
37fn get_name(prefix: String, name: String) -> Ident {
38 match prefix.as_str() {
39 "" => Ident::new(name.as_str(), Span::call_site()),
40 prefix => Ident::new(
41 format!("{}_{}", prefix, name).as_str(),
42 Span::call_site()
43 )
44 }
45}