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