fire_http_codegen/
lib.rs

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// todo should this be renamed to request?
133#[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}