wasmtime_internal_versioned_export_macros/
lib.rs

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//! > **⚠️ Warning ⚠️**: this crate is an internal-only crate for the Wasmtime
6//! > project and is not intended for general use. APIs are not strictly
7//! > reviewed for safety and usage outside of Wasmtime may have bugs. If
8//! > you're interested in using this feel free to file an issue on the
9//! > Wasmtime repository to start a discussion about doing so, but otherwise
10//! > be aware that your usage of this crate is not supported.
11
12use quote::ToTokens;
13
14const VERSION: &str = env!("CARGO_PKG_VERSION");
15
16fn version(value: impl std::fmt::Display) -> String {
17    format!("{}_{}", value, VERSION.replace('.', "_"))
18}
19
20fn versioned_lit_str(value: impl std::fmt::Display) -> syn::LitStr {
21    syn::LitStr::new(version(value).as_str(), proc_macro2::Span::call_site())
22}
23
24#[proc_macro_attribute]
25pub fn versioned_export(
26    _attr: proc_macro::TokenStream,
27    item: proc_macro::TokenStream,
28) -> proc_macro::TokenStream {
29    let mut function = syn::parse_macro_input!(item as syn::ItemFn);
30
31    let export_name = versioned_lit_str(&function.sig.ident);
32    function
33        .attrs
34        .push(syn::parse_quote! { #[unsafe(export_name = #export_name)] });
35
36    function.to_token_stream().into()
37}
38
39#[proc_macro_attribute]
40pub fn versioned_link(
41    _attr: proc_macro::TokenStream,
42    item: proc_macro::TokenStream,
43) -> proc_macro::TokenStream {
44    let mut function = syn::parse_macro_input!(item as syn::ForeignItemFn);
45
46    let link_name = versioned_lit_str(&function.sig.ident);
47    function
48        .attrs
49        .push(syn::parse_quote! { #[link_name = #link_name] });
50
51    function.to_token_stream().into()
52}
53
54#[proc_macro]
55pub fn versioned_stringify_ident(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
56    let ident = syn::parse_macro_input!(item as syn::Ident);
57
58    versioned_lit_str(ident).to_token_stream().into()
59}
60
61#[proc_macro]
62pub fn versioned_suffix(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
63    if !item.is_empty() {
64        return syn::Error::new(
65            proc_macro2::Span::call_site(),
66            "`versioned_suffix!` accepts no input",
67        )
68        .to_compile_error()
69        .into();
70    };
71
72    versioned_lit_str("").to_token_stream().into()
73}