1 //! This crate defines macros to easily define and use functions with a
2 //! versioned suffix, to facilitate using multiple versions of the same
3 //! crate that generate assembly.
4 
5 use quote::ToTokens;
6 
7 const VERSION: &str = env!("CARGO_PKG_VERSION");
8 
9 fn version(value: impl std::fmt::Display) -> String {
10     format!("{}_{}", value, VERSION.replace('.', "_"))
11 }
12 
13 fn versioned_lit_str(value: impl std::fmt::Display) -> syn::LitStr {
14     syn::LitStr::new(version(value).as_str(), proc_macro2::Span::call_site())
15 }
16 
17 #[proc_macro_attribute]
18 pub fn versioned_export(
19     _attr: proc_macro::TokenStream,
20     item: proc_macro::TokenStream,
21 ) -> proc_macro::TokenStream {
22     let mut function = syn::parse_macro_input!(item as syn::ItemFn);
23 
24     let export_name = versioned_lit_str(&function.sig.ident);
25     function
26         .attrs
27         .push(syn::parse_quote! { #[export_name = #export_name] });
28 
29     function.to_token_stream().into()
30 }
31 
32 #[proc_macro_attribute]
33 pub fn versioned_link(
34     _attr: proc_macro::TokenStream,
35     item: proc_macro::TokenStream,
36 ) -> proc_macro::TokenStream {
37     let mut function = syn::parse_macro_input!(item as syn::ForeignItemFn);
38 
39     let link_name = versioned_lit_str(&function.sig.ident);
40     function
41         .attrs
42         .push(syn::parse_quote! { #[link_name = #link_name] });
43 
44     function.to_token_stream().into()
45 }
46 
47 #[proc_macro]
48 pub fn versioned_stringify_ident(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
49     let ident = syn::parse_macro_input!(item as syn::Ident);
50 
51     versioned_lit_str(ident).to_token_stream().into()
52 }
53 
54 #[proc_macro]
55 pub fn versioned_suffix(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
56     if !item.is_empty() {
57         return syn::Error::new(
58             proc_macro2::Span::call_site(),
59             "`versioned_suffix!` accepts no input",
60         )
61         .to_compile_error()
62         .into();
63     };
64 
65     versioned_lit_str("").to_token_stream().into()
66 }
67