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