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