mendes_macros/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::{quote, ToTokens};
5use syn::parse_macro_input;
6
7mod cookies;
8mod forms;
9mod route;
10
11#[proc_macro_attribute]
12pub fn cookie(meta: TokenStream, item: TokenStream) -> TokenStream {
13    let ast = parse_macro_input!(item as syn::ItemStruct);
14    let meta = parse_macro_input!(meta as cookies::CookieMeta);
15    let cookie = cookies::cookie(&meta, &ast);
16    let mut tokens = ast.to_token_stream();
17    tokens.extend(cookie);
18    TokenStream::from(tokens)
19}
20
21#[proc_macro_attribute]
22pub fn form(meta: TokenStream, item: TokenStream) -> TokenStream {
23    let mut ast = parse_macro_input!(item as syn::ItemStruct);
24    let meta = parse_macro_input!(meta as forms::FormMeta);
25    let display = forms::form(&meta, &mut ast);
26    let mut tokens = ast.to_token_stream();
27    tokens.extend(display);
28    TokenStream::from(tokens)
29}
30
31/// Implement a request handler wrapper for the annotated function
32///
33/// The attribute takes allowed methods as its arguments:
34///
35/// ```ignore
36/// /// This handler will immediately return a `405 Method not allowed`
37/// /// error for all request methods other than `GET`
38/// #[handler(GET)]
39/// fn hello(_: &App) -> Result<Response<String>, Error> {
40///     Ok(Response::builder()
41///         .status(StatusCode::OK)
42///         .body("Hello, world".into())
43///         .unwrap())
44/// }
45/// ```
46///
47/// The first argument of the function must be a reference to an implementer of
48/// the `Application` trait (the implementor may also be wrapped in an `Arc`).
49/// All unannotated arguments must be of types that implement the `FromContext`
50/// trait for the `Application` type used in the first argument. This includes
51/// `&http::request::Parts`, the `Request`'s headers and any number of types
52/// that can represent a path component from the URI:
53///
54/// * `&[u8]` for the bytes representation of the path component
55/// * `Cow<'_, str>`
56/// * `String`
57/// * Numeric types (`i8`, `u8`, `i16`, `u16`, ..., `isize`, `usize`, `f32`, `f64`)
58/// * `bool` and `char`
59/// * If the `hyper` feature is enabled, `hyper::body::Body`
60///   (only if `Application::RequestBody` is also `Body`)
61///
62/// Each of these types can be wrapped in `Option` for optional path components.
63/// Additionally, there are two attributes that may be used on handler arguments:
64///
65/// * `#[rest]`: a `&str` representing the part of the request path not yet consumed by routing
66/// * `#[query]`: a type that implements `Deserialize`, and will be used to deserialize the URI query
67///
68/// This macro will generate a module that contains a `call()` function mirroring
69/// the original function, and you may rely on this behavior (for example, for testing).
70///
71/// ```ignore
72/// mod hello {
73///    use super::*;
74///    /// ... some internals hidden ...
75///    pub(super) async fn call(_: &App) -> Result<Response<Body>, Error> {
76///        Ok(Response::builder()
77///            .status(StatusCode::OK)
78///            .body("Hello, world".into())
79///            .unwrap())
80///    }
81/// }
82/// ```
83#[proc_macro_attribute]
84pub fn handler(meta: TokenStream, item: TokenStream) -> TokenStream {
85    let ast = parse_macro_input!(item as syn::ItemFn);
86    let methods = parse_macro_input!(meta as route::HandlerMethods).methods;
87    route::handler(&methods, ast)
88}
89
90#[proc_macro_attribute]
91pub fn scope(_: TokenStream, item: TokenStream) -> TokenStream {
92    let ast = parse_macro_input!(item as syn::ItemFn);
93    route::scope(ast)
94}
95
96#[proc_macro]
97pub fn route(item: TokenStream) -> TokenStream {
98    let mut ast = parse_macro_input!(item as syn::ExprMatch);
99    route::route(&mut ast);
100    quote!(#ast).into()
101}
102
103#[proc_macro_derive(ToField, attributes(option))]
104pub fn derive_to_field(item: TokenStream) -> TokenStream {
105    let ast = parse_macro_input!(item as syn::DeriveInput);
106    TokenStream::from(forms::to_field(ast))
107}