1extern crate proc_macro;
2
3use quote::{format_ident, quote};
4use syn::{
5 Attribute, Data, DeriveInput, Fields, Lit, PathArguments, Type, parse_macro_input,
6 punctuated::Punctuated, token::Comma,
7};
8
9#[proc_macro_derive(
10 ToBytes,
11 attributes(
12 bits,
13 dyn_int,
14 dyn_length,
15 key_dyn_length,
16 val_dyn_length,
17 toggles,
18 toggled_by,
19 length_for,
20 length_by,
21 variant_for,
22 variant_by,
23 multi_enum,
24 no_discriminator,
25 )
26)]
27pub fn generate_code_to_bytes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
28 generate_code_binary_serializer(false, input)
29}
30
31#[proc_macro_derive(
32 FromBytes,
33 attributes(
34 bits,
35 dyn_int,
36 key_dyn_length,
37 val_dyn_length,
38 dyn_length,
39 toggles,
40 toggled_by,
41 length_for,
42 length_by,
43 variant_for,
44 variant_by,
45 multi_enum,
46 no_discriminator
47 )
48)]
49pub fn generate_code_from_bytes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
50 generate_code_binary_serializer(true, input)
51}
52
53fn generate_code_binary_serializer(
54 read: bool,
55 input: proc_macro::TokenStream,
56) -> proc_macro::TokenStream {
57 let ast = parse_macro_input!(input as DeriveInput);
59
60 match ast.data {
61 Data::Struct(ref data) => generate_struct_serializer(read, &ast, data),
62 Data::Enum(ref data) => generate_enum_serializer(read, &ast, data),
63 _ => panic!("ToBytes can only be used on structs"),
64 }
65}
66
67fn generate_field_serializer(
68 read: bool,
69 field_ident: &proc_macro2::Ident,
70 field_type: &syn::Type,
71 field: &syn::Field,
72 is_enum: bool,
73) -> proc_macro2::TokenStream {
74 let single_ident_type_name = if let Type::Path(path) = field_type {
75 if path.path.segments.len() == 1 {
76 Some(path.path.segments[0].ident.to_string())
77 } else {
78 None
79 }
80 } else {
81 None
82 };
83
84 let mut toggle_key = None;
85 let mut variant_key = None;
86 let mut length_key = None;
87 let mut toggled_by = None;
88 let mut variant_by = None;
89 let mut length_by = None;
90 let mut is_dynamic_int = false;
91 let mut has_dynamic_length = false;
92 let mut bits_count = None;
93 let mut key_dyn_length = false;
94 let mut val_dyn_length = false;
95 let mut multi_enum = false;
96
97 for attr in field.attrs.iter() {
99 let ident = attr.path().get_ident().map(|i| i.clone().to_string());
100 match ident.as_deref() {
101 Some("dyn_int") => is_dynamic_int = true,
102 Some("dyn_length") => has_dynamic_length = true,
103 Some("key_dyn_length") => key_dyn_length = true,
104 Some("val_dyn_length") => val_dyn_length = true,
105 Some("multi_enum") => multi_enum = true,
106 Some("toggles") => toggle_key = get_string_value_from_attribute(attr),
107 Some("variant_for") => variant_key = get_string_value_from_attribute(attr),
108 Some("length_for") => length_key = get_string_value_from_attribute(attr),
109 Some("toggled_by") => toggled_by = get_string_value_from_attribute(attr),
110 Some("variant_by") => variant_by = get_string_value_from_attribute(attr),
111 Some("length_by") => length_by = get_string_value_from_attribute(attr),
112 Some("bits") => bits_count = get_int_value_from_attribute(attr).map(|b| b as u8),
113 _ => {} }
115 }
116
117 let val_reference = if matches!(single_ident_type_name, Some(s) if s == String::from("RefCell"))
118 {
119 if read {
120 quote! {
121 *#field_ident.borrow()
122 }
123 } else {
124 quote! {
125 *_p_val.borrow()
126 }
127 }
128 } else {
129 if read {
130 quote! {
131 _p_val
132 }
133 } else {
134 quote! {
135 *_p_val
136 }
137 }
138 };
139
140 let toggles = if let Some(key) = toggle_key {
142 quote! {
143 _p_config.set_toggle(#key, #val_reference);
144 }
145 } else {
146 quote! {}
147 };
148
149 let length = if let Some(key) = length_key {
151 quote! {
152 _p_config.set_length(#key, #val_reference as usize);
153 }
154 } else {
155 quote! {}
156 };
157
158 let variant = if let Some(key) = variant_key {
160 quote! {
161 _p_config.set_variant(#key, #val_reference as u8);
162 }
163 } else {
164 quote! {}
165 };
166
167 let f_ident = if is_enum {
169 quote! { #field_ident }
170 } else {
171 quote! { &self.#field_ident }
172 };
173
174 let before = if read {
175 quote! {}
176 } else {
177 quote! {
178 let _p_val = #f_ident;
179 #toggles
180 #length
181 #variant
182 }
183 };
184
185 let after = if read {
186 quote! {
187 let #field_ident = _p_val;
188 #toggles
189 #length
190 #variant
191 }
192 } else {
193 quote! {}
194 };
195
196 let handle_field = generate_code_for_handling_field(
197 read,
198 field_type,
199 field_ident,
200 bits_count,
201 toggled_by,
202 variant_by,
203 length_by,
204 is_dynamic_int,
205 has_dynamic_length,
206 key_dyn_length,
207 val_dyn_length,
208 multi_enum,
209 false,
210 0,
211 );
212
213 quote! {
214 #before
215 #handle_field
216 #after
217 }
218}
219
220fn generate_struct_serializer(
221 read: bool,
222 ast: &DeriveInput,
223 data_struct: &syn::DataStruct,
224) -> proc_macro::TokenStream {
225 let fields = &data_struct.fields;
226 let struct_name = &ast.ident;
227
228 let field_serializations = fields.iter().map(|field| {
230 generate_field_serializer(
231 read,
232 &field
233 .ident
234 .as_ref()
235 .expect("binary-codec does not support fields without a name"),
236 &field.ty,
237 field,
238 false,
239 )
240 });
241
242 let error_type = generate_error_type(read);
243 let serializer_code = if read {
244 let vars = fields.iter().map(|f| f.ident.as_ref().unwrap());
245
246 quote! {
248 impl<T : Clone> binary_codec::BinaryDeserializer<T> for #struct_name {
249 fn read_bytes(
250 stream: &mut binary_codec::BitStreamReader,
251 config: Option<&mut binary_codec::SerializerConfig<T>>,
252 ) -> Result<Self, #error_type> {
253 let mut _new_config = binary_codec::SerializerConfig::new(None);
254 let _p_config = config.unwrap_or(&mut _new_config);
255 let _p_stream = stream;
256
257 #(#field_serializations)*
258
259 Ok(Self {
260 #(#vars),*
261 })
262 }
263 }
264 }
265 } else {
266 quote! {
268 impl<T : Clone> binary_codec::BinarySerializer<T> for #struct_name {
269 fn write_bytes(
270 &self,
271 stream: &mut binary_codec::BitStreamWriter,
272 config: Option<&mut binary_codec::SerializerConfig<T>>,
273 ) -> Result<(), #error_type> {
274 let mut _new_config = binary_codec::SerializerConfig::new(None);
275 let _p_config = config.unwrap_or(&mut _new_config);
276 let _p_stream = stream;
277
278 #(#field_serializations)*
279 Ok(())
280 }
281 }
282 }
283 };
284
285 serializer_code.into()
286}
287
288fn generate_enum_serializer(
289 read: bool,
290 ast: &DeriveInput,
291 data_enum: &syn::DataEnum,
292) -> proc_macro::TokenStream {
293 let enum_name = &ast.ident;
294 let error_type = generate_error_type(read);
295
296 let mut no_disc_prefix = false;
297
298 for attr in ast.attrs.iter() {
300 if attr.path().is_ident("no_discriminator") {
302 no_disc_prefix = true;
303 }
304 }
305
306 let mut configure_functions = Vec::new();
307
308 let disc_variants = data_enum
310 .variants
311 .iter()
312 .enumerate()
313 .map(|(i, variant)| {
314 let var_ident = &variant.ident;
315 let disc_value = i as u8;
316
317 for attr in variant.attrs.iter() {
318 if attr.path().is_ident("toggled_by") {
319 let field = get_string_value_from_attribute(attr)
320 .expect("toggled_by for multi_enum should have a value");
321 configure_functions.push(quote! {
322 _p_config.configure_multi_disc(stringify!(#enum_name), #disc_value, #field);
323 });
324 }
325 }
326
327 match &variant.fields {
328 Fields::Unit => quote! {
329 Self::#var_ident => #disc_value
330 },
331 Fields::Unnamed(_) => quote! {
332 Self::#var_ident(..) => #disc_value
333 },
334 Fields::Named(_) => quote! {
335 Self::#var_ident { .. } => #disc_value
336 },
337 }
338 })
339 .collect::<Vec<_>>();
340
341 let serialization_variants = data_enum.variants.iter().enumerate().map(|(i, variant)| {
343 let var_ident = &variant.ident;
344 let disc_value = i as u8; let fields = &variant.fields;
346
347 let write_disc = if no_disc_prefix {
350 quote! {}
351 } else {
352 quote! {
353 let _p_disc: u8 = #disc_value;
354 _p_stream.write_fixed_int(_p_disc);
355 }
356 };
357
358 match fields {
359 Fields::Unit => {
360 if read {
361 quote! {
362 #disc_value => {
363 Ok(Self::#var_ident)
364 }
365 }
366 } else {
367 quote! {
368 Self::#var_ident => {
369 #write_disc
370 }
371 }
372 }
373 }
374 Fields::Unnamed(fields_unnamed) => {
375 let field_count = fields_unnamed.unnamed.len();
376 let idents: Vec<_> = (0..field_count).map(|i| format_ident!("f{}", i)).collect();
377 let ident_refs: Vec<&syn::Ident> = idents.iter().collect();
378 let field_serializations =
379 generate_enum_field_serializations(read, &ident_refs, &fields_unnamed.unnamed);
380 if read {
381 quote! {
382 #disc_value => {
383 #(#field_serializations)*
384 Ok(Self::#var_ident(#(#idents),*))
385 }
386 }
387 } else {
388 quote! {
389 Self::#var_ident(#(#idents),*) => {
390 #write_disc
391 #(#field_serializations)*
392 }
393 }
394 }
395 }
396 Fields::Named(fields_named) => {
397 let field_idents: Vec<_> = fields_named
398 .named
399 .iter()
400 .map(|f| f.ident.as_ref().unwrap())
401 .collect();
402
403 let field_serializations =
404 generate_enum_field_serializations(read, &field_idents, &fields_named.named);
405
406 if read {
407 quote! {
408 #disc_value => {
409 #(#field_serializations)*
410 Ok(Self::#var_ident { #(#field_idents),* })
411 }
412 }
413 } else {
414 quote! {
415 Self::#var_ident { #(#field_idents),* } => {
416 #write_disc
417 #(#field_serializations)*
418 }
419 }
420 }
421 }
422 }
423 });
424
425 if read {
426 quote! {
427 impl #enum_name {
428 pub fn configure_multi_disc<T : Clone>(config: &mut binary_codec::SerializerConfig<T>) {
429 let _p_config = config;
430 #(#configure_functions)*
431 }
432 }
433
434 impl<T : Clone> binary_codec::BinaryDeserializer<T> for #enum_name {
435 fn read_bytes(
436 stream: &mut binary_codec::BitStreamReader,
437 config: Option<&mut binary_codec::SerializerConfig<T>>,
438 ) -> Result<Self, #error_type> {
439 let mut _new_config = binary_codec::SerializerConfig::new(None);
440 let _p_config = config.unwrap_or(&mut _new_config);
441 let _p_stream = stream;
442
443 let _p_disc = if let Some(disc) = _p_config.discriminator.take() {
444 disc
445 } else {
446 _p_stream.read_fixed_int()?
447 };
448
449 match _p_disc {
450 #(#serialization_variants,)*
451 _ => Err(#error_type::UnknownDiscriminant(_p_disc)),
452 }
453 }
454 }
455 }
456 .into()
457 } else {
458 quote! {
459 impl<T : Clone> binary_codec::BinarySerializer<T> for #enum_name {
460 fn write_bytes(
461 &self,
462 stream: &mut binary_codec::BitStreamWriter,
463 config: Option<&mut binary_codec::SerializerConfig<T>>,
464 ) -> Result<(), #error_type> {
465 let mut _new_config = binary_codec::SerializerConfig::new(None);
466 let _p_config = config.unwrap_or(&mut _new_config);
467 #(#configure_functions)*
468 let _p_stream = stream;
469
470 match self {
471 #(#serialization_variants)*
472 }
473
474 Ok(())
475 }
476 }
477
478 impl #enum_name {
479 pub fn get_discriminator(&self) -> u8 {
480 match self {
481 #(#disc_variants,)*
482 }
483 }
484 }
485 }
486 .into()
487 }
488}
489
490fn generate_enum_field_serializations(
491 read: bool,
492 idents: &Vec<&syn::Ident>,
493 fields: &Punctuated<syn::Field, Comma>,
494) -> Vec<proc_macro2::TokenStream> {
495 let field_serializations = fields.iter().enumerate().map(|(i, f)| {
496 let field_type = &f.ty;
497 let field_ident = &idents[i];
498
499 generate_field_serializer(read, &field_ident, field_type, f, true)
500 });
501 field_serializations.collect()
502}
503
504fn generate_code_for_handling_field(
505 read: bool,
506 field_type: &Type,
507 field_name: &syn::Ident,
508 bits_count: Option<u8>,
509 toggled_by: Option<String>,
510 variant_by: Option<String>,
511 length_by: Option<String>,
512 is_dynamic_int: bool,
513 has_dynamic_length: bool,
514 key_dyn_length: bool,
515 val_dyn_length: bool,
516 multi_enum: bool,
517 direct_collection_child: bool,
518 level: usize,
519) -> proc_macro2::TokenStream {
520 if let Type::Path(path) = field_type {
521 let path = &path.path;
522
523 if let Some(ident) = path.get_ident() {
524 let ident_name = ident.to_string();
525
526 match ident_name.as_str() {
528 "bool" => {
529 if read {
530 quote! { let _p_val = _p_stream.read_bit()?;}
531 } else {
532 quote! { _p_stream.write_bit(*_p_val); }
533 }
534 }
535 "i8" => {
536 if let Some(bits_count) = bits_count.as_ref() {
537 if *bits_count < 1 || *bits_count > 7 {
538 panic!("Bits count should be between 1 and 7");
539 }
540
541 if read {
542 quote! { let _p_val = binary_codec::ZigZag::to_signed(_p_stream.read_small(#bits_count)?); }
543 } else {
544 quote! { _p_stream.write_small(binary_codec::ZigZag::to_unsigned(*_p_val), #bits_count); }
545 }
546 } else {
547 if read {
548 quote! { let _p_val = _p_stream.read_fixed_int()?; }
549 } else {
550 quote! { _p_stream.write_fixed_int(*_p_val); }
551 }
552 }
553 }
554 "u8" => {
555 if let Some(bits_count) = bits_count.as_ref() {
556 if *bits_count < 1 || *bits_count > 7 {
557 panic!("Bits count should be between 1 and 7");
558 }
559
560 if read {
561 quote! { let _p_val = _p_stream.read_small(#bits_count)?; }
562 } else {
563 quote! { _p_stream.write_small(*_p_val, #bits_count); }
564 }
565 } else {
566 if read {
567 quote! { let _p_val = _p_stream.read_byte()?; }
568 } else {
569 quote! { _p_stream.write_byte(*_p_val); }
570 }
571 }
572 }
573 "u16" | "u32" | "u64" | "u128" => {
574 if is_dynamic_int {
575 let dynint: proc_macro2::TokenStream = generate_dynint(read);
576 if read {
577 quote! {
578 #dynint
579 let _p_val = _p_dyn as #ident;
580 }
581 } else {
582 quote! {
583 let _p_dyn = *_p_val as u128;
584 #dynint
585 }
586 }
587 } else {
588 if read {
589 quote! { let _p_val = _p_stream.read_fixed_int()?; }
590 } else {
591 quote! { _p_stream.write_fixed_int(*_p_val); }
592 }
593 }
594 }
595 "i16" | "i32" | "i64" | "i128" => {
596 if is_dynamic_int {
597 let dynint: proc_macro2::TokenStream = generate_dynint(read);
598 if read {
599 quote! {
600 #dynint
601 let _p_val: #ident = binary_codec::ZigZag::to_signed(_p_dyn);
602 }
603 } else {
604 quote! {
605 let _p_dyn = binary_codec::ZigZag::to_unsigned(*_p_val) as u128;
606 #dynint
607 }
608 }
609 } else {
610 if read {
611 quote! { let _p_val = _p_stream.read_fixed_int()?; }
612 } else {
613 quote! { _p_stream.write_fixed_int(*_p_val); }
614 }
615 }
616 }
617 "String" => {
618 let size_key = generate_size_key(length_by, has_dynamic_length).1;
619
620 if read {
621 quote! {
622 let _p_val = binary_codec::utils::read_string(_p_stream, #size_key, _p_config)?;
623 }
624 } else {
625 quote! {
626 binary_codec::utils::write_string(_p_val, #size_key, _p_stream, _p_config)?;
627 }
628 }
629 }
630 _ => {
631 let size_key = generate_size_key(length_by, has_dynamic_length).1;
632
633 let variant_code = if variant_by.is_some() {
634 quote! {
635 _p_config.discriminator = _p_config.get_variant(#variant_by);
636 }
637 } else if multi_enum {
638 let config_multi = if !direct_collection_child {
639 quote! { #ident::configure_multi_disc(_p_config); }
640 } else {
641 quote! {}
642 };
643
644 quote! {
645 #config_multi
646 _p_config.discriminator = _p_config.get_next_multi_disc(stringify!(#field_name), #ident_name);
647 }
648 } else {
649 quote! {
650 _p_config.discriminator = None;
651 }
652 };
653
654 if read {
655 quote! {
656 #variant_code
657 let _p_val = binary_codec::utils::read_object(_p_stream, #size_key, _p_config)?;
658 }
659 } else {
660 quote! {
661 #variant_code
662 binary_codec::utils::write_object(_p_val, #size_key, _p_stream, _p_config)?;
663 }
664 }
665 }
666 }
667 } else {
668 if path.segments.len() == 1 {
670 let ident = &path.segments[0].ident;
671 let ident_name = ident.to_string();
672
673 match ident_name.as_ref() {
674 "RefCell" => {
675 let inner_type = get_inner_type(path).expect("Option missing inner type");
676 let handle = generate_code_for_handling_field(
677 read,
678 inner_type,
679 field_name,
680 bits_count,
681 None,
682 variant_by,
683 length_by,
684 is_dynamic_int,
685 has_dynamic_length,
686 key_dyn_length,
687 val_dyn_length,
688 multi_enum,
689 false,
690 level + 1,
691 );
692
693 if read {
694 quote! {
695 #handle
696 let _p_val = RefCell::new(_p_val);
697 }
698 } else {
699 quote! {
700 let _p_val = &*_p_val.borrow();
701 #handle
702 }
703 }
704 }
705 "Option" => {
706 let inner_type = get_inner_type(path).expect("Option missing inner type");
707 let handle = generate_code_for_handling_field(
708 read,
709 inner_type,
710 field_name,
711 bits_count,
712 None,
713 variant_by,
714 length_by,
715 is_dynamic_int,
716 has_dynamic_length,
717 key_dyn_length,
718 val_dyn_length,
719 multi_enum,
720 false,
721 level + 1,
722 );
723 let option_name: syn::Ident = format_ident!("__option_{}", level);
724
725 if let Some(toggled_by) = toggled_by {
726 let toggled_by = quote! {
728 _p_config.get_toggle(#toggled_by).unwrap_or(false)
729 };
730
731 if read {
732 quote! {
733 let mut #option_name: Option<#inner_type> = None;
734 if #toggled_by {
735 #handle
736 #option_name = Some(_p_val);
737 }
738 let _p_val = #option_name;
739 }
740 } else {
741 quote! {
742 if #toggled_by {
743 let _p_val = _p_val.as_ref().expect("Expected Some value, because toggled_by field is true");
744 #handle
745 }
746 }
747 }
748 } else {
749 if read {
751 quote! {
752 let mut #option_name: Option<#inner_type> = None;
753 if _p_stream.bytes_left() > 0 {
754 #handle
755 #option_name = Some(_p_val);
756 }
757 let _p_val = #option_name;
758 }
759 } else {
760 quote! {
761 if let Some(_p_val) = _p_val.as_ref() {
762 #handle
763 }
764 }
765 }
766 }
767 }
768 "Vec" => {
769 let vec_name = format_ident!("__val_{}", level);
770 let inner_type = get_inner_type(path).expect("Vec missing inner type");
771
772 if let Type::Path(inner_path) = inner_type {
774 if let Some(inner_ident) = inner_path.path.get_ident() {
775 if inner_ident == "u8" {
776 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
777
778 if read {
779 if has_size || multi_enum {
780 let len_code = if multi_enum {
782 quote! {
783 let _p_len = _p_config.get_multi_disc_size("u8");
785 }
786 } else {
787 quote! {
788 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
789 }
790 };
791
792 quote! {
793 #len_code
794 let _p_val = _p_stream.read_bytes(_p_len)?.to_vec();
795 }
796 } else {
797 quote! {
799 let _p_len = _p_stream.bytes_left();
800 let _p_val = _p_stream.read_bytes(_p_len)?.to_vec();
801 }
802 }
803 } else {
804 let write_size = if has_size {
806 quote! {
807 let _p_len = _p_val.len();
808 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
809 }
810 } else {
811 quote! {}
812 };
813
814 quote! {
815 #write_size
816 _p_stream.write_bytes(&_p_val);
817 }
818 }
819 } else {
820 let handle = generate_code_for_handling_field(
822 read,
823 inner_type,
824 field_name,
825 bits_count,
826 None,
827 None,
828 None,
829 is_dynamic_int,
830 val_dyn_length,
831 false,
832 false,
833 multi_enum,
834 true,
835 level + 1,
836 );
837
838 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
839
840 let write_code = quote! {
841 for _p_val in _p_val {
842 #handle
843 }
844 };
845
846 if has_size || (read && multi_enum) {
847 if read {
848 let len_code = if multi_enum && let Type::Path(path) = inner_type {
849 let enum_ident = path
850 .path
851 .get_ident()
852 .expect("Expected ident for multi_enum inner type");
853 quote! {
854 #enum_ident::configure_multi_disc(_p_config);
855 let _p_len = _p_config.get_multi_disc_size(stringify!(#enum_ident));
856 }
857 } else {
858 quote! {
859 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
860 }
861 };
862
863 quote! {
864 #len_code
865 let mut #vec_name = Vec::<#inner_type>::with_capacity(_p_len);
866 for _ in 0.._p_len {
867 #handle
868 #vec_name.push(_p_val);
869 }
870 let _p_val = #vec_name;
871 }
872 } else {
873 quote! {
874 let _p_len = _p_val.len();
875 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
876 #write_code
877 }
878 }
879 } else {
880 if read {
881 quote! {
882 let mut #vec_name = Vec::<#inner_type>::new();
883 while _p_stream.bytes_left() > 0 {
884 #handle
885 #vec_name.push(_p_val);
886 }
887 let _p_val = #vec_name;
888 }
889 } else {
890 quote! {
891 #write_code
892 }
893 }
894 }
895 }
896 } else {
897 panic!("Unsupported inner type for Vec");
898 }
899 } else {
900 panic!("Unsupported inner type for Vec");
901 }
902 }
903 "HashMap" => {
904 let (key_type, value_type) =
905 get_two_types(path).expect("Failed to get HashMap types");
906
907 let handle_key = generate_code_for_handling_field(
908 read,
909 key_type,
910 field_name,
911 None,
912 None,
913 None,
914 None,
915 is_dynamic_int,
916 key_dyn_length,
917 false,
918 false,
919 false,
920 false,
921 level + 1,
922 );
923
924 let handle_value = generate_code_for_handling_field(
925 read,
926 value_type,
927 field_name,
928 None,
929 None,
930 None,
931 None,
932 is_dynamic_int,
933 val_dyn_length,
934 false,
935 false,
936 false,
937 false,
938 level + 1,
939 );
940
941 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
942
943 let write_code = quote! {
944 for (key, value) in _p_val {
945 let _p_val = key;
946 #handle_key
947 let _p_val = value;
948 #handle_value
949 }
950 };
951
952 if read {
953 if has_size {
954 quote! {
955 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
956 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::with_capacity(_p_len);
957 for _ in 0.._p_len {
958 let _p_key;
959 #handle_key
960 _p_key = _p_val;
961 let _p_value;
962 #handle_value
963 _p_value = _p_val;
964 _p_map.insert(_p_key, _p_value);
965 }
966 let _p_val = _p_map;
967 }
968 } else {
969 quote! {
970 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::new();
971 while _p_stream.bytes_left() > 0 {
972 let _p_key;
973 #handle_key
974 _p_key = _p_val;
975 let _p_value;
976 #handle_value
977 _p_value = _p_val;
978 _p_map.insert(_p_key, _p_value);
979 }
980 let _p_val = _p_map;
981 }
982 }
983 } else {
984 if has_size {
985 quote! {
986 let _p_len = _p_val.len();
987 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
988 #write_code
989 }
990 } else {
991 quote! {
992 #write_code
993 }
994 }
995 }
996 }
997 _ => {
998 panic!("Type not implemented")
999 }
1000 }
1001 } else {
1002 panic!("Multi-segment paths are not supported");
1003 }
1004 }
1005 } else if let Type::Array(array) = field_type {
1006 let len: usize = if let syn::Expr::Lit(ref arr_len_lit) = array.len {
1007 if let Lit::Int(ref lit_int) = arr_len_lit.lit {
1008 lit_int
1009 .base10_parse()
1010 .expect("Failed to parse literal to usize")
1011 } else {
1012 panic!("Expected an int to determine array length");
1013 }
1014 } else {
1015 panic!("Expected literal to determine array length");
1016 };
1017
1018 let array_type = &*array.elem;
1019 if let Type::Path(at_path) = array_type {
1021 if let Some(at_ident) = at_path.path.get_ident() {
1022 if at_ident == "u8" {
1023 if read {
1024 quote! {
1025 let _p_slice = _p_stream.read_bytes(#len)?;
1026 let _p_val = <[u8; #len]>::try_from(_p_slice).expect("Failed to convert slice to array");
1027 }
1028 } else {
1029 quote! {
1030 _p_stream.write_bytes(&_p_val);
1031 }
1032 }
1033 } else {
1034 let handle = generate_code_for_handling_field(
1035 read,
1036 array_type,
1037 field_name,
1038 bits_count,
1039 None,
1040 None,
1041 None,
1042 is_dynamic_int,
1043 val_dyn_length,
1044 false,
1045 false,
1046 false,
1047 true,
1048 level + 1,
1049 );
1050
1051 let array_name = format_ident!("__val_{}", level);
1052
1053 if read {
1054 quote! {
1055 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
1056 for _ in 0..#len {
1057 #handle;
1058 #array_name.push(_p_val);
1059 }
1060 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
1061 }
1062 } else {
1063 quote! {
1064 for _p_val in _p_val {
1065 #handle
1066 }
1067 }
1068 }
1069 }
1070 } else {
1071 let handle = generate_code_for_handling_field(
1073 read,
1074 array_type,
1075 field_name,
1076 bits_count,
1077 None,
1078 None,
1079 None,
1080 is_dynamic_int,
1081 val_dyn_length,
1082 false,
1083 false,
1084 false,
1085 true,
1086 level + 1,
1087 );
1088
1089 let array_name = format_ident!("__val_{}", level);
1090
1091 if read {
1092 quote! {
1093 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
1094 for _ in 0..#len {
1095 #handle;
1096 #array_name.push(_p_val);
1097 }
1098 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
1099 }
1100 } else {
1101 quote! {
1102 for _p_val in _p_val {
1103 #handle
1104 }
1105 }
1106 }
1107 }
1108 } else {
1109 panic!("Unsupported array element type");
1110 }
1111 } else {
1112 panic!("Field type of '{:?}' not supported", field_name);
1113 }
1114}
1115
1116fn generate_error_type(read: bool) -> proc_macro2::TokenStream {
1117 if read {
1118 quote! { binary_codec::DeserializationError }
1119 } else {
1120 quote! { binary_codec::SerializationError }
1121 }
1122}
1123
1124fn generate_size_key(
1125 length_by: Option<String>,
1126 has_dynamic_length: bool,
1127) -> (bool, proc_macro2::TokenStream) {
1128 if let Some(length_by) = length_by.as_ref() {
1129 (true, quote! { Some(#length_by) })
1130 } else if has_dynamic_length {
1131 (true, quote! { Some("__dynamic") })
1132 } else {
1133 (false, quote! { None })
1134 }
1135}
1136
1137fn get_string_value_from_attribute(attr: &Attribute) -> Option<String> {
1138 match &attr.meta {
1139 syn::Meta::Path(_) => None,
1140 syn::Meta::List(list_value) => {
1141 for token in list_value.tokens.clone().into_iter() {
1143 if let proc_macro2::TokenTree::Literal(lit) = token {
1144 return Some(lit.to_string().trim_matches('"').to_string());
1145 }
1146 }
1147
1148 None
1149 }
1150 syn::Meta::NameValue(name_value) => {
1151 if let syn::Expr::Lit(lit_expr) = &name_value.value {
1152 if let Lit::Str(lit_str) = &lit_expr.lit {
1153 return Some(lit_str.value());
1154 }
1155 }
1156
1157 None
1158 }
1159 }
1160}
1161
1162fn get_int_value_from_attribute(attr: &Attribute) -> Option<i32> {
1163 match &attr.meta {
1164 syn::Meta::Path(_) => None,
1165 syn::Meta::List(list_value) => {
1166 for token in list_value.tokens.clone().into_iter() {
1168 if let proc_macro2::TokenTree::Literal(lit) = token {
1169 if let Ok(val) = lit.to_string().parse::<i32>() {
1170 return Some(val);
1171 }
1172 }
1173 }
1174
1175 None
1176 }
1177 syn::Meta::NameValue(name_value) => {
1178 if let syn::Expr::Lit(lit_expr) = &name_value.value {
1179 if let Lit::Int(lit_int) = &lit_expr.lit {
1180 return Some(lit_int.base10_parse().expect("Not a valid int value"));
1181 }
1182 }
1183
1184 None
1185 }
1186 }
1187}
1188
1189fn get_inner_type(path: &syn::Path) -> Option<&syn::Type> {
1190 if let Some(PathArguments::AngleBracketed(args)) =
1191 path.segments.last().map(|seg| &seg.arguments)
1192 {
1193 if let Some(arg) = args.args.first() {
1194 if let syn::GenericArgument::Type(inner_type) = arg {
1195 return Some(inner_type);
1196 }
1197 }
1198 }
1199
1200 None
1201}
1202
1203fn get_two_types(path: &syn::Path) -> Option<(&syn::Type, &syn::Type)> {
1204 if let Some(PathArguments::AngleBracketed(args)) =
1205 path.segments.last().map(|seg| &seg.arguments)
1206 {
1207 let mut types = args.args.iter().filter_map(|arg| {
1208 if let syn::GenericArgument::Type(inner_type) = arg {
1209 Some(inner_type)
1210 } else {
1211 None
1212 }
1213 });
1214
1215 if let (Some(t1), Some(t2)) = (types.next(), types.next()) {
1216 return Some((t1, t2));
1217 }
1218 }
1219
1220 None
1221}
1222
1223fn generate_dynint(read: bool) -> proc_macro2::TokenStream {
1224 if read {
1225 quote! {
1226 let _p_dyn = _p_stream.read_dyn_int()?;
1227 }
1228 } else {
1229 quote! {
1230 _p_stream.write_dyn_int(_p_dyn);
1231 }
1232 }
1233}