Skip to main content

pyro_macro/format/
library.rs

1use syn::{
2    Ident, LitStr, Token,
3    parse::{Parse, ParseStream},
4};
5
6pub struct LibraryArgs {
7    pub meta: String,
8    pub no_ffi: bool,
9}
10
11impl Parse for LibraryArgs {
12    fn parse(input: ParseStream) -> syn::Result<Self> {
13        let mut meta = String::new();
14        let mut no_ffi = false;
15
16        while !input.is_empty() {
17            if input.peek(LitStr) {
18                let s: LitStr = input.parse()?;
19                meta = s.value();
20            } else if input.peek(Ident) {
21                let id: Ident = input.parse()?;
22                if id == "NoFFI" {
23                    no_ffi = true;
24                }
25            }
26
27            if input.peek(Token![,]) {
28                input.parse::<Token![,]>()?;
29            } else {
30                break;
31            }
32        }
33
34        Ok(LibraryArgs { meta, no_ffi })
35    }
36}
37
38/// Creates a function we can use to register the library identity
39pub fn create_ident(
40    import_location: syn::Path,
41    meta: &str,
42    no_ffi: bool,
43) -> proc_macro2::TokenStream {
44    let ffi_exports = if !no_ffi {
45        quote::quote! {
46            #[unsafe(no_mangle)]
47            pub extern "C" fn library_json_ptr() -> *const u8 {
48                LIBRARY_IDENTITY_DATA.as_ptr()
49            }
50
51            #[unsafe(no_mangle)]
52            pub extern "C" fn library_json_len() -> usize {
53                LIBRARY_IDENTITY_DATA.len()
54            }
55        }
56    } else {
57        quote::quote! {}
58    };
59
60    quote::quote! {
61        #[derive(Debug, Clone, Copy)]
62        pub struct Library;
63
64        pub const LIBRARY_IDENTITY_DATA: &'static str = concat!(
65            "{",
66            "\"meta\": \"", #meta, "\",",
67            "\"name\": \"", env!("CARGO_PKG_NAME"), "\",",
68            "\"version\": \"", env!("CARGO_PKG_VERSION"), "\"",
69            "}"
70        );
71
72        impl Library {
73            pub const META: &'static str = #meta;
74            pub const NAME: &'static str = env!("CARGO_PKG_NAME");
75            pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
76
77            pub fn register_info() -> #import_location::captured::LibraryInfo<'static> {
78                let info = #import_location::captured::LibraryInfo {
79                    meta: ::std::borrow::Cow::Borrowed(Self::META),
80                    name: ::std::borrow::Cow::Borrowed(Self::NAME),
81                    version: ::std::borrow::Cow::Borrowed(Self::VERSION),
82                };
83                #import_location::captured::register_app_identity(info.clone(), LIBRARY_IDENTITY_DATA);
84
85                info
86            }
87        }
88
89        #ffi_exports
90    }
91}