Skip to content

Commit 746d32a

Browse files
committed
entity appearance trait and entity metadata rework
1 parent aa96859 commit 746d32a

File tree

27 files changed

+944
-687
lines changed

27 files changed

+944
-687
lines changed

crates/macros/src/derive_deref.rs

Lines changed: 0 additions & 79 deletions
This file was deleted.
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
use proc_macro::TokenStream;
2+
use proc_macro2::{Ident, TokenStream as TokenStream2};
3+
use quote::{format_ident, quote, ToTokens};
4+
use syn::parse::{Parse, ParseStream};
5+
use syn::punctuated::Punctuated;
6+
use syn::{parse_macro_input, Attribute, Expr, Token, Type, Visibility};
7+
8+
struct MetadataField {
9+
metadata_id: usize,
10+
visibility: Visibility,
11+
ident: Ident,
12+
ty: Type,
13+
default_expr: Option<Expr>,
14+
}
15+
16+
impl Parse for MetadataField {
17+
fn parse(input: ParseStream) -> syn::Result<Self> {
18+
19+
let id_lit: syn::LitInt = input.parse()?;
20+
let metadata_id = id_lit.base10_parse::<usize>()?;
21+
22+
let _: Token![=>] = input.parse()?;
23+
24+
let visibility: Visibility = input.parse()?;
25+
26+
let ident: Ident = input.parse()?;
27+
let _: Token![:] = input.parse()?;
28+
let ty: Type = input.parse()?;
29+
30+
let default_expr = if input.peek(Token![=]) {
31+
let _: Token![=] = input.parse()?;
32+
Some(input.parse()?)
33+
} else {
34+
None
35+
};
36+
37+
Ok(Self {
38+
visibility,
39+
metadata_id,
40+
ident,
41+
ty,
42+
default_expr,
43+
})
44+
}
45+
}
46+
47+
impl ToTokens for MetadataField {
48+
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
49+
let vis = &self.visibility;
50+
let ident = &self.ident;
51+
let ty = &self.ty;
52+
53+
tokens.extend(quote! {
54+
#vis #ident: #ty
55+
});
56+
}
57+
}
58+
59+
struct EnumVariant {
60+
pub ident: Ident,
61+
pub fields: Vec<MetadataField>,
62+
}
63+
64+
impl Parse for EnumVariant {
65+
fn parse(input: ParseStream) -> syn::Result<Self> {
66+
let ident = input.parse()?;
67+
68+
let braced;
69+
syn::braced!(braced in input);
70+
let punctuated: Punctuated<MetadataField, Token![,]> =
71+
Punctuated::parse_terminated(&braced)?;
72+
Ok(Self {
73+
ident,
74+
fields: punctuated.into_iter().collect(),
75+
})
76+
}
77+
}
78+
79+
enum MetadataInput {
80+
Struct {
81+
attrs: Vec<Attribute>,
82+
visibility: Visibility,
83+
ident: Ident,
84+
fields: Vec<MetadataField>,
85+
},
86+
Enum {
87+
attrs: Vec<Attribute>,
88+
visibility: Visibility,
89+
ident: Ident,
90+
variants: Vec<EnumVariant>,
91+
},
92+
}
93+
94+
impl Parse for MetadataInput {
95+
fn parse(input: ParseStream) -> syn::Result<Self> {
96+
let attrs: Vec<Attribute> = input.call(Attribute::parse_outer)?;
97+
let visibility: Visibility = input.parse()?;
98+
99+
if input.peek(Token![struct]) {
100+
let _: Token![struct] = input.parse()?;
101+
let ident = input.parse()?;
102+
103+
let braced;
104+
syn::braced!(braced in input);
105+
let punctuated: Punctuated<MetadataField, Token![,]> =
106+
Punctuated::parse_terminated(&braced)?;
107+
108+
Ok(Self::Struct {
109+
attrs,
110+
visibility,
111+
ident,
112+
fields: punctuated.into_iter().collect(),
113+
})
114+
} else {
115+
let _: Token![enum] = input.parse()?;
116+
let ident = input.parse()?;
117+
118+
let braced;
119+
syn::braced!(braced in input);
120+
let punctuated: Punctuated<EnumVariant, Token![,]> =
121+
Punctuated::parse_terminated(&braced)?;
122+
123+
Ok(Self::Enum {
124+
attrs,
125+
visibility,
126+
ident,
127+
variants: punctuated.into_iter().collect(),
128+
})
129+
}
130+
}
131+
}
132+
133+
pub fn entity_metadata_serializable_macro(input: TokenStream) -> TokenStream {
134+
let input = parse_macro_input!(input as MetadataInput);
135+
match input {
136+
MetadataInput::Struct { attrs, visibility, ident, fields } => {
137+
138+
let mut write_size_stream: Vec<TokenStream2> = Vec::new();
139+
let mut write_stream: TokenStream2 = TokenStream2::new();
140+
141+
// if this doesn't match length but != 0,
142+
// that means only some implement a default expr
143+
let mut default_expr_counter = 0;
144+
let mut default_stream: TokenStream2 = TokenStream2::new();
145+
146+
for field in fields.iter() {
147+
let ident = &field.ident;
148+
let ty = &field.ty;
149+
let id = field.metadata_id as u8;
150+
151+
write_size_stream.push(quote! {
152+
1 + self.#ident.write_size()
153+
});
154+
write_stream.extend(quote! {
155+
u8::write(&(<#ty as MetadataSerializable>::ID << 5 | #id & 31), buf);
156+
<#ty as PacketSerializable>::write(&self.#ident, buf);
157+
});
158+
159+
if let Some(expr) = &field.default_expr {
160+
default_expr_counter += 1;
161+
default_stream.extend(quote! { #ident: #expr, })
162+
}
163+
}
164+
165+
let default_impl = if default_expr_counter == fields.len() {
166+
quote! {
167+
impl Default for #ident {
168+
fn default() -> Self {
169+
Self {
170+
#default_stream
171+
}
172+
}
173+
}
174+
}
175+
} else if default_expr_counter != 0 {
176+
quote! {
177+
compile_error!("This implements a default value for only some values. It must be implemented for all");
178+
}
179+
} else {
180+
quote! {}
181+
};
182+
183+
quote! {
184+
#(#attrs)*
185+
#visibility struct #ident {
186+
#(#fields),*
187+
}
188+
189+
impl PacketSerializable for #ident {
190+
fn write_size(&self) -> usize {
191+
1 + #(#write_size_stream)+*
192+
}
193+
fn write(&self, buf: &mut bytes::BytesMut) {
194+
#write_stream
195+
u8::write(&127, buf);
196+
}
197+
}
198+
199+
#default_impl
200+
}
201+
}
202+
MetadataInput::Enum { attrs, visibility, ident, variants } => {
203+
204+
let mut field_stream: TokenStream2 = TokenStream2::new();
205+
let mut metadata_impls: Vec<TokenStream2> = Vec::new();
206+
207+
let mut write_size_stream: Vec<TokenStream2> = Vec::new();
208+
let mut write_stream: TokenStream2 = TokenStream2::new();
209+
210+
for variant in variants.iter() {
211+
let ident = &variant.ident;
212+
let fields = &variant.fields;
213+
let metadata_ident = format_ident!("{}{}", ident, "Metadata");
214+
215+
// if this doesn't match length but != 0,
216+
// that means only some implement a default expr
217+
let mut default_expr_counter = 0;
218+
let mut default_stream: TokenStream2 = TokenStream2::new();
219+
220+
field_stream.extend(quote! {
221+
#ident(#metadata_ident),
222+
});
223+
224+
let mut variant_write_sizes: Vec<TokenStream2> = Vec::new();
225+
let mut variant_writes: TokenStream2 = TokenStream2::new();
226+
227+
for field in fields {
228+
let ident = &field.ident;
229+
let ty = &field.ty;
230+
let id = field.metadata_id as u8;
231+
232+
variant_write_sizes.push(quote! {
233+
1 + metadata.#ident.write_size()
234+
});
235+
variant_writes.extend(quote! {
236+
u8::write(&(<#ty as MetadataSerializable>::ID << 5 | #id & 31), buf);
237+
<#ty as PacketSerializable>::write(&metadata.#ident, buf);
238+
});
239+
240+
if let Some(expr) = &field.default_expr {
241+
default_expr_counter += 1;
242+
default_stream.extend(quote! { #ident: #expr, })
243+
}
244+
}
245+
246+
write_size_stream.push(quote! {
247+
Self::#ident(metadata) => {
248+
#(#variant_write_sizes)+*
249+
}
250+
});
251+
write_stream.extend(quote! {
252+
Self::#ident(metadata) => {
253+
#variant_writes
254+
}
255+
});
256+
257+
let default_impl = if default_expr_counter == fields.len() {
258+
quote! {
259+
impl Default for #metadata_ident {
260+
fn default() -> Self {
261+
Self {
262+
#default_stream
263+
}
264+
}
265+
}
266+
}
267+
} else if default_expr_counter != 0 {
268+
quote! {
269+
compile_error!("This implements a default value for only some values. It must be implemented for all");
270+
}
271+
} else {
272+
quote! {}
273+
};
274+
275+
metadata_impls.push(quote! {
276+
#(#attrs)*
277+
#visibility struct #metadata_ident {
278+
#(#fields),*
279+
}
280+
281+
#default_impl
282+
})
283+
}
284+
285+
quote! {
286+
#(#attrs)*
287+
#visibility enum #ident {
288+
#field_stream
289+
}
290+
291+
impl PacketSerializable for #ident {
292+
fn write_size(&self) -> usize {
293+
1 + match self {
294+
#(#write_size_stream)*
295+
}
296+
}
297+
fn write(&self, buf: &mut bytes::BytesMut) {
298+
match self {
299+
#write_stream
300+
}
301+
u8::write(&127, buf);
302+
}
303+
}
304+
305+
#(#metadata_impls)*
306+
}
307+
}
308+
}.into()
309+
}

0 commit comments

Comments
 (0)