borderless_sdk_macros/
lib.rs1use agent::AgentArgs;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, Item, ItemMod};
5
6mod action;
7mod agent;
8mod contract;
9mod schedule;
10mod state;
11mod utils;
12
13#[proc_macro_attribute]
18pub fn contract(_attrs: TokenStream, input: TokenStream) -> TokenStream {
19 let module = parse_macro_input!(input as ItemMod);
20
21 if module.content.is_none() {
23 return syn::Error::new_spanned(
24 module,
25 "Macro can only be implemented on modules that have some content",
26 )
27 .to_compile_error()
28 .into();
29 }
30 let (brace, mut items) = module.content.unwrap();
31
32 let new_tokens = match contract::parse_module_content(brace.span.join(), &items, &module.ident)
34 {
35 Ok(tokens) => tokens,
36 Err(e) => return e.to_compile_error().into(),
37 };
38
39 items.push(Item::Verbatim(new_tokens));
41
42 match module.vis {
44 syn::Visibility::Public(_) => (),
45 _ => {
46 let tokens =
47 syn::Error::new_spanned(module.mod_token, "Contract module must be public")
48 .to_compile_error();
49 items.push(Item::Verbatim(tokens));
50 }
51 }
52
53 let wasm_exports = contract::generate_wasm_exports(&module.ident);
54
55 let new_module = ItemMod {
57 attrs: module.attrs,
58 vis: module.vis,
59 unsafety: module.unsafety,
60 mod_token: module.mod_token,
61 ident: module.ident,
62 content: Some((brace, items)),
63 semi: module.semi,
64 };
65
66 quote! {
68 #new_module
69 #wasm_exports
70 }
71 .into()
72}
73
74#[proc_macro_attribute]
75pub fn agent(attrs: TokenStream, input: TokenStream) -> TokenStream {
76 let module = parse_macro_input!(input as ItemMod);
77 let parsed_attrs = syn::parse_macro_input!(attrs as AgentArgs);
78
79 if module.content.is_none() {
81 return syn::Error::new_spanned(
82 module,
83 "Macro can only be implemented on modules that have some content",
84 )
85 .to_compile_error()
86 .into();
87 }
88 let (brace, mut items) = module.content.unwrap();
89
90 let use_ws = parsed_attrs.websocket.unwrap_or_default();
92
93 let new_tokens = match agent::parse_module_content(brace.span.join(), &items, use_ws) {
95 Ok(tokens) => tokens,
96 Err(e) => return e.to_compile_error().into(),
97 };
98
99 items.push(Item::Verbatim(new_tokens));
101
102 match module.vis {
104 syn::Visibility::Public(_) => (),
105 _ => {
106 let tokens = syn::Error::new_spanned(module.mod_token, "Agent module must be public")
107 .to_compile_error();
108 items.push(Item::Verbatim(tokens));
109 }
110 }
111
112 let wasm_exports = agent::generate_wasm_exports(&module.ident);
113
114 let wasm_ws_exports = if use_ws {
116 agent::generate_ws_wasm_exports(&module.ident)
117 } else {
118 quote! {}
119 };
120
121 let new_module = ItemMod {
123 attrs: module.attrs,
124 vis: module.vis,
125 unsafety: module.unsafety,
126 mod_token: module.mod_token,
127 ident: module.ident,
128 content: Some((brace, items)),
129 semi: module.semi,
130 };
131
132 quote! {
134 #new_module
135 #wasm_exports
136 #wasm_ws_exports
137 }
138 .into()
139}
140
141#[proc_macro_derive(State)]
142pub fn derive_contract_state(input: TokenStream) -> TokenStream {
143 let input = parse_macro_input!(input);
144 let output = state::impl_state(input);
145
146 match output {
147 syn::Result::Ok(token_stream) => token_stream,
148 syn::Result::Err(err) => err.to_compile_error(),
149 }
150 .into()
151}
152
153#[proc_macro_attribute]
154pub fn action(_attrs: TokenStream, input: TokenStream) -> TokenStream {
155 input
156}
157
158#[proc_macro_attribute]
159pub fn schedule(_attrs: TokenStream, input: TokenStream) -> TokenStream {
160 input
161}