1extern crate proc_macro;
3use proc_macro::{TokenStream};
4use quote::{quote, quote_spanned};
5use syn::{parse_macro_input, spanned::Spanned, LitInt, AttrStyle};
6
7#[proc_macro_derive(Packet, attributes(id))]
8pub fn derive_packet(input: TokenStream) -> TokenStream {
9 let ast: syn::DeriveInput = parse_macro_input!(input);
10 let name = ast.ident;
11
12 let attrs = ast.attrs;
13
14 let mut id = Option::<LitInt>::None;
15
16 for i in attrs {
17 if let AttrStyle::Outer = i.style {
18 id = Some(i.parse_args().unwrap());
19 }
20 }
21
22 let id = id.unwrap();
23
24
25 let fields = if let syn::Data::Struct(syn::DataStruct {
26 fields: syn::Fields::Named(ref fields),
27 ..
28 }) = ast.data
29 {
30 fields
31 } else {
32 panic!("Only support structs")
33 };
34
35 let recurse_encoder = fields.named.iter().map(|f| {
36 let name = &f.ident;
37 quote_spanned! {f.span()=>
38 self.#name.write_to(w)?;
39 }
40 });
41 let stream_encoder = quote! {
42 #(#recurse_encoder)*
43 };
44
45 let recurse_decoder_types = fields.named.iter().map(|f| {
46 let ty = &f.ty;
47 let name = &f.ident;
48 quote_spanned! {f.span()=>
49 let #name = #ty::read_from(r)?;
50 }
51 });
52 let stream_decoder_types = quote! {
53 #(#recurse_decoder_types)*
54 };
55
56 let recurse_decoder_names = fields.named.iter().map(|f| {
57 let name = &f.ident;
58 quote_spanned! {f.span()=>
59 #name,
60 }
61 });
62 let stream_decoder_names = quote! {
63 #(#recurse_decoder_names)*
64 };
65
66 let extended = quote! {
67 use minceraft::net::types::{Encoder, Decoder};
68 impl Encoder for #name {
69 fn write_to(&self, w: &mut impl std::io::Write) -> anyhow::Result<()> {
70 #stream_encoder
71 Ok(())
72 }
73 }
74
75 impl Decoder for #name {
76 fn read_from(r: &mut impl std::io::Read) -> anyhow::Result<Self> {
77 #stream_decoder_types
78
79 Ok(Self {
80 #stream_decoder_names
81 })
82 }
83 }
84
85 use minceraft::net::types::VarInt;
86 impl Packet for #name {
87 const ID: VarInt = VarInt(#id);
88 }
89 };
90 TokenStream::from(extended)
91}