craydate_macro/
lib.rs

1#![deny(clippy::all)]
2
3extern crate proc_macro;
4extern crate proc_macro2;
5extern crate quote;
6extern crate syn;
7
8use proc_macro::TokenStream;
9use quote::{quote, quote_spanned};
10use syn::spanned::Spanned;
11use syn::{parse_macro_input, ItemFn};
12
13#[proc_macro_attribute]
14pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
15  let func = parse_macro_input!(item as ItemFn);
16  let func_ident = &func.sig.ident;
17
18  if func.sig.asyncness.is_none() {
19    return quote_spanned! { func.sig.span()  =>
20      compile_error!{"The #[craydate::main] function must be async."}
21    }
22    .into();
23  }
24
25  quote!{
26    mod __main {
27      use super::*;
28      use ::alloc::boxed::Box;
29      use ::core::pin::Pin;
30      use ::core::future::Future;
31      use ::craydate::macro_helpers::__private::*;
32
33      #[no_mangle]
34      extern "C" fn eventHandler(eh1: EventHandler1, eh2: EventHandler2, eh3: EventHandler3) -> i32 {
35        fn main_wrapper(api: ::craydate::Api) -> Pin<Box<dyn Future<Output = !>>> {
36          Box::pin(#func_ident(api))
37        }
38        let config = GameConfig {
39          main_fn: main_wrapper,
40        };
41        event_handler(eh1, eh2, eh3, config);
42        0  // What does it do? We don't know.
43      }
44
45      #[cfg(all(target_arch = "arm", target_os = "none"))]
46      type EventHandlerFn = extern "C" fn(EventHandler1, EventHandler2, EventHandler3) -> i32;
47
48      #[cfg(all(target_arch = "arm", target_os = "none"))]
49      #[used]
50      #[link_section = ".capi_handler"]
51      static EVENT_HANDLER: EventHandlerFn = eventHandler;
52
53      #func
54    }
55  }.into()
56}