1extern crate proc_macro;
43
44mod route;
45
46use proc_macro::TokenStream;
47use quote::quote;
48
49#[proc_macro_attribute]
59pub fn web_get(args: TokenStream, input: TokenStream) -> TokenStream {
60 let gen_code = match route::Route::new(args, input, route::MethodType::Get) {
61 Ok(gen_code) => gen_code,
62 Err(err) => return err.to_compile_error().into(),
63 };
64 gen_code.generate()
65}
66
67#[proc_macro_attribute]
73pub fn web_post(args: TokenStream, input: TokenStream) -> TokenStream {
74 let gen_code = match route::Route::new(args, input, route::MethodType::Post) {
75 Ok(gen_code) => gen_code,
76 Err(err) => return err.to_compile_error().into(),
77 };
78 gen_code.generate()
79}
80
81#[proc_macro_attribute]
87pub fn web_put(args: TokenStream, input: TokenStream) -> TokenStream {
88 let gen_code = match route::Route::new(args, input, route::MethodType::Put) {
89 Ok(gen_code) => gen_code,
90 Err(err) => return err.to_compile_error().into(),
91 };
92 gen_code.generate()
93}
94
95#[proc_macro_attribute]
101pub fn web_delete(args: TokenStream, input: TokenStream) -> TokenStream {
102 let gen_code = match route::Route::new(args, input, route::MethodType::Delete) {
103 Ok(gen_code) => gen_code,
104 Err(err) => return err.to_compile_error().into(),
105 };
106 gen_code.generate()
107}
108
109#[proc_macro_attribute]
115pub fn web_head(args: TokenStream, input: TokenStream) -> TokenStream {
116 let gen_code = match route::Route::new(args, input, route::MethodType::Head) {
117 Ok(gen_code) => gen_code,
118 Err(err) => return err.to_compile_error().into(),
119 };
120 gen_code.generate()
121}
122
123#[proc_macro_attribute]
129pub fn web_connect(args: TokenStream, input: TokenStream) -> TokenStream {
130 let gen_code = match route::Route::new(args, input, route::MethodType::Connect) {
131 Ok(gen_code) => gen_code,
132 Err(err) => return err.to_compile_error().into(),
133 };
134 gen_code.generate()
135}
136
137#[proc_macro_attribute]
143pub fn web_options(args: TokenStream, input: TokenStream) -> TokenStream {
144 let gen_code = match route::Route::new(args, input, route::MethodType::Options) {
145 Ok(gen_code) => gen_code,
146 Err(err) => return err.to_compile_error().into(),
147 };
148 gen_code.generate()
149}
150
151#[proc_macro_attribute]
157pub fn web_trace(args: TokenStream, input: TokenStream) -> TokenStream {
158 let gen_code = match route::Route::new(args, input, route::MethodType::Trace) {
159 Ok(gen_code) => gen_code,
160 Err(err) => return err.to_compile_error().into(),
161 };
162 gen_code.generate()
163}
164
165#[proc_macro_attribute]
171pub fn web_patch(args: TokenStream, input: TokenStream) -> TokenStream {
172 let gen_code = match route::Route::new(args, input, route::MethodType::Patch) {
173 Ok(gen_code) => gen_code,
174 Err(err) => return err.to_compile_error().into(),
175 };
176 gen_code.generate()
177}
178
179#[proc_macro_attribute]
190pub fn rt_main(_: TokenStream, item: TokenStream) -> TokenStream {
191 let mut input = syn::parse_macro_input!(item as syn::ItemFn);
192 let attrs = &input.attrs;
193 let vis = &input.vis;
194 let sig = &mut input.sig;
195 let body = &input.block;
196 let name = &sig.ident;
197
198 if sig.asyncness.is_none() {
199 return syn::Error::new_spanned(sig.fn_token, "only async fn is supported")
200 .to_compile_error()
201 .into();
202 }
203
204 sig.asyncness = None;
205
206 (quote! {
207 #(#attrs)*
208 #vis #sig {
209 ntex::rt::System::build()
210 .name(stringify!(#name))
211 .build(ntex::rt::DefaultRuntime)
212 .block_on(async move { #body })
213 }
214 })
215 .into()
216}
217
218#[proc_macro_attribute]
229pub fn rt_test(_: TokenStream, item: TokenStream) -> TokenStream {
230 let input = syn::parse_macro_input!(item as syn::ItemFn);
231
232 let ret = &input.sig.output;
233 let name = &input.sig.ident;
234 let body = &input.block;
235 let attrs = &input.attrs;
236 let mut has_test_attr = false;
237
238 for attr in attrs {
239 if attr.path().is_ident("test") {
240 has_test_attr = true;
241 }
242 }
243
244 if input.sig.asyncness.is_none() {
245 return syn::Error::new_spanned(
246 input.sig.fn_token,
247 format!("only async fn is supported, {}", input.sig.ident),
248 )
249 .to_compile_error()
250 .into();
251 }
252
253 let result = if has_test_attr {
254 quote! {
255 #(#attrs)*
256 fn #name() #ret {
257 ntex::util::enable_test_logging();
258 ntex::rt::System::build()
259 .name(stringify!(#name))
260 .testing()
261 .build(ntex::rt::DefaultRuntime)
262 .block_on(async { #body })
263 }
264 }
265 } else {
266 quote! {
267 #[test]
268 #(#attrs)*
269 fn #name() #ret {
270 ntex::util::enable_test_logging();
271 ntex::rt::System::build()
272 .name(stringify!(#name))
273 .testing()
274 .build(ntex::rt::DefaultRuntime)
275 .block_on(async { #body })
276 }
277 }
278 };
279
280 result.into()
281}
282
283#[doc(hidden)]
294#[proc_macro_attribute]
295pub fn rt_test2(_: TokenStream, item: TokenStream) -> TokenStream {
296 let input = syn::parse_macro_input!(item as syn::ItemFn);
297
298 let ret = &input.sig.output;
299 let name = &input.sig.ident;
300 let body = &input.block;
301 let attrs = &input.attrs;
302 let mut has_test_attr = false;
303
304 for attr in attrs {
305 if attr.path().is_ident("test") {
306 has_test_attr = true;
307 }
308 }
309
310 if input.sig.asyncness.is_none() {
311 return syn::Error::new_spanned(
312 input.sig.fn_token,
313 format!("only async fn is supported, {}", input.sig.ident),
314 )
315 .to_compile_error()
316 .into();
317 }
318
319 let result = if has_test_attr {
320 quote! {
321 #(#attrs)*
322 fn #name() #ret {
323 ntex_rt::System::build()
324 .name(stringify!(#name))
325 .testing()
326 .build(ntex::rt::DefaultRuntime)
327 .block_on(async { #body })
328 }
329 }
330 } else {
331 quote! {
332 #[test]
333 #(#attrs)*
334 fn #name() #ret {
335 ntex_rt::System::build()
336 .name(stringify!(#name))
337 .testing()
338 .build(ntex::rt::DefaultRuntime)
339 .block_on(async { #body })
340 }
341 }
342 };
343
344 result.into()
345}
346
347#[doc(hidden)]
358#[proc_macro_attribute]
359pub fn rt_test_internal(_: TokenStream, item: TokenStream) -> TokenStream {
360 let input = syn::parse_macro_input!(item as syn::ItemFn);
361
362 let ret = &input.sig.output;
363 let name = &input.sig.ident;
364 let body = &input.block;
365 let attrs = &input.attrs;
366 let mut has_test_attr = false;
367
368 for attr in attrs {
369 if attr.path().is_ident("test") {
370 has_test_attr = true;
371 }
372 }
373
374 if input.sig.asyncness.is_none() {
375 return syn::Error::new_spanned(
376 input.sig.fn_token,
377 format!("only async fn is supported, {}", input.sig.ident),
378 )
379 .to_compile_error()
380 .into();
381 }
382
383 let result = if has_test_attr {
384 quote! {
385 #(#attrs)*
386 fn #name() #ret {
387 crate::util::enable_test_logging();
388 ntex_rt::System::build()
389 .name(stringify!(#name))
390 .testing()
391 .build(crate::rt::DefaultRuntime)
392 .block_on(async { #body })
393 }
394 }
395 } else {
396 quote! {
397 #[test]
398 #(#attrs)*
399 fn #name() #ret {
400 crate::util::enable_test_logging();
401 ntex_rt::System::build()
402 .name(stringify!(#name))
403 .testing()
404 .build(crate::rt::DefaultRuntime)
405 .block_on(async { #body })
406 }
407 }
408 };
409
410 result.into()
411}