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 let handle = generate_code_for_handling_field(
773 read,
774 inner_type,
775 field_name,
776 bits_count,
777 None,
778 None,
779 None,
780 is_dynamic_int,
781 val_dyn_length,
782 false,
783 false,
784 multi_enum,
785 true,
786 level + 1,
787 );
788
789 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
790
791 let write_code = quote! {
792 for _p_val in _p_val {
793 #handle
794 }
795 };
796
797 if has_size || (read && multi_enum) {
798 if read {
799 let len_code = if multi_enum && let Type::Path(path) = inner_type {
800 let enum_ident = path
801 .path
802 .get_ident()
803 .expect("Expected ident for multi_enum inner type");
804 quote! {
805 #enum_ident::configure_multi_disc(_p_config);
806 let _p_len = _p_config.get_multi_disc_size(stringify!(#enum_ident));
807 }
808 } else {
809 quote! {
810 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
811 }
812 };
813
814 quote! {
815 #len_code
816 let mut #vec_name = Vec::<#inner_type>::with_capacity(_p_len);
817 for _ in 0.._p_len {
818 #handle
819 #vec_name.push(_p_val);
820 }
821 let _p_val = #vec_name;
822 }
823 } else {
824 quote! {
825 let _p_len = _p_val.len();
826 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
827 #write_code
828 }
829 }
830 } else {
831 if read {
832 quote! {
833 let mut #vec_name = Vec::<#inner_type>::new();
834 while _p_stream.bytes_left() > 0 {
835 #handle
836 #vec_name.push(_p_val);
837 }
838 let _p_val = #vec_name;
839 }
840 } else {
841 quote! {
842 #write_code
843 }
844 }
845 }
846 }
847 "HashMap" => {
848 let (key_type, value_type) =
849 get_two_types(path).expect("Failed to get HashMap types");
850
851 let handle_key = generate_code_for_handling_field(
852 read,
853 key_type,
854 field_name,
855 None,
856 None,
857 None,
858 None,
859 is_dynamic_int,
860 key_dyn_length,
861 false,
862 false,
863 false,
864 false,
865 level + 1,
866 );
867
868 let handle_value = generate_code_for_handling_field(
869 read,
870 value_type,
871 field_name,
872 None,
873 None,
874 None,
875 None,
876 is_dynamic_int,
877 val_dyn_length,
878 false,
879 false,
880 false,
881 false,
882 level + 1,
883 );
884
885 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
886
887 let write_code = quote! {
888 for (key, value) in _p_val {
889 let _p_val = key;
890 #handle_key
891 let _p_val = value;
892 #handle_value
893 }
894 };
895
896 if read {
897 if has_size {
898 quote! {
899 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
900 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::with_capacity(_p_len);
901 for _ in 0.._p_len {
902 let _p_key;
903 #handle_key
904 _p_key = _p_val;
905 let _p_value;
906 #handle_value
907 _p_value = _p_val;
908 _p_map.insert(_p_key, _p_value);
909 }
910 let _p_val = _p_map;
911 }
912 } else {
913 quote! {
914 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::new();
915 while _p_stream.bytes_left() > 0 {
916 let _p_key;
917 #handle_key
918 _p_key = _p_val;
919 let _p_value;
920 #handle_value
921 _p_value = _p_val;
922 _p_map.insert(_p_key, _p_value);
923 }
924 let _p_val = _p_map;
925 }
926 }
927 } else {
928 if has_size {
929 quote! {
930 let _p_len = _p_val.len();
931 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
932 #write_code
933 }
934 } else {
935 quote! {
936 #write_code
937 }
938 }
939 }
940 }
941 _ => {
942 panic!("Type not implemented")
943 }
944 }
945 } else {
946 panic!("Multi-segment paths are not supported");
947 }
948 }
949 } else if let Type::Array(array) = field_type {
950 let len: usize = if let syn::Expr::Lit(ref arr_len_lit) = array.len {
951 if let Lit::Int(ref lit_int) = arr_len_lit.lit {
952 lit_int
953 .base10_parse()
954 .expect("Failed to parse literal to usize")
955 } else {
956 panic!("Expected an int to determine array length");
957 }
958 } else {
959 panic!("Expected literal to determine array length");
960 };
961
962 let array_type = &array.elem;
963 let handle = generate_code_for_handling_field(
964 read,
965 array_type,
966 field_name,
967 bits_count,
968 None,
969 None,
970 None,
971 is_dynamic_int,
972 val_dyn_length,
973 false,
974 false,
975 false,
976 true,
977 level + 1,
978 );
979
980 let array_name = format_ident!("__val_{}", level);
981
982 if read {
983 quote! {
984 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
985 for _ in 0..#len {
986 #handle;
987 #array_name.push(_p_val);
988 }
989 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
990 }
991 } else {
992 quote! {
993 for _p_val in _p_val {
994 #handle
995 }
996 }
997 }
998 } else {
999 panic!("Field type of '{:?}' not supported", field_name);
1000 }
1001}
1002
1003fn generate_error_type(read: bool) -> proc_macro2::TokenStream {
1004 if read {
1005 quote! { binary_codec::DeserializationError }
1006 } else {
1007 quote! { binary_codec::SerializationError }
1008 }
1009}
1010
1011fn generate_size_key(
1012 length_by: Option<String>,
1013 has_dynamic_length: bool,
1014) -> (bool, proc_macro2::TokenStream) {
1015 if let Some(length_by) = length_by.as_ref() {
1016 (true, quote! { Some(#length_by) })
1017 } else if has_dynamic_length {
1018 (true, quote! { Some("__dynamic") })
1019 } else {
1020 (false, quote! { None })
1021 }
1022}
1023
1024fn get_string_value_from_attribute(attr: &Attribute) -> Option<String> {
1025 match &attr.meta {
1026 syn::Meta::Path(_) => None,
1027 syn::Meta::List(list_value) => {
1028 for token in list_value.tokens.clone().into_iter() {
1030 if let proc_macro2::TokenTree::Literal(lit) = token {
1031 return Some(lit.to_string().trim_matches('"').to_string());
1032 }
1033 }
1034
1035 None
1036 }
1037 syn::Meta::NameValue(name_value) => {
1038 if let syn::Expr::Lit(lit_expr) = &name_value.value {
1039 if let Lit::Str(lit_str) = &lit_expr.lit {
1040 return Some(lit_str.value());
1041 }
1042 }
1043
1044 None
1045 }
1046 }
1047}
1048
1049fn get_int_value_from_attribute(attr: &Attribute) -> Option<i32> {
1050 match &attr.meta {
1051 syn::Meta::Path(_) => None,
1052 syn::Meta::List(list_value) => {
1053 for token in list_value.tokens.clone().into_iter() {
1055 if let proc_macro2::TokenTree::Literal(lit) = token {
1056 if let Ok(val) = lit.to_string().parse::<i32>() {
1057 return Some(val);
1058 }
1059 }
1060 }
1061
1062 None
1063 }
1064 syn::Meta::NameValue(name_value) => {
1065 if let syn::Expr::Lit(lit_expr) = &name_value.value {
1066 if let Lit::Int(lit_int) = &lit_expr.lit {
1067 return Some(lit_int.base10_parse().expect("Not a valid int value"));
1068 }
1069 }
1070
1071 None
1072 }
1073 }
1074}
1075
1076fn get_inner_type(path: &syn::Path) -> Option<&syn::Type> {
1077 if let Some(PathArguments::AngleBracketed(args)) =
1078 path.segments.last().map(|seg| &seg.arguments)
1079 {
1080 if let Some(arg) = args.args.first() {
1081 if let syn::GenericArgument::Type(inner_type) = arg {
1082 return Some(inner_type);
1083 }
1084 }
1085 }
1086
1087 None
1088}
1089
1090fn get_two_types(path: &syn::Path) -> Option<(&syn::Type, &syn::Type)> {
1091 if let Some(PathArguments::AngleBracketed(args)) =
1092 path.segments.last().map(|seg| &seg.arguments)
1093 {
1094 let mut types = args.args.iter().filter_map(|arg| {
1095 if let syn::GenericArgument::Type(inner_type) = arg {
1096 Some(inner_type)
1097 } else {
1098 None
1099 }
1100 });
1101
1102 if let (Some(t1), Some(t2)) = (types.next(), types.next()) {
1103 return Some((t1, t2));
1104 }
1105 }
1106
1107 None
1108}
1109
1110fn generate_dynint(read: bool) -> proc_macro2::TokenStream {
1111 if read {
1112 quote! {
1113 let _p_dyn = _p_stream.read_dyn_int()?;
1114 }
1115 } else {
1116 quote! {
1117 _p_stream.write_dyn_int(_p_dyn);
1118 }
1119 }
1120}