1use proc_macro::{TokenStream};
2use proc_macro2::{Ident};
3use quote::{quote};
4use std::collections::BTreeMap;
5use syn::{parse_macro_input, Token, ItemStruct};
6use syn::parse::{Parse, ParseStream};
7use syn::punctuated::Punctuated;
8
9mod types;
10
11use types::Imports;
12
13struct DependsOnAttribute {
14 pub name: Ident,
15}
16
17impl Parse for DependsOnAttribute {
18 fn parse(input: ParseStream) -> syn::Result<Self> {
19 let name: Ident = input.parse()?;
20
21 Ok(Self { name })
22 }
23}
24
25#[proc_macro_derive(LoginPacket, attributes(depends_on))]
32pub fn login_packet(input: TokenStream) -> TokenStream {
33 let ItemStruct { ident, fields, .. } = parse_macro_input!(input);
34 let Imports {
35 async_buf_read,
36 binary_converter,
37 byteorder_write,
38 cursor,
39 json_formatter,
40 result,
41 serialize,
42 stream_reader,
43 ..
44 } = Imports::get();
45
46 let field_names = fields.iter().map(|f| {
47 f.ident.clone()
48 }).collect::<Vec<Option<Ident>>>();
49
50 let mut depends_on: BTreeMap<Option<Ident>, Vec<Ident>> = BTreeMap::new();
51 for field in fields.iter() {
52 let ident = field.ident.clone();
53
54 if field.attrs.iter().any(|attr| attr.path().is_ident("depends_on")) {
55 let mut dependencies: Vec<Ident> = vec![];
56
57 field.attrs.iter().for_each(|attr| {
58 if attr.path().is_ident("depends_on") {
59 let parsed_attrs = attr.parse_args_with(
60 Punctuated::<DependsOnAttribute, Token![,]>::parse_terminated
61 ).unwrap();
62
63 for a in parsed_attrs {
64 dependencies.push(a.name);
65 }
66 }
67 });
68
69 depends_on.insert(ident, dependencies);
70 }
71 }
72
73 let initializers = fields
74 .iter()
75 .map(|f| {
76 let field_name = f.ident.clone();
77 let field_type = f.ty.clone();
78
79 if let Some(dep_fields) = depends_on.get(&field_name) {
80 quote! {
81 {
82 let mut data: Vec<u8> = vec![];
83 #(
84 #binary_converter::write_into(
85 &mut cache.#dep_fields,
86 &mut data,
87 )?;
88 )*
89 #binary_converter::read_from(&mut reader, &mut data)?
90 }
91 }
92 } else {
93 quote! {
94 {
95 let value: #field_type = #binary_converter::read_from(&mut reader, &mut vec![])?;
96 cache.#field_name = value.clone();
97 value
98 }
99 }
100 }
101 });
102
103 let mut output = quote! {
104 impl #ident {
105 pub fn from_binary(buffer: &[u8]) -> #result<(Self, String)> {
106 let mut cache = Self {
107 #(#field_names: Default::default()),*
108 };
109
110 let mut reader = #cursor::new(buffer.to_vec());
111 let mut instance = Self {
112 #(#field_names: #initializers),*
113 };
114 let details = instance.get_json_details()?;
115
116 Ok((instance, details))
117 }
118
119 pub fn to_binary_with_opcode(&mut self, opcode: u8) -> #result<Vec<u8>> {
120 let body = self._build_body()?;
121 let header = Self::_build_header(opcode)?;
122 Ok([header, body].concat())
123 }
124
125 pub fn unpack_with_opcode(&mut self, opcode: u8) -> #result<(u32, Vec<u8>, String)> {
126 Ok((opcode as u32, self.to_binary_with_opcode(opcode)?, self.get_json_details()?))
127 }
128
129 pub fn get_json_details(&mut self) -> #result<String> {
130 let mut serializer = #json_formatter::init();
131 #serialize::serialize(self, &mut serializer)?;
132 String::from_utf8(serializer.into_inner()).map_err(|e| e.into())
133 }
134
135 fn _build_body(&mut self) -> #result<Vec<u8>> {
136 let mut body = Vec::new();
137 #(
138 #binary_converter::write_into(
139 &mut self.#field_names,
140 &mut body
141 )?;
142 )*
143
144 Ok(body)
145 }
146
147 fn _build_header(opcode: u8) -> #result<Vec<u8>> {
148 let mut header: Vec<u8> = Vec::new();
149 #byteorder_write::write_u8(
150 &mut header,
151 opcode,
152 )?;
153
154 Ok(header)
155 }
156 }
157 };
158
159 let async_initializers = fields
160 .iter()
161 .map(|f| {
162 let field_name = f.ident.clone();
163 let field_type = f.ty.clone();
164
165 if let Some(dep_fields) = depends_on.get(&field_name) {
166 quote! {
167 {
168 let mut data: Vec<u8> = vec![];
169 #(
170 #binary_converter::write_into(
171 &mut cache.#dep_fields,
172 &mut data,
173 )?;
174 )*
175 #stream_reader::read_from(&mut stream, &mut data).await?
176 }
177 }
178 } else {
179 quote! {
180 {
181 let value: #field_type = #stream_reader::read_from(&mut stream, &mut vec![]).await?;
182 cache.#field_name = value.clone();
183 value
184 }
185 }
186 }
187 });
188
189 output = quote! {
190 #output
191
192 impl #ident {
193 pub async fn from_stream<R>(mut stream: &mut R) -> #result<Vec<u8>>
194 where R: #async_buf_read + Unpin + Send
195 {
196 let mut cache = Self {
197 #(#field_names: Default::default()),*
198 };
199
200 let mut instance = Self {
201 #(#field_names: #async_initializers),*
202 };
203
204 instance._build_body()
205 }
206 }
207 };
208
209 TokenStream::from(output)
210}
211
212#[proc_macro_derive(WorldPacket, attributes(depends_on, conditional))]
222pub fn world_packet(input: TokenStream) -> TokenStream {
223 let ItemStruct { ident, fields, .. } = parse_macro_input!(input);
224 let Imports {
225 binary_converter,
226 byteorder_be,
227 byteorder_le,
228 byteorder_write,
229 cursor,
230 json_formatter,
231 result,
232 serialize,
233 utils,
234 ..
235 } = Imports::get();
236
237 let field_names = fields.iter().map(|f| {
238 f.ident.clone()
239 }).collect::<Vec<Option<Ident>>>();
240
241 let mut depends_on: BTreeMap<Option<Ident>, Vec<Ident>> = BTreeMap::new();
242 let mut conditional: Vec<Option<Ident>> = vec![];
243 for field in fields.iter() {
244 let ident = field.ident.clone();
245
246 if field.attrs.iter().any(|attr| attr.path().is_ident("depends_on")) {
247 let mut dependencies: Vec<Ident> = vec![];
248
249 field.attrs.iter().for_each(|attr| {
250 if attr.path().is_ident("depends_on") {
251 let parsed_attrs = attr.parse_args_with(
252 Punctuated::<DependsOnAttribute, Token![,]>::parse_terminated
253 ).unwrap();
254
255 for a in parsed_attrs {
256 dependencies.push(a.name);
257 }
258 }
259 });
260
261 depends_on.insert(ident.clone(), dependencies);
262 }
263
264 if field.attrs.iter().any(|attr| attr.path().is_ident("conditional")) {
265 conditional.push(ident);
266 }
267 }
268
269 let initializers = fields
270 .iter()
271 .map(|f| {
272 let field_name = f.ident.clone();
273 let field_type = f.ty.clone();
274
275 let output = if let Some(dep_fields) = depends_on.get(&field_name) {
276 quote! {
277 {
278 let mut data: Vec<u8> = vec![];
279 #(
280 #binary_converter::write_into(
281 &mut cache.#dep_fields,
282 &mut data,
283 )?;
284 )*
285 #binary_converter::read_from(&mut reader, &mut data)?
286 }
287 }
288 } else {
289 quote! {
290 {
291 let value: #field_type = #binary_converter::read_from(
292 &mut reader, &mut vec![]
293 ).unwrap_or_default();
294
295 cache.#field_name = value.clone();
296 value
297 }
298 }
299 };
300
301 if conditional.contains(&field_name) {
302 quote! {
303 {
304 if Self::#field_name(&mut cache) {
305 #output
306 } else {
307 Default::default()
308 }
309 }
310 }
311 } else {
312 output
313 }
314 });
315
316 let writable_fields = fields.iter().map(|f| {
317 let field_name = f.ident.clone();
318
319 if conditional.contains(&field_name) {
320 quote! {
321 if Self::#field_name(self) {
322 #binary_converter::write_into(&mut self.#field_name, &mut body)?;
323 }
324 }
325 } else {
326 quote! {
327 #binary_converter::write_into(&mut self.#field_name, &mut body)?;
328 }
329 }
330 });
331
332 let output = quote! {
333 impl #ident {
334 pub fn from_binary(buffer: &[u8]) -> #result<(Self, String)> {
335 Self::build_instance(buffer)
336 }
337
338 pub fn from_compressed_binary(buffer: &[u8]) -> #result<(Self, String)> {
339 let mut buffer = #utils::deflate_decompress(&buffer[6..])?;
340 Self::build_instance(&buffer)
341 }
342
343 pub fn to_binary_with_server_opcode(
344 &mut self,
345 opcode: u16
346 ) -> #result<Vec<u8>> {
347 let body = self._build_body()?;
348 let header = Self::_build_header_for_server_packet(body.len(), opcode)?;
349 Ok([header, body].concat())
350 }
351
352 pub fn to_binary_with_client_opcode(&mut self, opcode: u32) -> #result<Vec<u8>> {
353 let body = self._build_body()?;
354 let header = Self::_build_header_for_client_packet(body.len(), opcode)?;
355 Ok([header, body].concat())
356 }
357
358 pub fn unpack_with_server_opcode(
359 &mut self,
360 opcode: u16
361 ) -> #result<(u16, Vec<u8>, String)> {
362 Ok((opcode,
363 self.to_binary_with_server_opcode(opcode)?,
364 self.get_json_details()?))
365 }
366
367 pub fn unpack_with_client_opcode(&mut self, opcode: u32) -> #result<(u32, Vec<u8>, String)> {
368 Ok((opcode, self.to_binary_with_client_opcode(opcode)?, self.get_json_details()?))
369 }
370
371 pub fn get_json_details(&mut self) -> #result<String> {
372 let mut serializer = #json_formatter::init();
373 #serialize::serialize(self, &mut serializer)?;
374 String::from_utf8(serializer.into_inner()).map_err(|e| e.into())
375 }
376
377 fn _build_body(&mut self) -> #result<Vec<u8>> {
378 let mut body = Vec::new();
379 #(#writable_fields)*
380
381 Ok(body)
382 }
383
384 fn _build_header_for_server_packet(body_len: usize, opcode: u16) -> #result<Vec<u8>> {
385 let mut header: Vec<u8> = Vec::new();
386
387 let is_large_packet = body_len > 0x7FFF;
388
389 #byteorder_write::write_u16::<#byteorder_be>(
390 &mut header,
391 (body_len as u16) + 2,
393 )?;
394
395 #byteorder_write::write_u16::<#byteorder_le>(
396 &mut header,
397 opcode,
398 )?;
399
400 if is_large_packet {
401 header.insert(0, 128);
402 }
403
404 Ok(header)
405 }
406
407 fn _build_header_for_client_packet(body_len: usize, opcode: u32) -> #result<Vec<u8>> {
408 let mut header: Vec<u8> = Vec::new();
409 #byteorder_write::write_u16::<#byteorder_be>(
410 &mut header,
411 (body_len as u16) + 4,
413 )?;
414
415 #byteorder_write::write_u32::<#byteorder_le>(
416 &mut header,
417 opcode,
418 )?;
419
420 Ok(header)
421 }
422
423 fn build_instance(buffer: &[u8]) -> #result<(Self, String)> {
424 let mut cache = Self {
425 #(#field_names: Default::default()),*
426 };
427
428 let mut reader = #cursor::new(buffer);
429 let mut instance = Self {
430 #(#field_names: #initializers),*
431 };
432
433 let details = instance.get_json_details()?;
434
435 Ok((instance, details))
436 }
437 }
438 };
439
440 TokenStream::from(output)
441}
442
443#[proc_macro_derive(Segment, attributes(depends_on, conditional))]
454pub fn segment(input: TokenStream) -> TokenStream {
455 let ItemStruct { ident, fields, .. } = parse_macro_input!(input);
456 let Imports {
457 binary_converter,
458 buf_read,
459 result,
460 ..
461 } = Imports::get();
462
463 let field_names = fields.iter().map(|f| {
464 f.ident.clone()
465 }).collect::<Vec<Option<Ident>>>();
466
467 let mut depends_on: BTreeMap<Option<Ident>, Vec<Ident>> = BTreeMap::new();
468 let mut conditional: Vec<Option<Ident>> = vec![];
469 for field in fields.iter() {
470 let ident = field.ident.clone();
471
472 if field.attrs.iter().any(|attr| attr.path().is_ident("depends_on")) {
473 let mut dependencies: Vec<Ident> = vec![];
474
475 field.attrs.iter().for_each(|attr| {
476 if attr.path().is_ident("depends_on") {
477 let parsed_attrs = attr.parse_args_with(
478 Punctuated::<DependsOnAttribute, Token![,]>::parse_terminated
479 ).unwrap();
480
481 for a in parsed_attrs {
482 dependencies.push(a.name);
483 }
484 }
485 });
486
487 depends_on.insert(ident.clone(), dependencies);
488 }
489
490 if field.attrs.iter().any(|attr| attr.path().is_ident("conditional")) {
491 conditional.push(ident);
492 }
493 }
494
495 let initializers = fields
496 .iter()
497 .map(|f| {
498 let field_name = f.ident.clone();
499 let field_type = f.ty.clone();
500
501 let output = if let Some(dep_fields) = depends_on.get(&field_name) {
502 quote! {
503 {
504 let mut data: Vec<u8> = vec![];
505 #(
506 #binary_converter::write_into(
507 &mut cache.#dep_fields,
508 &mut data,
509 )?;
510 )*
511 #binary_converter::read_from(&mut reader, &mut data)?
512 }
513 }
514 } else {
515 quote! {
516 {
517 let value: #field_type = #binary_converter::read_from(&mut reader, &mut vec![])?;
518 cache.#field_name = value.clone();
519 value
520 }
521 }
522 };
523
524 if conditional.contains(&field_name) {
525 quote! {
526 {
527 if Self::#field_name(&mut cache) {
528 #output
529 } else {
530 Default::default()
531 }
532 }
533 }
534 } else {
535 output
536 }
537 });
538
539 let writable_fields = fields.iter().map(|f| {
540 let field_name = f.ident.clone();
541
542 if conditional.contains(&field_name) {
543 quote! {
544 if Self::#field_name(self) {
545 #binary_converter::write_into(&mut self.#field_name, &mut body)?;
546 }
547 }
548 } else {
549 quote! {
550 #binary_converter::write_into(&mut self.#field_name, &mut body)?;
551 }
552 }
553 });
554
555 let output = quote! {
556 impl #ident {
557 pub fn read_from<R: #buf_read>(mut reader: &mut R) -> #result<Self> {
558 let mut cache = Self {
559 #(#field_names: Default::default()),*
560 };
561
562 let mut instance = Self {
563 #(#field_names: #initializers),*
564 };
565
566 Ok(instance)
567 }
568
569 pub fn to_binary(&mut self) -> #result<Vec<u8>> {
570 let mut body = Vec::new();
571 #(#writable_fields)*
572
573 Ok(body)
574 }
575 }
576
577 impl #binary_converter for #ident {
578 fn write_into(&mut self, buffer: &mut Vec<u8>) -> #result<()> {
579 buffer.extend(self.to_binary()?);
580 Ok(())
581 }
582
583 fn read_from<R: #buf_read>(reader: &mut R, _: &mut Vec<u8>) -> #result<Self> {
584 Self::read_from(reader)
585 }
586 }
587 };
588
589 TokenStream::from(output)
590}