1use syn::parse_quote;
2use utils::traitor::{Traitor, TraitorField};
3
4mod api;
5mod command;
6mod entity;
7mod enum_code;
8mod enum_int;
9mod legacy;
10mod model;
11mod perms;
12mod routes;
13mod schema;
14mod utils;
15
16use proc_macro::TokenStream;
17
18#[proc_macro_derive(Command)]
29pub fn command(code: TokenStream) -> TokenStream {
30 command::command(code)
31}
32
33#[proc_macro_derive(EnumCode, attributes(enum_code))]
45pub fn enum_code(code: TokenStream) -> TokenStream {
46 enum_code::enum_code(code)
47}
48
49#[proc_macro_attribute]
98pub fn legacy(_args: TokenStream, code: TokenStream) -> TokenStream {
99 let item = syn::parse_macro_input!(code as syn::ItemMod);
100 legacy::legacy(item).unwrap_or_else(syn::Error::into_compile_error).into()
101}
102
103#[proc_macro_attribute]
118pub fn enum_int(args: TokenStream, code: TokenStream) -> TokenStream {
119 let item = syn::parse_macro_input!(code as syn::ItemEnum);
120 enum_int::enum_int(item, args)
121 .unwrap_or_else(syn::Error::into_compile_error)
122 .into()
123}
124
125#[proc_macro_attribute]
126pub fn api(args: TokenStream, code: TokenStream) -> TokenStream {
127 type Args = syn::punctuated::Punctuated<syn::MetaNameValue, syn::Token![,]>;
128 let item = syn::parse_macro_input!(code as syn::ItemMod);
129 let attrs = syn::parse_macro_input!(args with Args::parse_terminated);
130
131 api::api(attrs, item).unwrap_or_else(syn::Error::into_compile_error).into()
132}
133
134#[proc_macro_attribute]
135pub fn model(_args: TokenStream, code: TokenStream) -> TokenStream {
136 let item = syn::parse_macro_input!(code as syn::ItemStruct);
137 model::model(item).unwrap_or_else(syn::Error::into_compile_error).into()
138}
139
140#[proc_macro_derive(Entity, attributes(entity))]
141pub fn entity(code: TokenStream) -> TokenStream {
146 entity::entity(code)
147}
148
149#[proc_macro_derive(Belt, attributes(belt))]
150pub fn belt(code: TokenStream) -> TokenStream {
154 let ci = crate_ident();
155 let inp = syn::parse_macro_input!(code as syn::DeriveInput);
156
157 let gene = parse_quote!(#ci::models::Gene);
158
159 let tr = Traitor::new(
160 "belt",
161 parse_quote!(#ci::db::belt::Belt),
162 [
163 TraitorField::new("next", &gene, false),
164 TraitorField::new("past", &gene, false),
165 TraitorField::new("buckle", &gene, false),
166 ],
167 );
168 tr.derive(inp).unwrap_or_else(syn::Error::into_compile_error).into()
169}
170
171#[proc_macro_derive(Buckle, attributes(buckle))]
172pub fn buckle(code: TokenStream) -> TokenStream {
173 let ci = crate_ident();
174 let inp = syn::parse_macro_input!(code as syn::DeriveInput);
175
176 let gene = parse_quote!(#ci::models::Gene);
177 let pu64 = parse_quote!(u64);
178
179 let tr = Traitor::new(
180 "buckle",
181 parse_quote!(#ci::db::belt::Buckle),
182 [
183 TraitorField::new("head", &gene, false),
184 TraitorField::new("tail", &gene, false),
185 TraitorField::new("belt_count", &pu64, true),
186 ],
187 );
188 tr.derive(inp).unwrap_or_else(syn::Error::into_compile_error).into()
189}
190
191#[proc_macro_derive(Duck, attributes(duck))]
192pub fn duck(code: TokenStream) -> TokenStream {
193 let ci = crate_ident();
194 let inp = syn::parse_macro_input!(code as syn::DeriveInput);
195 let gene = parse_quote!(#ci::models::Gene);
196 let tr = Traitor::new(
197 "duck",
198 parse_quote!(#ci::db::pond::Duck),
199 [TraitorField::new("pond", &gene, false)],
200 );
201 tr.derive(inp).unwrap_or_else(syn::Error::into_compile_error).into()
202}
203
204#[proc_macro_derive(Pond, attributes(pond))]
205pub fn pond(code: TokenStream) -> TokenStream {
206 let ci = crate_ident();
207 let inp = syn::parse_macro_input!(code as syn::DeriveInput);
208
209 let gene = parse_quote!(#ci::models::Gene);
210 let pru8 = parse_quote!(u8);
211 let gene_id = parse_quote!(#ci::models::GeneId);
212
213 let tr = Traitor::new(
214 "pond",
215 parse_quote!(#ci::db::pond::Pond),
216 [
217 TraitorField::new("next", &gene, false),
218 TraitorField::new("past", &gene, false),
219 TraitorField::new("origin", &gene, false),
220 TraitorField::new("stack", &gene_id, true),
221 TraitorField::new("alive", &pru8, true),
222 TraitorField::new("empty", &pru8, true),
223 ],
224 );
225 tr.derive(inp).unwrap_or_else(syn::Error::into_compile_error).into()
226}
227
228#[proc_macro_derive(Origin, attributes(origin))]
229pub fn origin(code: TokenStream) -> TokenStream {
230 let ci = crate_ident();
231 let inp = syn::parse_macro_input!(code as syn::DeriveInput);
232
233 let gene = parse_quote!(#ci::models::Gene);
234 let pu64 = parse_quote!(u64);
235
236 let tr = Traitor::new(
237 "origin",
238 parse_quote!(#ci::db::pond::Origin),
239 [
240 TraitorField::new("head", &gene, false),
241 TraitorField::new("tail", &gene, false),
242 TraitorField::new("pond_count", &pu64, true),
243 TraitorField::new("item_count", &pu64, true),
244 ],
245 );
246 tr.derive(inp).unwrap_or_else(syn::Error::into_compile_error).into()
247}
248
249#[proc_macro_derive(ShahSchema)]
250pub fn schema(code: TokenStream) -> TokenStream {
251 schema::schema(code)
252}
253
254#[proc_macro]
255pub fn routes(code: TokenStream) -> TokenStream {
256 routes::routes(code)
257}
258
259#[proc_macro]
260pub fn perms(code: TokenStream) -> TokenStream {
261 perms::perms(code)
262}
263
264fn crate_ident() -> syn::Ident {
265 ident!("shah")
271}
272
273macro_rules! ident {
274 ($name:literal) => {
275 syn::Ident::new($name, proc_macro2::Span::call_site())
276 };
277 ($name:expr) => {
278 syn::Ident::new($name, proc_macro2::Span::call_site())
279 };
280}
281pub(crate) use ident;
282
283macro_rules! err {
284 ($span:expr, $($msg:literal),*) => {
285 Err(syn::Error::new($span, concat!( $($msg),* )))
286 };
287 ($span:expr, $msg:expr) => {
288 Err(syn::Error::new($span, $msg))
289 };
290}
291
292pub(crate) use err;