1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
// The `quote!` macro requires deep recursion.
#![recursion_limit = "512"]
#![allow(clippy::match_like_matches_macro)]
extern crate proc_macro;
use proc_macro::TokenStream as TokenStream1;
use syn::{parse_macro_input, AttributeArgs, Item, ItemImpl};
mod controller;
mod guard;
mod middleware;
mod openapi;
mod utils;
/// Saphir macro for auto trait implementation on controllers
///
/// The base macro attribule look like this : `#[controller]` and is to be put
/// on top of a Controller's method impl block
///
/// ```ignore
/// #use saphir::prelude::*;
/// #use saphir_macro::controller;
///
/// #struct ExampleController;
///
/// #[controller]
/// impl ExampleController {
/// // ....
/// }
/// ```
///
/// Different arguments can be passed to the controller macro:
/// - `name="<newName>"` will take place of the default controller name (by
/// default the controller name is the struct name, lowercase, with the
/// "controller keyword stripped"). the name will result as the basepath of
/// the controller.
/// - `version=<u16>` use for api version, the version will be added before the
/// name as the controller basepath
/// - `prefix="<prefix>"` add a prefix before the basepath and the version.
///
/// ##Example
///
/// ```ignore
/// use saphir::prelude::*;
/// use saphir_macro::controller;
///
/// struct ExampleController;
///
/// #[controller(name="test", version=1, prefix="api")]
/// impl ExampleController {
/// // ....
/// }
/// ```
///
/// This will result in the Example controller being routed to `/api/v1/test`
#[proc_macro_attribute]
pub fn controller(args: TokenStream1, input: TokenStream1) -> TokenStream1 {
let args = parse_macro_input!(args as AttributeArgs);
let input = parse_macro_input!(input as ItemImpl);
let expanded = controller::expand_controller(args, input).unwrap_or_else(|e| e.to_compile_error());
TokenStream1::from(expanded)
}
#[proc_macro_attribute]
pub fn middleware(_args: TokenStream1, input: TokenStream1) -> TokenStream1 {
let input = parse_macro_input!(input as ItemImpl);
let expanded = middleware::expand_middleware(input).unwrap_or_else(|e| e.to_compile_error());
TokenStream1::from(expanded)
}
#[proc_macro_attribute]
pub fn guard(_args: TokenStream1, input: TokenStream1) -> TokenStream1 {
let input = parse_macro_input!(input as ItemImpl);
let expanded = guard::expand_guard(input).unwrap_or_else(|e| e.to_compile_error());
TokenStream1::from(expanded)
}
/// Saphir OpenAPI macro which can be put on top of a struct or enum definition.
/// Allow specifying informations for the corresponding type when generating
/// OpenAPI documentation through saphir's CLI.
///
/// The syntax looks like this : `#[openapi(mime = "application/json")]`.
/// `mime` can either be a full mimetype, or one of the following keywords:
/// - json (application/json)
/// - form (application/x-www-form-urlencoded)
/// - any (*/*)
#[proc_macro_attribute]
pub fn openapi(args: TokenStream1, input: TokenStream1) -> TokenStream1 {
let args = parse_macro_input!(args as AttributeArgs);
let parsed_input = parse_macro_input!(input as Item);
let expanded = openapi::validate_openapi(args, parsed_input).unwrap_or_else(|e| e.to_compile_error());
TokenStream1::from(expanded)
}