1extern crate proc_macro;
2
3use core::{ops::ControlFlow, str::FromStr};
4use proc_macro::{TokenStream, TokenTree};
5
6#[proc_macro_derive(Message)]
7pub fn message(stream: TokenStream) -> TokenStream {
8 let mut name = "".to_string();
9 let nonident = ["enum".to_string(), "struct".to_string()];
10 stream
11 .into_iter()
12 .try_for_each(|tree| {
16 if let TokenTree::Ident(ident) = tree {
17 name = ident.to_string();
18 if !nonident.contains(&&name) {
19 return ControlFlow::Break(());
20 }
21 }
22 ControlFlow::Continue(())
23 });
24 assert_ne!(name, "", "struct/enum name NOT FOUND");
25 let raw_token =
26 r#"impl crossbus::message::Message for <+ident+> { }"#.replace("<+ident+>", &name);
27 TokenStream::from_str(&raw_token).unwrap()
28}
29
30#[proc_macro_attribute]
31pub fn main(attr: TokenStream, stream: TokenStream) -> TokenStream {
32 let mut name = "".to_string();
33 let raw_stream = stream.to_string();
34 if !raw_stream.contains("async fn ") {
35 panic!("attribute for async function ONLY");
36 }
37 let raw_attr = attr.to_string();
38 let rt_vec: Vec<&str> = raw_attr.split(",").filter(|en| *en != "").collect();
39 if rt_vec.len() != 1 {
40 panic!("ONLY one type runtime is allowed");
41 }
42 let rt_str_ = rt_vec[0].replace(" ", "");
43 let rt_str = rt_str_.strip_prefix("runtime=");
44 if rt_str.is_none() {
45 panic!("Runtime not found, HELP: #[main(runtime = \"xx::xx\")]");
46 }
47 let rt_str = rt_str.unwrap();
48 let nonident = [
49 "fn".to_owned(),
50 "async".to_owned(),
51 "pub".to_owned(),
52 "mod".to_owned(),
53 "in".to_owned(),
54 "super".to_owned(),
55 "crate".to_owned(),
56 ];
57 stream
58 .into_iter()
59 .try_for_each(|tree| {
63 if let TokenTree::Ident(ident) = tree {
64 name = ident.to_string();
65 if !nonident.contains(&&name) {
66 return ControlFlow::Break(());
67 }
68 }
69 ControlFlow::Continue(())
70 });
71 assert_eq!(name, "main", "attribute for main function ONLY");
72 let runtime;
73 match rt_str {
74 "async-std" => {
75 runtime = "crossbus::rt::runtime_async_std::Runtime::block_on";
76 }
77 "tokio" => {
78 runtime = "crossbus::rt::runtime_tokio::Runtime::block_on";
79 }
80 "wasm32" | "wasm64" => {
81 runtime = "crossbus::rt::runtime_wasm32::Runtime::spawn_local";
82 }
83 _ => {
84 runtime = rt_str;
85 }
86 }
87 let raw_token = r#"fn main() {
88<+fn+>
89
90let _ = <+runtime+>(async {
91
92 main().await;
93 crossbus::reactor::Reactor::as_future().await;
94}); }"#
95 .replace("<+fn+>", &raw_stream)
96 .replace("<+runtime+>", runtime);
97 TokenStream::from_str(&raw_token).unwrap()
98}