1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-02 13:29:24 +00:00
actix-web/actix-web-codegen/src/lib.rs

142 lines
3.5 KiB
Rust
Raw Normal View History

#![recursion_limit = "512"]
extern crate proc_macro;
use proc_macro::TokenStream;
2020-09-22 21:42:51 +00:00
mod route;
2020-09-22 21:42:51 +00:00
/// Creates resource handler, allowing multiple HTTP method guards.
///
2020-09-22 21:42:51 +00:00
/// ## Syntax
/// ```text
/// #[route("path", method="HTTP_METHOD"[, attributes])]
/// ```
///
2020-09-22 21:42:51 +00:00
/// ### Attributes
/// - `"path"` - Raw literal string with path for which to register handler.
/// - `method="HTTP_METHOD"` - Registers HTTP method to provide guard for. Upper-case string, "GET", "POST" for example.
/// - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
/// - `wrap="Middleware"` - Registers a resource middleware.
///
2020-09-22 21:42:51 +00:00
/// ### Notes
/// Function name can be specified as any expression that is going to be accessible to the generate
/// code, e.g `my_guard` or `my_module::my_guard`.
///
2020-09-22 21:42:51 +00:00
/// ## Example
///
2020-09-22 21:42:51 +00:00
/// ```rust
/// use actix_web::HttpResponse;
/// use actix_web_codegen::route;
///
2020-09-22 21:42:51 +00:00
/// #[route("/", method="GET", method="HEAD")]
/// async fn example() -> HttpResponse {
/// HttpResponse::Ok().finish()
/// }
/// ```
#[proc_macro_attribute]
2020-09-22 21:42:51 +00:00
pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
route::with_method(None, args, input)
}
2020-09-22 21:42:51 +00:00
macro_rules! doc_comment {
($x:expr; $($tt:tt)*) => {
#[doc = $x]
$($tt)*
};
}
2020-09-22 21:42:51 +00:00
macro_rules! method_macro {
(
$($variant:ident, $method:ident,)+
) => {
$(doc_comment! {
concat!("
Creates route handler with `actix_web::guard::", stringify!($variant), "`.
## Syntax
```text
#[", stringify!($method), r#"("path"[, attributes])]
```
### Attributes
- `"path"` - Raw literal string with path for which to register handler.
- `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`.
- `wrap="Middleware"` - Registers a resource middleware.
### Notes
Function name can be specified as any expression that is going to be accessible to the generate
code, e.g `my_guard` or `my_module::my_guard`.
## Example
```rust
use actix_web::HttpResponse;
use actix_web_codegen::"#, stringify!($method), ";
#[", stringify!($method), r#"("/")]
async fn example() -> HttpResponse {
HttpResponse::Ok().finish()
}
2020-09-22 21:42:51 +00:00
```
"#);
#[proc_macro_attribute]
pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
route::with_method(Some(route::MethodType::$variant), args, input)
}
})+
};
2019-06-05 02:43:13 +00:00
}
2020-09-22 21:42:51 +00:00
method_macro! {
Get, get,
Post, post,
Put, put,
Delete, delete,
Head, head,
Connect, connect,
Options, options,
Trace, trace,
Patch, patch,
}
/// Marks async main function as the actix system entry-point.
///
/// ## Usage
///
/// ```rust
/// #[actix_web::main]
/// async fn main() {
/// async { println!("Hello world"); }.await
/// }
/// ```
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
use quote::quote;
let mut input = syn::parse_macro_input!(item as syn::ItemFn);
let attrs = &input.attrs;
let vis = &input.vis;
let sig = &mut input.sig;
let body = &input.block;
let name = &sig.ident;
if sig.asyncness.is_none() {
return syn::Error::new_spanned(sig.fn_token, "only async fn is supported")
.to_compile_error()
.into();
}
sig.asyncness = None;
(quote! {
#(#attrs)*
#vis #sig {
actix_web::rt::System::new(stringify!(#name))
.block_on(async move { #body })
}
})
.into()
}