wolfram_library_link_macros/
lib.rs1mod export;
2
3
4use proc_macro::TokenStream;
5use proc_macro2::TokenStream as TokenStream2;
6
7use quote::quote;
8use syn::{spanned::Spanned, Error, Item};
9
10#[proc_macro_attribute]
15pub fn init(
16 attr: proc_macro::TokenStream,
17 item: proc_macro::TokenStream,
18) -> proc_macro::TokenStream {
19 match init_(attr.into(), item) {
20 Ok(tokens) => tokens.into(),
21 Err(err) => err.into_compile_error().into(),
22 }
23}
24
25fn init_(attr: TokenStream2, item: TokenStream) -> Result<TokenStream2, Error> {
26 if !attr.is_empty() {
28 return Err(Error::new(attr.span(), "unexpected attribute arguments"));
29 }
30
31 let item: Item = syn::parse(item)?;
36
37 let func = match item {
38 Item::Fn(func) => func,
39 _ => {
40 return Err(Error::new(
41 attr.span(),
42 "this attribute can only be applied to `fn(..) {..}` items",
43 ))
44 },
45 };
46
47 if let Some(async_) = func.sig.asyncness {
53 return Err(Error::new(
54 async_.span(),
55 "initialization function cannot be `async`",
56 ));
57 }
58
59 if let Some(lt) = func.sig.generics.lt_token {
61 return Err(Error::new(
62 lt.span(),
63 "initialization function cannot be generic",
64 ));
65 }
66
67 if !func.sig.inputs.is_empty() {
69 return Err(Error::new(
70 func.sig.inputs.span(),
71 "initialization function should have zero parameters",
72 ));
73 }
74
75 let user_init_fn_name: syn::Ident = func.sig.ident.clone();
80
81 let output = quote! {
82 #func
83
84 #[no_mangle]
85 pub unsafe extern "C" fn WolframLibrary_initialize(
86 lib: ::wolfram_library_link::sys::WolframLibraryData,
87 ) -> ::std::os::raw::c_int {
88 ::wolfram_library_link::macro_utils::init_with_user_function(
89 lib,
90 #user_init_fn_name
91 )
92 }
93 };
94
95 Ok(output)
96}
97
98#[proc_macro_attribute]
103pub fn export(
104 attrs: proc_macro::TokenStream,
105 item: proc_macro::TokenStream,
106) -> proc_macro::TokenStream {
107 let attrs: syn::AttributeArgs = syn::parse_macro_input!(attrs);
108
109 match self::export::export(attrs, item) {
110 Ok(tokens) => tokens.into(),
111 Err(err) => err.into_compile_error().into(),
112 }
113}