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()
220 .name(stringify!(#name))
221 .build(ntex::rt::DefaultRuntime)
222 .block_on(async move { #body })
223 }
224 })
225 .into()
226}
227
228#[proc_macro_attribute]
239pub fn rt_test(_: TokenStream, item: TokenStream) -> TokenStream {
240 let input = syn::parse_macro_input!(item as syn::ItemFn);
241
242 let ret = &input.sig.output;
243 let name = &input.sig.ident;
244 let body = &input.block;
245 let attrs = &input.attrs;
246 let mut has_test_attr = false;
247
248 for attr in attrs {
249 if attr.path.is_ident("test") {
250 has_test_attr = true;
251 }
252 }
253
254 if input.sig.asyncness.is_none() {
255 return syn::Error::new_spanned(
256 input.sig.fn_token,
257 format!("only async fn is supported, {}", input.sig.ident),
258 )
259 .to_compile_error()
260 .into();
261 }
262
263 let result = if has_test_attr {
264 quote! {
265 #(#attrs)*
266 fn #name() #ret {
267 ntex::util::enable_test_logging();
268 ntex::rt::System::build()
269 .name(stringify!(#name))
270 .testing()
271 .build(ntex::rt::DefaultRuntime)
272 .block_on(async { #body })
273 }
274 }
275 } else {
276 quote! {
277 #[test]
278 #(#attrs)*
279 fn #name() #ret {
280 ntex::util::enable_test_logging();
281 ntex::rt::System::build()
282 .name(stringify!(#name))
283 .testing()
284 .build(ntex::rt::DefaultRuntime)
285 .block_on(async { #body })
286 }
287 }
288 };
289
290 result.into()
291}
292
293#[doc(hidden)]
304#[proc_macro_attribute]
305pub fn rt_test2(_: TokenStream, item: TokenStream) -> TokenStream {
306 let input = syn::parse_macro_input!(item as syn::ItemFn);
307
308 let ret = &input.sig.output;
309 let name = &input.sig.ident;
310 let body = &input.block;
311 let attrs = &input.attrs;
312 let mut has_test_attr = false;
313
314 for attr in attrs {
315 if attr.path.is_ident("test") {
316 has_test_attr = true;
317 }
318 }
319
320 if input.sig.asyncness.is_none() {
321 return syn::Error::new_spanned(
322 input.sig.fn_token,
323 format!("only async fn is supported, {}", input.sig.ident),
324 )
325 .to_compile_error()
326 .into();
327 }
328
329 let result = if has_test_attr {
330 quote! {
331 #(#attrs)*
332 fn #name() #ret {
333 ntex_rt::System::build()
334 .name(stringify!(#name))
335 .testing()
336 .build(ntex::rt::DefaultRuntime)
337 .block_on(async { #body })
338 }
339 }
340 } else {
341 quote! {
342 #[test]
343 #(#attrs)*
344 fn #name() #ret {
345 ntex_rt::System::build()
346 .name(stringify!(#name))
347 .testing()
348 .build(ntex::rt::DefaultRuntime)
349 .block_on(async { #body })
350 }
351 }
352 };
353
354 result.into()
355}
356
357#[doc(hidden)]
368#[proc_macro_attribute]
369pub fn rt_test_internal(_: TokenStream, item: TokenStream) -> TokenStream {
370 let input = syn::parse_macro_input!(item as syn::ItemFn);
371
372 let ret = &input.sig.output;
373 let name = &input.sig.ident;
374 let body = &input.block;
375 let attrs = &input.attrs;
376 let mut has_test_attr = false;
377
378 for attr in attrs {
379 if attr.path.is_ident("test") {
380 has_test_attr = true;
381 }
382 }
383
384 if input.sig.asyncness.is_none() {
385 return syn::Error::new_spanned(
386 input.sig.fn_token,
387 format!("only async fn is supported, {}", input.sig.ident),
388 )
389 .to_compile_error()
390 .into();
391 }
392
393 let result = if has_test_attr {
394 quote! {
395 #(#attrs)*
396 fn #name() #ret {
397 crate::util::enable_test_logging();
398 ntex_rt::System::build()
399 .name(stringify!(#name))
400 .testing()
401 .build(crate::rt::DefaultRuntime)
402 .block_on(async { #body })
403 }
404 }
405 } else {
406 quote! {
407 #[test]
408 #(#attrs)*
409 fn #name() #ret {
410 crate::util::enable_test_logging();
411 ntex_rt::System::build()
412 .name(stringify!(#name))
413 .testing()
414 .build(crate::rt::DefaultRuntime)
415 .block_on(async { #body })
416 }
417 }
418 };
419
420 result.into()
421}