1extern crate proc_macro;
43
44mod route;
45
46use proc_macro::TokenStream;
47use quote::quote;
48use syn::parse_macro_input;
49
50#[proc_macro_attribute]
60pub fn web_get(args: TokenStream, input: TokenStream) -> TokenStream {
61 let args = parse_macro_input!(args as syn::AttributeArgs);
62 let gen_code = match route::Route::new(args, input, route::MethodType::Get) {
63 Ok(gen_code) => gen_code,
64 Err(err) => return err.to_compile_error().into(),
65 };
66 gen_code.generate()
67}
68
69#[proc_macro_attribute]
75pub fn web_post(args: TokenStream, input: TokenStream) -> TokenStream {
76 let args = parse_macro_input!(args as syn::AttributeArgs);
77 let gen_code = match route::Route::new(args, input, route::MethodType::Post) {
78 Ok(gen_code) => gen_code,
79 Err(err) => return err.to_compile_error().into(),
80 };
81 gen_code.generate()
82}
83
84#[proc_macro_attribute]
90pub fn web_put(args: TokenStream, input: TokenStream) -> TokenStream {
91 let args = parse_macro_input!(args as syn::AttributeArgs);
92 let gen_code = match route::Route::new(args, input, route::MethodType::Put) {
93 Ok(gen_code) => gen_code,
94 Err(err) => return err.to_compile_error().into(),
95 };
96 gen_code.generate()
97}
98
99#[proc_macro_attribute]
105pub fn web_delete(args: TokenStream, input: TokenStream) -> TokenStream {
106 let args = parse_macro_input!(args as syn::AttributeArgs);
107 let gen_code = match route::Route::new(args, input, route::MethodType::Delete) {
108 Ok(gen_code) => gen_code,
109 Err(err) => return err.to_compile_error().into(),
110 };
111 gen_code.generate()
112}
113
114#[proc_macro_attribute]
120pub fn web_head(args: TokenStream, input: TokenStream) -> TokenStream {
121 let args = parse_macro_input!(args as syn::AttributeArgs);
122 let gen_code = match route::Route::new(args, input, route::MethodType::Head) {
123 Ok(gen_code) => gen_code,
124 Err(err) => return err.to_compile_error().into(),
125 };
126 gen_code.generate()
127}
128
129#[proc_macro_attribute]
135pub fn web_connect(args: TokenStream, input: TokenStream) -> TokenStream {
136 let args = parse_macro_input!(args as syn::AttributeArgs);
137 let gen_code = match route::Route::new(args, input, route::MethodType::Connect) {
138 Ok(gen_code) => gen_code,
139 Err(err) => return err.to_compile_error().into(),
140 };
141 gen_code.generate()
142}
143
144#[proc_macro_attribute]
150pub fn web_options(args: TokenStream, input: TokenStream) -> TokenStream {
151 let args = parse_macro_input!(args as syn::AttributeArgs);
152 let gen_code = match route::Route::new(args, input, route::MethodType::Options) {
153 Ok(gen_code) => gen_code,
154 Err(err) => return err.to_compile_error().into(),
155 };
156 gen_code.generate()
157}
158
159#[proc_macro_attribute]
165pub fn web_trace(args: TokenStream, input: TokenStream) -> TokenStream {
166 let args = parse_macro_input!(args as syn::AttributeArgs);
167 let gen_code = match route::Route::new(args, input, route::MethodType::Trace) {
168 Ok(gen_code) => gen_code,
169 Err(err) => return err.to_compile_error().into(),
170 };
171 gen_code.generate()
172}
173
174#[proc_macro_attribute]
180pub fn web_patch(args: TokenStream, input: TokenStream) -> TokenStream {
181 let args = parse_macro_input!(args as syn::AttributeArgs);
182 let gen_code = match route::Route::new(args, input, route::MethodType::Patch) {
183 Ok(gen_code) => gen_code,
184 Err(err) => return err.to_compile_error().into(),
185 };
186 gen_code.generate()
187}
188
189#[proc_macro_attribute]
200pub fn rt_main(_: TokenStream, item: TokenStream) -> TokenStream {
201 let mut input = syn::parse_macro_input!(item as syn::ItemFn);
202 let attrs = &input.attrs;
203 let vis = &input.vis;
204 let sig = &mut input.sig;
205 let body = &input.block;
206 let name = &sig.ident;
207
208 if sig.asyncness.is_none() {
209 return syn::Error::new_spanned(sig.fn_token, "only async fn is supported")
210 .to_compile_error()
211 .into();
212 }
213
214 sig.asyncness = None;
215
216 (quote! {
217 #(#attrs)*
218 #vis #sig {
219 ntex::rt::System::build().name(stringify!(#name))
220 .build(ntex::rt::DefaultRuntime)
221 .block_on(async move { #body })
222 }
223 })
224 .into()
225}
226
227#[proc_macro_attribute]
238pub fn rt_test(_: TokenStream, item: TokenStream) -> TokenStream {
239 let input = syn::parse_macro_input!(item as syn::ItemFn);
240
241 let ret = &input.sig.output;
242 let name = &input.sig.ident;
243 let body = &input.block;
244 let attrs = &input.attrs;
245 let mut has_test_attr = false;
246
247 for attr in attrs {
248 if attr.path.is_ident("test") {
249 has_test_attr = true;
250 }
251 }
252
253 if input.sig.asyncness.is_none() {
254 return syn::Error::new_spanned(
255 input.sig.fn_token,
256 format!("only async fn is supported, {}", input.sig.ident),
257 )
258 .to_compile_error()
259 .into();
260 }
261
262 let result = if has_test_attr {
263 quote! {
264 #(#attrs)*
265 fn #name() #ret {
266 ntex::util::enable_test_logging();
267 ntex::rt::System::build().name("test")
268 .build(ntex::rt::DefaultRuntime)
269 .block_on(async { #body })
270 }
271 }
272 } else {
273 quote! {
274 #[test]
275 #(#attrs)*
276 fn #name() #ret {
277 ntex::util::enable_test_logging();
278 ntex::rt::System::build().name("test")
279 .build(ntex::rt::DefaultRuntime)
280 .block_on(async { #body })
281 }
282 }
283 };
284
285 result.into()
286}
287
288#[doc(hidden)]
299#[proc_macro_attribute]
300pub fn rt_test2(_: TokenStream, item: TokenStream) -> TokenStream {
301 let input = syn::parse_macro_input!(item as syn::ItemFn);
302
303 let ret = &input.sig.output;
304 let name = &input.sig.ident;
305 let body = &input.block;
306 let attrs = &input.attrs;
307 let mut has_test_attr = false;
308
309 for attr in attrs {
310 if attr.path.is_ident("test") {
311 has_test_attr = true;
312 }
313 }
314
315 if input.sig.asyncness.is_none() {
316 return syn::Error::new_spanned(
317 input.sig.fn_token,
318 format!("only async fn is supported, {}", input.sig.ident),
319 )
320 .to_compile_error()
321 .into();
322 }
323
324 let result = if has_test_attr {
325 quote! {
326 #(#attrs)*
327 fn #name() #ret {
328 ntex_rt::System::build().name("test")
329 .build(ntex::rt::DefaultRuntime)
330 .block_on(async { #body })
331 }
332 }
333 } else {
334 quote! {
335 #[test]
336 #(#attrs)*
337 fn #name() #ret {
338 ntex_rt::System::build().name("test")
339 .build(ntex::rt::DefaultRuntime)
340 .block_on(async { #body })
341 }
342 }
343 };
344
345 result.into()
346}
347
348#[doc(hidden)]
359#[proc_macro_attribute]
360pub fn rt_test_internal(_: TokenStream, item: TokenStream) -> TokenStream {
361 let input = syn::parse_macro_input!(item as syn::ItemFn);
362
363 let ret = &input.sig.output;
364 let name = &input.sig.ident;
365 let body = &input.block;
366 let attrs = &input.attrs;
367 let mut has_test_attr = false;
368
369 for attr in attrs {
370 if attr.path.is_ident("test") {
371 has_test_attr = true;
372 }
373 }
374
375 if input.sig.asyncness.is_none() {
376 return syn::Error::new_spanned(
377 input.sig.fn_token,
378 format!("only async fn is supported, {}", input.sig.ident),
379 )
380 .to_compile_error()
381 .into();
382 }
383
384 let result = if has_test_attr {
385 quote! {
386 #(#attrs)*
387 fn #name() #ret {
388 crate::util::enable_test_logging();
389 ntex_rt::System::build().name("test")
390 .build(crate::rt::DefaultRuntime)
391 .block_on(async { #body })
392 }
393 }
394 } else {
395 quote! {
396 #[test]
397 #(#attrs)*
398 fn #name() #ret {
399 crate::util::enable_test_logging();
400 ntex_rt::System::build().name("test")
401 .build(crate::rt::DefaultRuntime)
402 .block_on(async { #body })
403 }
404 }
405 };
406
407 result.into()
408}