1mod app;
6mod handler;
7mod json;
8mod macros;
9mod request;
10mod response;
11mod runtime;
12mod types;
13
14use macros::fibers;
15use runtime::paths;
16
17#[proc_macro_derive(Message, attributes(prost))]
19pub fn message(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
20 let input = syn::parse_macro_input!(input as syn::DeriveInput);
21 use macros::message::Message;
22 match Message::new(input).and_then(Message::expand) {
23 Ok(tokens) => tokens.into(),
24 Err(error) => error.into_compile_error().into(),
25 }
26}
27
28#[proc_macro]
30pub fn header_name(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
31 let value = syn::parse_macro_input!(input as syn::LitStr);
32 emit(
33 |paths| Ok(response::name(paths, &value)),
34 runtime::Requirement::Http,
35 )
36}
37
38fn emit(
39 build: impl FnOnce(&paths::Paths) -> syn::Result<proc_macro2::TokenStream>,
40 need: runtime::Requirement,
41) -> proc_macro::TokenStream {
42 let result = paths::Paths::resolve(need)
43 .and_then(|paths| build(&paths).and_then(|tokens| paths.finish(tokens)));
44 match result {
45 Ok(tokens) => tokens.into(),
46 Err(error) => error.into_compile_error().into(),
47 }
48}
49
50#[proc_macro]
52pub fn fiber(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
53 let input = syn::parse_macro_input!(input as fibers::Body);
54 emit(|paths| Ok(input.expand(paths)), runtime::Requirement::Fiber)
55}
56
57#[proc_macro]
62pub fn define_route(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
63 use self::app::App;
64 let input = syn::parse_macro_input!(input as app::inputs::Input);
65 emit(
66 |paths| {
67 paths.h1.require()?;
68 App::new(paths, input).map(|app| app.expand(paths, runtime::H1::Available))
69 },
70 runtime::Requirement::Fiber,
71 )
72}
73
74#[proc_macro]
77pub fn define_task_route(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
78 use self::app::App;
79 let input = syn::parse_macro_input!(input as app::inputs::Input);
80 emit(
81 |paths| App::new(paths, input).map(|app| app.expand(paths, runtime::H1::Missing)),
82 runtime::Requirement::Fiber,
83 )
84}
85
86#[proc_macro]
90pub fn define_router(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
91 use self::app::App;
92 let input = syn::parse_macro_input!(input as app::inputs::Input);
93 emit(
94 |paths| App::new_router(paths, input).map(|app| app.router(paths, paths.h1())),
95 runtime::Requirement::Portable,
96 )
97}
98
99#[proc_macro_attribute]
103pub fn handler(
104 attr: proc_macro::TokenStream,
105 item: proc_macro::TokenStream,
106) -> proc_macro::TokenStream {
107 use self::handler::{Entry, Handler, args};
108 let args = syn::parse_macro_input!(attr as args::Args);
109 let fun = syn::parse_macro_input!(item as syn::ItemFn);
110 let need = if fun.sig.asyncness.is_some() {
111 runtime::Requirement::Fiber
112 } else {
113 runtime::Requirement::Portable
114 };
115 emit(
116 |paths| {
117 Handler::new(args, fun, Entry::Handler)
118 .and_then(|handler| handler.expand(paths, paths.h1()))
119 },
120 need,
121 )
122}
123
124#[proc_macro_attribute]
128pub fn duplex(
129 attr: proc_macro::TokenStream,
130 item: proc_macro::TokenStream,
131) -> proc_macro::TokenStream {
132 use syn::{Error, Item};
133
134 use self::handler::{Entry, Handler};
135
136 let args = syn::parse_macro_input!(attr as handler::args::Args);
137 let item = syn::parse_macro_input!(item as Item);
138 emit(
139 |paths| match item {
140 Item::Fn(fun) => Handler::new(args, fun, Entry::Duplex)
141 .and_then(|handler| handler.expand(paths, paths.h1())),
142 other => Err(Error::new_spanned(
143 other,
144 "#[sark_gen::duplex] supports only fn",
145 )),
146 },
147 runtime::Requirement::Fiber,
148 )
149}
150
151#[proc_macro_attribute]
155pub fn json(
156 attr: proc_macro::TokenStream,
157 item: proc_macro::TokenStream,
158) -> proc_macro::TokenStream {
159 let st = syn::parse_macro_input!(item as syn::ItemStruct);
160 let mode = syn::parse_macro_input!(attr as json::mode::Mode);
161 emit(
162 |paths| json::build(paths, mode, st),
163 runtime::Requirement::Json,
164 )
165}
166
167#[proc_macro_attribute]
171pub fn request(
172 attr: proc_macro::TokenStream,
173 item: proc_macro::TokenStream,
174) -> proc_macro::TokenStream {
175 let mode = syn::parse_macro_input!(attr as request::mode::Mode);
176 let st = syn::parse_macro_input!(item as syn::ItemStruct);
177 emit(
178 |paths| {
179 if st
180 .attrs
181 .iter()
182 .any(|attr| attr.path().is_ident("json_body"))
183 {
184 paths.json.require()?;
185 }
186 request::build(paths, mode, st)
187 },
188 runtime::Requirement::Portable,
189 )
190}
191
192#[proc_macro_attribute]
193pub fn response(
194 attr: proc_macro::TokenStream,
195 item: proc_macro::TokenStream,
196) -> proc_macro::TokenStream {
197 use self::response::code;
198 let mode = syn::parse_macro_input!(attr as response::Mode);
199 let st = syn::parse_macro_input!(item as syn::ItemStruct);
200 emit(
201 |paths| {
202 if matches!(mode, response::Mode::Json) {
203 paths.json.require()?;
204 }
205 code::build(paths, mode, st)
206 },
207 runtime::Requirement::Portable,
208 )
209}