1#[cfg(feature = "api")]
2mod api;
3#[cfg(all(feature = "api", feature = "stream"))]
4mod api_stream;
5mod args;
6#[cfg(feature = "api")]
7mod request_extractor;
8mod resource;
9mod route;
10mod util;
11#[cfg(feature = "ws")]
12mod ws;
13
14#[cfg(feature = "api")]
15use args::ApiArgs;
16use args::Args;
17
18use proc_macro::TokenStream;
19use quote::quote;
20use syn::{parse_macro_input, ItemFn};
21
22enum Method {
23 Get,
24 Post,
25 Put,
26 Delete,
27 Head,
28}
29
30impl Method {
31 pub fn as_str(&self) -> &'static str {
32 match self {
33 Self::Get => "GET",
34 Self::Post => "POST",
35 Self::Put => "PUT",
36 Self::Delete => "DELETE",
37 Self::Head => "HEAD",
38 }
39 }
40}
41
42#[allow(dead_code)]
43enum TransformOutput {
44 No,
45 Json,
46}
47
48fn to_compile_error(error: syn::Error) -> TokenStream {
49 let compile_error = error.to_compile_error();
50 quote!(#compile_error).into()
51}
52
53macro_rules! attribute_route {
54 ($name:ident, $method:ident, No) => {
55 attribute_route!(_; $name, $method, No,);
56 };
57 ($name:ident, $method:ident, Json) => {
58 attribute_route!(_; $name, $method, Json, #[cfg(feature = "json")]);
59 };
60 (_; $name:ident, $method:ident, $output:ident, $(#[$attr:meta])*) => {
61 #[proc_macro_attribute]
62 $(#[$attr])*
63 pub fn $name(attrs: TokenStream, item: TokenStream) -> TokenStream {
64 let args = parse_macro_input!(attrs as Args);
65 let item = parse_macro_input!(item as ItemFn);
66
67 let stream = route::expand(
68 args,
69 item,
70 Method::$method,
71 TransformOutput::$output
72 );
73
74 stream
75 .map(|stream| stream.into())
76 .unwrap_or_else(to_compile_error)
77 }
78 }
79}
80
81attribute_route!(get, Get, No);
82attribute_route!(post, Post, No);
83attribute_route!(put, Put, No);
84attribute_route!(delete, Delete, No);
85attribute_route!(head, Head, No);
86
87attribute_route!(get_json, Get, Json);
88attribute_route!(post_json, Post, Json);
89attribute_route!(put_json, Put, Json);
90attribute_route!(delete_json, Delete, Json);
91attribute_route!(head_json, Head, Json);
92
93#[proc_macro_attribute]
94#[cfg(feature = "ws")]
95pub fn ws(attrs: TokenStream, item: TokenStream) -> TokenStream {
96 let args = parse_macro_input!(attrs as Args);
97 let item = parse_macro_input!(item as ItemFn);
98
99 let stream = ws::expand(args, item);
100
101 stream
102 .map(|stream| stream.into())
103 .unwrap_or_else(to_compile_error)
104}
105
106#[proc_macro_attribute]
107#[cfg(feature = "api")]
108pub fn api(attrs: TokenStream, item: TokenStream) -> TokenStream {
109 let args = parse_macro_input!(attrs as ApiArgs);
110 let item = parse_macro_input!(item as ItemFn);
111
112 let stream = api::expand(args, item);
113
114 stream
115 .map(|stream| stream.into())
116 .unwrap_or_else(to_compile_error)
117}
118
119#[proc_macro_attribute]
120#[cfg(all(feature = "api", feature = "stream"))]
121pub fn api_stream(attrs: TokenStream, item: TokenStream) -> TokenStream {
122 let args = parse_macro_input!(attrs as ApiArgs);
123 let item = parse_macro_input!(item as ItemFn);
124
125 let stream = api_stream::expand(args, item);
126
127 stream
128 .map(|stream| stream.into())
129 .unwrap_or_else(to_compile_error)
130}
131
132#[proc_macro_derive(RequestExtractor)]
134#[cfg(feature = "api")]
135pub fn derive_request_extractor(input: TokenStream) -> TokenStream {
136 let input = parse_macro_input!(input as syn::DeriveInput);
137
138 request_extractor::expand(&input).unwrap_or_else(to_compile_error)
139}
140
141#[proc_macro_derive(Resource)]
142pub fn derive_resource(input: TokenStream) -> TokenStream {
143 let input = parse_macro_input!(input as syn::DeriveInput);
144
145 resource::expand(&input).unwrap_or_else(to_compile_error)
146}