1extern crate proc_macro;
2mod types;
3
4use proc_macro2::TokenStream;
5use quote::{quote, ToTokens, TokenStreamExt};
6use syn::parse::{Parse, ParseStream};
7use syn::{braced, parse_macro_input, Attribute, Data, Lit, Meta, Token};
8use syn::{DeriveInput, Expr, LitInt, Path, PathArguments, PathSegment, Type};
9use crate::types::FieldType;
10
11struct FieldMacroInput {
12 attributes: Vec<Attribute>,
13 name: syn::Ident,
14 body: Vec<types::Field>,
15}
16impl Parse for FieldMacroInput {
17 fn parse(input: ParseStream) -> syn::Result<Self> {
18 let attributes = Attribute::parse_outer(input)?;
19 let name = input.parse::<syn::Ident>()?;
20 input.parse::<Token![,]>()?;
21 let raw_body;
22 braced!(raw_body in input);
23 let mut body = Vec::new();
24 while let Ok(f) = raw_body.parse::<types::Field>() {
25 if f.r#type.is_none() {
26 panic!("Field field type can't be None");
27 }
28 body.push(f);
29 }
30 Ok(Self { name, body, attributes })
31 }
32}
33impl ToTokens for FieldMacroInput {
34 fn to_tokens(&self, tokens: &mut TokenStream) {
35 let name = &self.name;
36 let attributes = &self.attributes;
37 if self.body.len() == 0 {
38 tokens.extend(quote! {
39 #(#attributes)*
40 #[derive(Debug, Clone)]
41 pub struct #name {}
42 impl crate::Field for #name {
43 fn to_bytes(&self) -> Vec<u8> {Vec::new()}
44 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::errors::Result<Self> {Ok(Self {})}
45 }
46 impl #name {
47 pub fn new() -> Self {Self {}}
48 }
49 });
50 return;
51 }
52 let field_names = self.body.iter().map(|f| &f.name).collect::<Vec<_>>();
53 let field_types = self.body.iter().map(|f| &f.r#type).collect::<Vec<_>>();
54 let field_attributes = self.body.iter().map(|f| &f.attributes).collect::<Vec<_>>();
55 let encoders = self.body.iter().map(|f| f.get_struct_encoder()).collect::<Vec<_>>();
56 let decoders = self.body.iter().map(|f| f.get_struct_decoder()).collect::<Vec<_>>();
57 tokens.append_all(quote! {
58 #(#attributes)*
59 #[derive(Debug, Clone)]
60 pub struct #name {
61 #(
62 #(#field_attributes)*
63 pub #field_names: #field_types,
64 )*
65 }
66 impl crate::Field for #name {
67 fn to_bytes(&self) -> Vec<u8> {
68 vec![#(#encoders,)*].iter().flatten().cloned().collect::<Vec<u8>>()
69 }
70 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::errors::Result<Self> {
71 Ok(Self {
72 #(#field_names: #decoders,)*
73 })
74 }
75 }
76 });
77 tokens.extend(quote! {
78 impl #name {
79 pub fn new(#(#field_names: #field_types,)*) -> Self {
80 Self {#(#field_names,)*}
81 }
82 }
83 })
84 }
85}
86#[proc_macro]
87#[allow(non_snake_case)]
88pub fn Field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
89 let input = parse_macro_input!(input as FieldMacroInput);
90 input.to_token_stream().into()
91}
92
93struct PacketMacroInput {
94 name: syn::Ident,
95 id: syn::LitInt,
96 attributes: Vec<Attribute>,
97 body: Vec<types::Field>,
98}
99impl Parse for PacketMacroInput {
100 fn parse(input: ParseStream) -> syn::Result<Self> {
101 let attributes = Attribute::parse_outer(input)?;
102 let name = input.parse::<syn::Ident>()?;
103 input.parse::<Token![,]>()?;
104 let id = input.parse::<syn::LitInt>()?;
105 input.parse::<Token![,]>()?;
106 let raw_body;
107 braced!(raw_body in input);
108 let mut body = Vec::new();
109 while let Ok(f) = raw_body.parse::<types::Field>() {
110 if f.r#type.is_none() {
111 panic!("Packet field type can't be None");
112 }
113 body.push(f);
114 }
115 Ok(Self { name, id, body, attributes })
116 }
117}
118impl ToTokens for PacketMacroInput {
119 fn to_tokens(&self, tokens: &mut TokenStream) {
120 let name = &self.name;
121 let id = &self.id;
122 let attributes = &self.attributes;
123 if self.body.len() == 0 {
124 tokens.extend(quote! {
125 #(#attributes)*
126 #[derive(Debug, Clone)]
127 pub struct #name {}
128 impl crate::Packet for #name {
129 const ID: i32 = #id;
130 fn to_bytes(&self) -> Vec<u8> {Vec::new()}
131 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::errors::Result<Self> {Ok(Self {})}
132 }
133 impl #name {
134 pub fn new() -> Self {Self {}}
135 }
136 });
137 return;
138 }
139 let field_names = self.body.iter().map(|f| &f.name).collect::<Vec<_>>();
140 let field_types = self.body.iter().map(|f| &f.r#type).collect::<Vec<_>>();
141 let field_attributes = self.body.iter().map(|f| &f.attributes).collect::<Vec<_>>();
142 let encoders = self.body.iter().map(|f| f.get_struct_encoder()).collect::<Vec<_>>();
143 let decoders = self.body.iter().map(|f| f.get_struct_decoder()).collect::<Vec<_>>();
144 tokens.append_all(quote! {
145 #(#attributes)*
146 #[derive(Debug, Clone)]
147 pub struct #name {
148
149 #(
150 #(#field_attributes)*
151 pub #field_names: #field_types,
152 )*
153 }
154 impl crate::Packet for #name {
155 const ID: i32 = #id;
156 fn to_bytes(&self) -> Vec<u8> {
157 vec![#(#encoders,)*].iter().flatten().cloned().collect()
158 }
159 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::errors::Result<Self> {
160 Ok(Self {
161 #(#field_names: #decoders,)*
162 })
163 }
164 }
165 });
166 tokens.extend(quote! {
167 impl #name {
168 pub fn new(#(#field_names: #field_types,)*) -> Self {
169 Self {#(#field_names,)*}
170 }
171 }
172 })
173 }
174}
175#[proc_macro]
176#[allow(non_snake_case)]
177pub fn Packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
178 let input = parse_macro_input!(input as PacketMacroInput);
179 input.to_token_stream().into()
180}
181
182
183struct EnumMacroInput {
184 name: syn::Ident,
185 attributes: Vec<Attribute>,
186 body: Vec<types::Field>,
187}
188impl Parse for EnumMacroInput {
189 fn parse(input: ParseStream) -> syn::Result<Self> {
190 let attributes = Attribute::parse_outer(input)?;
191 let name = input.parse::<syn::Ident>()?;
192 input.parse::<Token![,]>()?;
193 let raw_body;
194 braced!(raw_body in input);
195 let mut body = Vec::new();
196 while let Ok(f) = raw_body.parse::<types::Field>() {
197 body.push(f);
198 }
199 Ok(Self { name, body, attributes })
200 }
201}
202impl ToTokens for EnumMacroInput {
203 fn to_tokens(&self, tokens: &mut TokenStream) {
204 let name = &self.name;
205 let attributes = &self.attributes;
206 if self.body.len() == 0 {
207 tokens.extend(quote! {
208 #(#attributes)*
209 #[derive(Debug, Clone)]
210 pub enum #name {}
211 impl crate::Field for #name {
212 fn to_bytes(&self) -> Vec<u8> {compile_error!("can't convert empty enum to bytes")}
213 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::errors::Result<Self> {compile_error!("can't convert empty enum to bytes")}
214 }
215 impl crate::Field for #name {
216 pub fn new() -> Self {Self {}}
217 }
218 });
219 return;
220 }
221 if self.body.len() > i32::MAX as usize {
222 panic!("can't encode an enum with more options than an Integer. How did you even get here?")
223 }
224 let field_names = self.body.iter().map(|f| &f.name).collect::<Vec<_>>();
225 let field_types = self.body.iter().map(|f| match &f.r#type {
226 FieldType::None => quote! {},
227 v => quote!{(#v)},
228 }).collect::<Vec<_>>();
229 let field_attributes = self.body.iter().map(|f| &f.attributes).collect::<Vec<_>>();
230 let encoders = self.body.iter()
231 .enumerate().map(|(i, f)| match std::panic::catch_unwind(|| {
232 f.get_enum_encoder(i)}) {
233 Err(e) => {eprintln!("error while parsing {}", self.name); std::panic::resume_unwind(e)},
234 Ok(v) => v,
235 })
236 .collect::<Vec<_>>();
237 let decoders = self.body.iter()
238 .enumerate()
239 .map(|(i, f)| f.get_enum_decoder(i))
240 .collect::<Vec<_>>();
241 tokens.extend(quote! {
242 #(#attributes)*
243 #[derive(Debug, Clone)]
244 pub enum #name {
245 #(
246 #(#field_attributes)*
247 #field_names #field_types,
248 )*
249 }
250 impl crate::Field for #name {
251 fn to_bytes(&self) -> Vec<u8> {
252 match self.clone() {
253 #(#encoders,)*
254 }
255 }
256 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::errors::Result<Self> {
257 Ok(match reader.read_var_int()? {
258 #(#decoders,)*
259 v => return Err(crate::errors::Errors::InvalidEnum(format!("Integer {v} is outside of range for enum"))),
260 })
261 }
262 }
263 })
264 }
265}
266#[proc_macro]
267#[allow(non_snake_case)]
268pub fn VarIntEnum(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
269 parse_macro_input!(input as EnumMacroInput).to_token_stream().into()
270}
271
272
273#[proc_macro_derive(Packet_old, attributes(id, len, Var, Const, when))]
274pub fn derive_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
275 let ast: DeriveInput = syn::parse(input).unwrap();
277
278 let id = get_packet_id(&ast.attrs);
279 let name = &ast.ident;
280 let Data::Struct(s) = &ast.data else {
281 panic!("Can only be used for structs");
282 };
283
284 let mut field_encoders = Vec::with_capacity(s.fields.len());
285 let mut field_decoders = Vec::with_capacity(s.fields.len());
286 let mut field_names = Vec::with_capacity(s.fields.len());
287 for field in &s.fields {
288 let field_name = field.ident.clone().expect("unnamed fields");
289 let field_type = &field.ty;
290 field_names.push(field_name.clone());
291 let (encoder, decoder) = get_encoder_and_decoder_for_field(field_type, quote! {self.#field_name}, &field.attrs);
292 let decoder = quote! {let #field_name = #decoder};
293 field_encoders.push(encoder);
294 field_decoders.push(decoder);
295 };
296
297 let res = quote! {
298 impl crate::Packet for #name {
299 const ID: i32 = #id;
300 fn to_bytes(&self) -> Vec<u8> {
301 let vector: Vec<Vec<u8>> = vec![
302 #(#field_encoders),*
303 ];
304 vector.iter().flatten().cloned().collect()
305 }
306 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::Result<Self> {
307 #(#field_decoders);*;
308 Ok(Self {
309 #(#field_names),*
310 })
311 }
312 }
313 };
314 res.into()
315}
316
317#[proc_macro_derive(Field_old, attributes(len, Var, Const, when))]
318pub fn derive_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
319 let ast: DeriveInput = syn::parse(input).unwrap();
321
322 let name = &ast.ident;
323 let Data::Struct(s) = &ast.data else {
324 panic!("Can only be used for structs");
325 };
326
327 let mut field_encoders = Vec::with_capacity(s.fields.len());
328 let mut field_decoders = Vec::with_capacity(s.fields.len());
329 let mut field_names = Vec::with_capacity(s.fields.len());
330 for field in &s.fields {
331 let field_name = field.ident.clone().expect("unnamed fields");
332 let field_type = &field.ty;
333 field_names.push(field_name.clone());
334 let (encoder, decoder) = get_encoder_and_decoder_for_field(field_type, quote! {self.#field_name}, &field.attrs);
335 let decoder = quote! {let #field_name = #decoder};
336 field_encoders.push(encoder);
337 field_decoders.push(decoder);
338 };
339
340 let res = quote! {
341 impl crate::Field for #name {
342 fn to_bytes(&self) -> Vec<u8> {
343 let vector: Vec<Vec<u8>> = vec![
344 #(#field_encoders),*
345 ];
346 vector.iter().flatten().cloned().collect()
347 }
348 fn from_reader(reader: &mut crate::fields::PacketReader) -> crate::Result<Self> {
349 #(#field_decoders);*;
350 Ok(Self {
351 #(#field_names),*
352 })
353 }
354 }
355 };
356 res.into()
357}
358fn get_packet_id(attrs: &[Attribute]) -> &LitInt {
359 for attr in attrs {
360 let Meta::NameValue(name_value) = &attr.meta else {
361 continue;
362 };
363 if !name_value.path.is_ident("id") {continue}
364 let Expr::Lit(lit) = &name_value.value else {
365 panic!("id must a literal")
366 };
367 let Lit::Int(int) = &lit.lit else {
368 panic!("id must be an integer")
369 };
370 return int;
371 }
372 panic!("requires id attribute for struct");
373}
374
375fn get_encoder_and_decoder_for_field(field_type: &Type, val_ref: impl ToTokens + Clone, attrs: &[Attribute]) -> (TokenStream, TokenStream) {
376 let path = match field_type {
377 Type::Paren(type_paren) => return get_encoder_and_decoder_for_field(&type_paren.elem, val_ref, attrs),
378 Type::Path(path) => &path.path,
379 t => panic!("invalid field type: {}", t.to_token_stream().to_string()),
380 };
381 let segment = path.segments.last().unwrap();
382 let ident = &segment.ident;
383
384 match ident.to_string().as_ref() {
385 "bool" => (quote! { crate::fields::encode_bool(#val_ref) }, quote! { reader.read_bool()? }),
386 "u8" => (quote! { crate::fields::encode_ubyte(#val_ref) }, quote! { reader.read_ubyte() }),
387 "i8" => (quote! { crate::fields::encode_byte(#val_ref) }, quote! { reader.read_byte() }),
388 "u16" => (quote! { crate::fields::encode_ushort(#val_ref) }, quote! { reader.read_ushort() }),
389 "i16" => (quote! { crate::fields::encode_short(#val_ref) }, quote! { reader.read_short() }),
390 "i32" => handle_int(attrs, val_ref),
391 "i64" => handle_long(attrs, val_ref),
392 "u128" => (quote! { crate::fields::encode_uuid(#val_ref) }, quote! { reader.read_uuid() }),
393 "f32" => (quote! { crate::fields::encode_float(#val_ref) }, quote! { reader.read_float() }),
394 "f64" => (quote! { crate::fields::encode_double(#val_ref) }, quote! { reader.read_double() }),
395 "String" => (quote! { crate::fields::encode_string(#val_ref .clone()) }, quote! { reader.read_string()? }),
396
397 "Byte" => (quote! { crate::fields::encode_byte(#val_ref) }, quote! { reader.read_byte() }),
398 "UByte" => (quote! { crate::fields::encode_ubyte(#val_ref) }, quote! { reader.read_ubyte() }),
399 "Short" => (quote! { crate::fields::encode_short(#val_ref) }, quote! { reader.read_short() }),
400 "UShort" => (quote! { crate::fields::encode_ushort(#val_ref) }, quote! { reader.read_ushort() }),
401 "Int" => (quote! { crate::fields::encode_int(#val_ref) }, quote! { reader.read_int() }),
402 "UInt" => (quote! { crate::fields::encode_uint(#val_ref) }, quote! { reader.read_uint() }),
403 "Long" => (quote! { crate::fields::encode_long(#val_ref) }, quote! { reader.read_long() }),
404 "UUID" => (quote! { crate::fields::encode_uuid(#val_ref) }, quote! { reader.read_uuid() }),
405 "Float" => (quote! { crate::fields::encode_float(#val_ref) }, quote! { reader.read_float() }),
406 "Double" => (quote! { crate::fields::encode_double(#val_ref) }, quote! { reader.read_double() }),
407
408 "Identifier" => (quote! { crate::fields::encode_identifier(#val_ref .clone()) }, quote! { reader.read_identifier()? }),
409 "Angle" => (quote! { crate::fields::encode_angle(#val_ref) }, quote! { reader.read_angle() }),
410 "VarInt" => (quote! { crate::fields::encode_var_int(#val_ref) }, quote! { reader.read_var_int()? }),
411 "VarLong" => (quote! { crate::fields::encode_var_long(#val_ref) }, quote! { reader.read_var_long()? }),
412 "PrefixedArray" => handle_prefixed_array(segment, val_ref, attrs),
413 "PrefixedOptional" => handle_prefixed_option(segment, val_ref, attrs),
414
415 _ => if ident == "Vec" {
416 handle_vec(segment, val_ref, attrs)
417 } else if ident == "Option" {
418 handle_option(segment, val_ref, attrs)
419 } else {
420 handle_generic(val_ref, path)
421 },
422 }
423}
424fn handle_prefixed_array(segment: &PathSegment, name: impl ToTokens + Clone, attrs: &[Attribute]) -> (TokenStream, TokenStream) {
425 let PathArguments::AngleBracketed(args) = &segment.arguments else {
426 panic!("Invalid vector inner type")
427 };
428 let Some(syn::GenericArgument::Type(inner_type)) = args.args.first() else {
429 panic!("Invalid vector inner type")
430 };
431 let (inner_encoder, inner_decoder) = get_encoder_and_decoder_for_field(&inner_type, quote! {v.clone()}, attrs);
432 (quote! {
433 vec![crate::fields::encode_var_int(#name.len() as i32), #name.iter().cloned().flat_map(|v| #inner_encoder).collect()].iter().cloned().flatten().collect()
434 }, quote! {
435 {
436 let len = reader.read_var_int()?;
437 let mut v = Vec::with_capacity(len as usize);
438 for _ in 0..len {
439 v.push(#inner_decoder);
440 }
441 v
442 }
443 })
444}
445
446fn handle_prefixed_option(segment: &PathSegment, name: impl ToTokens + Clone, attrs: &[Attribute]) -> (TokenStream, TokenStream) {
447 let PathArguments::AngleBracketed(args) = &segment.arguments else {
448 panic!("Invalid vector inner type")
449 };
450 let Some(syn::GenericArgument::Type(inner_type)) = args.args.first() else {
451 panic!("Invalid vector inner type")
452 };
453 let (inner_encoder, inner_decoder) = get_encoder_and_decoder_for_field(&inner_type, quote! {v.clone()}, attrs);
454 (quote! {
455 if let Some(v) = &#name {vec![crate::fields::encode_bool(true), #inner_encoder].iter().cloned().flatten().collect()} else {crate::fields::encode_bool(false)}
456 }, quote! {
457 if reader.read_bool()? {Some(#inner_decoder)} else {None}
458 })
459}
460fn is_var(attrs: &[Attribute]) -> bool {
461 for attr in attrs {
462 let Meta::Path(path) = &attr.meta else {continue};
463 if path.is_ident("Var") {
464 return true;
465 }
466 }
467 false
468}
469fn is_const(attrs: &[Attribute]) -> bool {
470 for attr in attrs {
471 let Meta::Path(path) = &attr.meta else {continue};
472 if path.is_ident("Const") {
473 return true;
474 }
475 }
476 false
477}
478fn handle_int(attrs: &[Attribute], name: impl ToTokens) -> (TokenStream, TokenStream) {
479 if is_var(attrs) {
480 (quote! {
481 crate::fields::encode_var_int(#name)
482 }, quote! {
483 reader.read_var_int()?
484 })
485 } else {
486 #[cfg(debug_assertions)]
487 if !is_const(attrs) {
488 eprintln!("warning: unspecified Integer used for field {} guessing regular integer", name.to_token_stream());
489 }
490 (quote! {
491 crate::fields::encode_int(#name)
492 }, quote! {
493 reader.read_int()
494 })
495 }
496}
497fn handle_long(attrs: &[Attribute], name: impl ToTokens) -> (TokenStream, TokenStream) {
498 if is_var(attrs) {
499 (quote! {
500 crate::fields::encode_var_long(#name)
501 }, quote! {
502 reader.read_var_long()?
503 })
504 } else {
505 #[cfg(debug_assertions)]
506 if !is_const(attrs) {
507 eprintln!("warning: unspecified Long used for field {} guessing fixed size", name.to_token_stream());
508 }
509 (quote! {
510 crate::fields::encode_long(#name)
511 }, quote! {
512 reader.read_long()
513 })
514 }
515}
516fn handle_vec(segment: &PathSegment, name: impl ToTokens + Clone, attrs: &[Attribute]) -> (TokenStream, TokenStream) {
517 let PathArguments::AngleBracketed(args) = &segment.arguments else {
518 panic!("Invalid vector inner type")
519 };
520 let Some(syn::GenericArgument::Type(inner_type)) = args.args.first() else {
521 panic!("Invalid vector inner type")
522 };
523 let len_resp_field = get_length_responsible_attr(attrs);
524 let (inner_encoder, inner_decoder) = get_encoder_and_decoder_for_field(&inner_type, quote! {v.clone()}, attrs);
525 (quote! {
526 #name.iter().flat_map(|v| #inner_encoder).collect()
527 }, quote! {
528 {
529 let mut v = Vec::with_capacity(#len_resp_field as usize);
530 for _ in 0..#len_resp_field {
531 v.push(#inner_decoder);
532 }
533 v
534 }
535 })
536}
537fn get_length_responsible_attr(attrs: &[Attribute]) -> Path {
538 for attr in attrs {
539 let Meta::NameValue(meta) = &attr.meta else {
540 continue;
541 };
542 if !meta.path.is_ident("len") {continue}
543 let Expr::Lit(expr) = &meta.value else {
544 panic!("len must be literal expression")
545 };
546 let Lit::Str(path_str) = &expr.lit else {
547 panic!("len must be a string literal")
548 };
549 return syn::parse_str::<Path>(&*path_str.value()).expect("Invalid path");
550 }
551 panic!("requires a \"len\" attribute");
552}
553fn handle_option(segment: &PathSegment, name: impl ToTokens + Clone, attrs: &[Attribute]) -> (TokenStream, TokenStream) {
554 let PathArguments::AngleBracketed(args) = &segment.arguments else {
555 panic!("Invalid option inner type")
556 };
557 let Some(syn::GenericArgument::Type(inner_type)) = args.args.first() else {
558 panic!("Invalid option inner type")
559 };
560 let dependency = get_dependency(attrs);
561
562 let (inner_encoder, inner_decoder) = get_encoder_and_decoder_for_field(&inner_type, quote! {v}, attrs);
563 (quote! {
564 if self.#dependency {
565 let v = #name.clone().unwrap();
566 #inner_encoder
567 } else {vec![]}
568 }, quote! {
569 if #dependency {core::option::Option::Some(#inner_decoder)} else {core::option::Option::None}
570 })
571}
572fn get_dependency(attrs: &[Attribute]) -> Path {
573 for attr in attrs {
574 let Meta::NameValue(meta) = &attr.meta else {
575 continue;
576 };
577 if !meta.path.is_ident("when") {continue}
578 let Expr::Lit(expr) = &meta.value else {
579 panic!("when must be literal expression")
580 };
581 let Lit::Str(path_str) = &expr.lit else {
582 panic!("when must be a string literal")
583 };
584 return syn::parse_str::<Path>(&*path_str.value()).expect("Invalid path");
585 }
586 panic!("requires a \"len\" attribute");
587}
588
589fn handle_generic(name: impl ToTokens, path: &Path) -> (TokenStream, TokenStream) {
590 (quote! {crate::Field::to_bytes(&#name)}, quote! {{use crate::Field; #path::from_reader(reader)?}})
591}