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