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 mut disc_values: Vec<u8> = Vec::with_capacity(data_enum.variants.len());
311 let mut last_val: Option<u8> = None;
312 for variant in data_enum.variants.iter() {
313 let val = if let Some((_, expr)) = &variant.discriminant {
314 match expr {
315 syn::Expr::Lit(syn::ExprLit { lit: Lit::Int(lit_int), .. }) => {
316 lit_int.base10_parse::<u8>().expect("Invalid discriminant integer")
317 }
318 _ => panic!("Discriminant must be an integer literal"),
319 }
320 } else {
321 match last_val {
322 Some(v) => v + 1,
323 None => 0,
324 }
325 };
326
327 if val > u8::from(u8::MAX) {
328 panic!("Discriminant value too large (must fit in u8)");
329 }
330
331 disc_values.push(val);
332 last_val = Some(val);
333 }
334
335 let disc_variants = data_enum
337 .variants
338 .iter()
339 .enumerate()
340 .map(|(i, variant)| {
341 let var_ident = &variant.ident;
342 let disc_value = disc_values[i];
343
344 for attr in variant.attrs.iter() {
345 if attr.path().is_ident("toggled_by") {
346 let field = get_string_value_from_attribute(attr)
347 .expect("toggled_by for multi_enum should have a value");
348 configure_functions.push(quote! {
349 _p_config.configure_multi_disc(stringify!(#enum_name), #disc_value, #field);
350 });
351 }
352 }
353
354 match &variant.fields {
355 Fields::Unit => quote! {
356 Self::#var_ident => #disc_value
357 },
358 Fields::Unnamed(_) => quote! {
359 Self::#var_ident(..) => #disc_value
360 },
361 Fields::Named(_) => quote! {
362 Self::#var_ident { .. } => #disc_value
363 },
364 }
365 })
366 .collect::<Vec<_>>();
367
368 let serialization_variants = data_enum.variants.iter().enumerate().map(|(i, variant)| {
370 let var_ident = &variant.ident;
371 let disc_value = disc_values[i];
372 let fields = &variant.fields;
373
374 let write_disc = if no_disc_prefix {
377 quote! {}
378 } else {
379 quote! {
380 let _p_disc: u8 = #disc_value;
381 _p_stream.write_fixed_int(_p_disc);
382 }
383 };
384
385 match fields {
386 Fields::Unit => {
387 if read {
388 quote! {
389 #disc_value => {
390 Ok(Self::#var_ident)
391 }
392 }
393 } else {
394 quote! {
395 Self::#var_ident => {
396 #write_disc
397 }
398 }
399 }
400 }
401 Fields::Unnamed(fields_unnamed) => {
402 let field_count = fields_unnamed.unnamed.len();
403 let idents: Vec<_> = (0..field_count).map(|i| format_ident!("f{}", i)).collect();
404 let ident_refs: Vec<&syn::Ident> = idents.iter().collect();
405 let field_serializations =
406 generate_enum_field_serializations(read, &ident_refs, &fields_unnamed.unnamed);
407 if read {
408 quote! {
409 #disc_value => {
410 #(#field_serializations)*
411 Ok(Self::#var_ident(#(#idents),*))
412 }
413 }
414 } else {
415 quote! {
416 Self::#var_ident(#(#idents),*) => {
417 #write_disc
418 #(#field_serializations)*
419 }
420 }
421 }
422 }
423 Fields::Named(fields_named) => {
424 let field_idents: Vec<_> = fields_named
425 .named
426 .iter()
427 .map(|f| f.ident.as_ref().unwrap())
428 .collect();
429
430 let field_serializations =
431 generate_enum_field_serializations(read, &field_idents, &fields_named.named);
432
433 if read {
434 quote! {
435 #disc_value => {
436 #(#field_serializations)*
437 Ok(Self::#var_ident { #(#field_idents),* })
438 }
439 }
440 } else {
441 quote! {
442 Self::#var_ident { #(#field_idents),* } => {
443 #write_disc
444 #(#field_serializations)*
445 }
446 }
447 }
448 }
449 }
450 });
451
452 if read {
453 quote! {
454 impl #enum_name {
455 pub fn configure_multi_disc<T : Clone>(config: &mut binary_codec::SerializerConfig<T>) {
456 let _p_config = config;
457 #(#configure_functions)*
458 }
459 }
460
461 impl<T : Clone> binary_codec::BinaryDeserializer<T> for #enum_name {
462 fn read_bytes(
463 stream: &mut binary_codec::BitStreamReader,
464 config: Option<&mut binary_codec::SerializerConfig<T>>,
465 ) -> Result<Self, #error_type> {
466 let mut _new_config = binary_codec::SerializerConfig::new(None);
467 let _p_config = config.unwrap_or(&mut _new_config);
468 let _p_stream = stream;
469
470 let _p_disc = if let Some(disc) = _p_config.discriminator.take() {
471 disc
472 } else {
473 _p_stream.read_fixed_int()?
474 };
475
476 match _p_disc {
477 #(#serialization_variants,)*
478 _ => Err(#error_type::UnknownDiscriminant(_p_disc)),
479 }
480 }
481 }
482 }
483 .into()
484 } else {
485 quote! {
486 impl<T : Clone> binary_codec::BinarySerializer<T> for #enum_name {
487 fn write_bytes(
488 &self,
489 stream: &mut binary_codec::BitStreamWriter,
490 config: Option<&mut binary_codec::SerializerConfig<T>>,
491 ) -> Result<(), #error_type> {
492 let mut _new_config = binary_codec::SerializerConfig::new(None);
493 let _p_config = config.unwrap_or(&mut _new_config);
494 #(#configure_functions)*
495 let _p_stream = stream;
496
497 match self {
498 #(#serialization_variants)*
499 }
500
501 Ok(())
502 }
503 }
504
505 impl #enum_name {
506 pub fn get_discriminator(&self) -> u8 {
507 match self {
508 #(#disc_variants,)*
509 }
510 }
511 }
512 }
513 .into()
514 }
515}
516
517fn generate_enum_field_serializations(
518 read: bool,
519 idents: &Vec<&syn::Ident>,
520 fields: &Punctuated<syn::Field, Comma>,
521) -> Vec<proc_macro2::TokenStream> {
522 let field_serializations = fields.iter().enumerate().map(|(i, f)| {
523 let field_type = &f.ty;
524 let field_ident = &idents[i];
525
526 generate_field_serializer(read, &field_ident, field_type, f, true)
527 });
528 field_serializations.collect()
529}
530
531fn generate_code_for_handling_field(
532 read: bool,
533 field_type: &Type,
534 field_name: &syn::Ident,
535 bits_count: Option<u8>,
536 toggled_by: Option<String>,
537 variant_by: Option<String>,
538 length_by: Option<String>,
539 is_dynamic_int: bool,
540 has_dynamic_length: bool,
541 key_dyn_length: bool,
542 val_dyn_length: bool,
543 multi_enum: bool,
544 direct_collection_child: bool,
545 level: usize,
546) -> proc_macro2::TokenStream {
547 if let Type::Path(path) = field_type {
548 let path = &path.path;
549
550 if let Some(ident) = path.get_ident() {
551 let ident_name = ident.to_string();
552
553 match ident_name.as_str() {
555 "bool" => {
556 if read {
557 quote! { let _p_val = _p_stream.read_bit()?;}
558 } else {
559 quote! { _p_stream.write_bit(*_p_val); }
560 }
561 }
562 "i8" => {
563 if let Some(bits_count) = bits_count.as_ref() {
564 if *bits_count < 1 || *bits_count > 7 {
565 panic!("Bits count should be between 1 and 7");
566 }
567
568 if read {
569 quote! { let _p_val = binary_codec::ZigZag::to_signed(_p_stream.read_small(#bits_count)?); }
570 } else {
571 quote! { _p_stream.write_small(binary_codec::ZigZag::to_unsigned(*_p_val), #bits_count); }
572 }
573 } else {
574 if read {
575 quote! { let _p_val = _p_stream.read_fixed_int()?; }
576 } else {
577 quote! { _p_stream.write_fixed_int(*_p_val); }
578 }
579 }
580 }
581 "u8" => {
582 if let Some(bits_count) = bits_count.as_ref() {
583 if *bits_count < 1 || *bits_count > 7 {
584 panic!("Bits count should be between 1 and 7");
585 }
586
587 if read {
588 quote! { let _p_val = _p_stream.read_small(#bits_count)?; }
589 } else {
590 quote! { _p_stream.write_small(*_p_val, #bits_count); }
591 }
592 } else {
593 if read {
594 quote! { let _p_val = _p_stream.read_byte()?; }
595 } else {
596 quote! { _p_stream.write_byte(*_p_val); }
597 }
598 }
599 }
600 "u16" | "u32" | "u64" | "u128" => {
601 if is_dynamic_int {
602 let dynint: proc_macro2::TokenStream = generate_dynint(read);
603 if read {
604 quote! {
605 #dynint
606 let _p_val = _p_dyn as #ident;
607 }
608 } else {
609 quote! {
610 let _p_dyn = *_p_val as u128;
611 #dynint
612 }
613 }
614 } else {
615 if read {
616 quote! { let _p_val = _p_stream.read_fixed_int()?; }
617 } else {
618 quote! { _p_stream.write_fixed_int(*_p_val); }
619 }
620 }
621 }
622 "i16" | "i32" | "i64" | "i128" => {
623 if is_dynamic_int {
624 let dynint: proc_macro2::TokenStream = generate_dynint(read);
625 if read {
626 quote! {
627 #dynint
628 let _p_val: #ident = binary_codec::ZigZag::to_signed(_p_dyn);
629 }
630 } else {
631 quote! {
632 let _p_dyn = binary_codec::ZigZag::to_unsigned(*_p_val) as u128;
633 #dynint
634 }
635 }
636 } else {
637 if read {
638 quote! { let _p_val = _p_stream.read_fixed_int()?; }
639 } else {
640 quote! { _p_stream.write_fixed_int(*_p_val); }
641 }
642 }
643 }
644 "String" => {
645 let size_key = generate_size_key(length_by, has_dynamic_length).1;
646
647 if read {
648 quote! {
649 let _p_val = binary_codec::utils::read_string(_p_stream, #size_key, _p_config)?;
650 }
651 } else {
652 quote! {
653 binary_codec::utils::write_string(_p_val, #size_key, _p_stream, _p_config)?;
654 }
655 }
656 }
657 _ => {
658 let size_key = generate_size_key(length_by, has_dynamic_length).1;
659
660 let variant_code = if variant_by.is_some() {
661 quote! {
662 _p_config.discriminator = _p_config.get_variant(#variant_by);
663 }
664 } else if multi_enum {
665 let config_multi = if !direct_collection_child {
666 quote! { #ident::configure_multi_disc(_p_config); }
667 } else {
668 quote! {}
669 };
670
671 quote! {
672 #config_multi
673 _p_config.discriminator = _p_config.get_next_multi_disc(stringify!(#field_name), #ident_name);
674 }
675 } else {
676 quote! {
677 _p_config.discriminator = None;
678 }
679 };
680
681 if read {
682 quote! {
683 #variant_code
684 let _p_val = binary_codec::utils::read_object(_p_stream, #size_key, _p_config)?;
685 }
686 } else {
687 quote! {
688 #variant_code
689 binary_codec::utils::write_object(_p_val, #size_key, _p_stream, _p_config)?;
690 }
691 }
692 }
693 }
694 } else {
695 if path.segments.len() == 1 {
697 let ident = &path.segments[0].ident;
698 let ident_name = ident.to_string();
699
700 match ident_name.as_ref() {
701 "RefCell" => {
702 let inner_type = get_inner_type(path).expect("Option missing inner type");
703 let handle = generate_code_for_handling_field(
704 read,
705 inner_type,
706 field_name,
707 bits_count,
708 None,
709 variant_by,
710 length_by,
711 is_dynamic_int,
712 has_dynamic_length,
713 key_dyn_length,
714 val_dyn_length,
715 multi_enum,
716 false,
717 level + 1,
718 );
719
720 if read {
721 quote! {
722 #handle
723 let _p_val = RefCell::new(_p_val);
724 }
725 } else {
726 quote! {
727 let _p_val = &*_p_val.borrow();
728 #handle
729 }
730 }
731 }
732 "Option" => {
733 let inner_type = get_inner_type(path).expect("Option missing inner type");
734 let handle = generate_code_for_handling_field(
735 read,
736 inner_type,
737 field_name,
738 bits_count,
739 None,
740 variant_by,
741 length_by,
742 is_dynamic_int,
743 has_dynamic_length,
744 key_dyn_length,
745 val_dyn_length,
746 multi_enum,
747 false,
748 level + 1,
749 );
750 let option_name: syn::Ident = format_ident!("__option_{}", level);
751
752 if let Some(toggled_by) = toggled_by {
753 let toggled_by = quote! {
755 _p_config.get_toggle(#toggled_by).unwrap_or(false)
756 };
757
758 if read {
759 quote! {
760 let mut #option_name: Option<#inner_type> = None;
761 if #toggled_by {
762 #handle
763 #option_name = Some(_p_val);
764 }
765 let _p_val = #option_name;
766 }
767 } else {
768 quote! {
769 if #toggled_by {
770 let _p_val = _p_val.as_ref().expect("Expected Some value, because toggled_by field is true");
771 #handle
772 }
773 }
774 }
775 } else {
776 if read {
778 quote! {
779 let mut #option_name: Option<#inner_type> = None;
780 if _p_stream.bytes_left() > 0 {
781 #handle
782 #option_name = Some(_p_val);
783 }
784 let _p_val = #option_name;
785 }
786 } else {
787 quote! {
788 if let Some(_p_val) = _p_val.as_ref() {
789 #handle
790 }
791 }
792 }
793 }
794 }
795 "Vec" => {
796 let vec_name = format_ident!("__val_{}", level);
797 let inner_type = get_inner_type(path).expect("Vec missing inner type");
798
799 if let Type::Path(inner_path) = inner_type {
801 if let Some(inner_ident) = inner_path.path.get_ident() {
802 if inner_ident == "u8" {
803 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
804
805 if read {
806 if has_size || multi_enum {
807 let len_code = if multi_enum {
809 quote! {
810 let _p_len = _p_config.get_multi_disc_size("u8");
812 }
813 } else {
814 quote! {
815 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
816 }
817 };
818
819 quote! {
820 #len_code
821 let _p_val = _p_stream.read_bytes(_p_len)?.to_vec();
822 }
823 } else {
824 quote! {
826 let _p_len = _p_stream.bytes_left();
827 let _p_val = _p_stream.read_bytes(_p_len)?.to_vec();
828 }
829 }
830 } else {
831 let write_size = if has_size {
833 quote! {
834 let _p_len = _p_val.len();
835 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
836 }
837 } else {
838 quote! {}
839 };
840
841 quote! {
842 #write_size
843 _p_stream.write_bytes(_p_val);
844 }
845 }
846 } else {
847 let handle = generate_code_for_handling_field(
849 read,
850 inner_type,
851 field_name,
852 bits_count,
853 None,
854 None,
855 None,
856 is_dynamic_int,
857 val_dyn_length,
858 false,
859 false,
860 multi_enum,
861 true,
862 level + 1,
863 );
864
865 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
866
867 let write_code = quote! {
868 for _p_val in _p_val {
869 #handle
870 }
871 };
872
873 if has_size || (read && multi_enum) {
874 if read {
875 let len_code = if multi_enum && let Type::Path(path) = inner_type {
876 let enum_ident = path
877 .path
878 .get_ident()
879 .expect("Expected ident for multi_enum inner type");
880 quote! {
881 #enum_ident::configure_multi_disc(_p_config);
882 let _p_len = _p_config.get_multi_disc_size(stringify!(#enum_ident));
883 }
884 } else {
885 quote! {
886 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
887 }
888 };
889
890 quote! {
891 #len_code
892 let mut #vec_name = Vec::<#inner_type>::with_capacity(_p_len);
893 for _ in 0.._p_len {
894 #handle
895 #vec_name.push(_p_val);
896 }
897 let _p_val = #vec_name;
898 }
899 } else {
900 quote! {
901 let _p_len = _p_val.len();
902 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
903 #write_code
904 }
905 }
906 } else {
907 if read {
908 quote! {
909 let mut #vec_name = Vec::<#inner_type>::new();
910 while _p_stream.bytes_left() > 0 {
911 #handle
912 #vec_name.push(_p_val);
913 }
914 let _p_val = #vec_name;
915 }
916 } else {
917 quote! {
918 #write_code
919 }
920 }
921 }
922 }
923 } else {
924 panic!("Unsupported inner type for Vec");
925 }
926 } else {
927 panic!("Unsupported inner type for Vec");
928 }
929 }
930 "HashMap" => {
931 let (key_type, value_type) =
932 get_two_types(path).expect("Failed to get HashMap types");
933
934 let handle_key = generate_code_for_handling_field(
935 read,
936 key_type,
937 field_name,
938 None,
939 None,
940 None,
941 None,
942 is_dynamic_int,
943 key_dyn_length,
944 false,
945 false,
946 false,
947 false,
948 level + 1,
949 );
950
951 let handle_value = generate_code_for_handling_field(
952 read,
953 value_type,
954 field_name,
955 None,
956 None,
957 None,
958 None,
959 is_dynamic_int,
960 val_dyn_length,
961 false,
962 false,
963 false,
964 false,
965 level + 1,
966 );
967
968 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
969
970 let write_code = quote! {
971 for (key, value) in _p_val {
972 let _p_val = key;
973 #handle_key
974 let _p_val = value;
975 #handle_value
976 }
977 };
978
979 if read {
980 if has_size {
981 quote! {
982 let _p_len = binary_codec::utils::get_read_size(_p_stream, #size_key, _p_config)?;
983 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::with_capacity(_p_len);
984 for _ in 0.._p_len {
985 let _p_key;
986 #handle_key
987 _p_key = _p_val;
988 let _p_value;
989 #handle_value
990 _p_value = _p_val;
991 _p_map.insert(_p_key, _p_value);
992 }
993 let _p_val = _p_map;
994 }
995 } else {
996 quote! {
997 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::new();
998 while _p_stream.bytes_left() > 0 {
999 let _p_key;
1000 #handle_key
1001 _p_key = _p_val;
1002 let _p_value;
1003 #handle_value
1004 _p_value = _p_val;
1005 _p_map.insert(_p_key, _p_value);
1006 }
1007 let _p_val = _p_map;
1008 }
1009 }
1010 } else {
1011 if has_size {
1012 quote! {
1013 let _p_len = _p_val.len();
1014 binary_codec::utils::write_size(_p_len, #size_key, _p_stream, _p_config)?;
1015 #write_code
1016 }
1017 } else {
1018 quote! {
1019 #write_code
1020 }
1021 }
1022 }
1023 }
1024 _ => {
1025 panic!("Type not implemented")
1026 }
1027 }
1028 } else {
1029 panic!("Multi-segment paths are not supported");
1030 }
1031 }
1032 } else if let Type::Array(array) = field_type {
1033 let len: usize = if let syn::Expr::Lit(ref arr_len_lit) = array.len {
1034 if let Lit::Int(ref lit_int) = arr_len_lit.lit {
1035 lit_int
1036 .base10_parse()
1037 .expect("Failed to parse literal to usize")
1038 } else {
1039 panic!("Expected an int to determine array length");
1040 }
1041 } else {
1042 panic!("Expected literal to determine array length");
1043 };
1044
1045 let array_type = &*array.elem;
1046 if let Type::Path(at_path) = array_type {
1048 if let Some(at_ident) = at_path.path.get_ident() {
1049 if at_ident == "u8" {
1050 if read {
1051 quote! {
1052 let _p_slice = _p_stream.read_bytes(#len)?;
1053 let _p_val = <[u8; #len]>::try_from(_p_slice).expect("Failed to convert slice to array");
1054 }
1055 } else {
1056 quote! {
1057 _p_stream.write_bytes(_p_val);
1058 }
1059 }
1060 } else {
1061 let handle = generate_code_for_handling_field(
1062 read,
1063 array_type,
1064 field_name,
1065 bits_count,
1066 None,
1067 None,
1068 None,
1069 is_dynamic_int,
1070 val_dyn_length,
1071 false,
1072 false,
1073 false,
1074 true,
1075 level + 1,
1076 );
1077
1078 let array_name = format_ident!("__val_{}", level);
1079
1080 if read {
1081 quote! {
1082 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
1083 for _ in 0..#len {
1084 #handle;
1085 #array_name.push(_p_val);
1086 }
1087 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
1088 }
1089 } else {
1090 quote! {
1091 for _p_val in _p_val {
1092 #handle
1093 }
1094 }
1095 }
1096 }
1097 } else {
1098 let handle = generate_code_for_handling_field(
1100 read,
1101 array_type,
1102 field_name,
1103 bits_count,
1104 None,
1105 None,
1106 None,
1107 is_dynamic_int,
1108 val_dyn_length,
1109 false,
1110 false,
1111 false,
1112 true,
1113 level + 1,
1114 );
1115
1116 let array_name = format_ident!("__val_{}", level);
1117
1118 if read {
1119 quote! {
1120 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
1121 for _ in 0..#len {
1122 #handle;
1123 #array_name.push(_p_val);
1124 }
1125 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
1126 }
1127 } else {
1128 quote! {
1129 for _p_val in _p_val {
1130 #handle
1131 }
1132 }
1133 }
1134 }
1135 } else {
1136 panic!("Unsupported array element type");
1137 }
1138 } else {
1139 panic!("Field type of '{:?}' not supported", field_name);
1140 }
1141}
1142
1143fn generate_error_type(read: bool) -> proc_macro2::TokenStream {
1144 if read {
1145 quote! { binary_codec::DeserializationError }
1146 } else {
1147 quote! { binary_codec::SerializationError }
1148 }
1149}
1150
1151fn generate_size_key(
1152 length_by: Option<String>,
1153 has_dynamic_length: bool,
1154) -> (bool, proc_macro2::TokenStream) {
1155 if let Some(length_by) = length_by.as_ref() {
1156 (true, quote! { Some(#length_by) })
1157 } else if has_dynamic_length {
1158 (true, quote! { Some("__dynamic") })
1159 } else {
1160 (false, quote! { None })
1161 }
1162}
1163
1164fn get_string_value_from_attribute(attr: &Attribute) -> Option<String> {
1165 match &attr.meta {
1166 syn::Meta::Path(_) => None,
1167 syn::Meta::List(list_value) => {
1168 for token in list_value.tokens.clone().into_iter() {
1170 if let proc_macro2::TokenTree::Literal(lit) = token {
1171 return Some(lit.to_string().trim_matches('"').to_string());
1172 }
1173 }
1174
1175 None
1176 }
1177 syn::Meta::NameValue(name_value) => {
1178 if let syn::Expr::Lit(lit_expr) = &name_value.value {
1179 if let Lit::Str(lit_str) = &lit_expr.lit {
1180 return Some(lit_str.value());
1181 }
1182 }
1183
1184 None
1185 }
1186 }
1187}
1188
1189fn get_int_value_from_attribute(attr: &Attribute) -> Option<i32> {
1190 match &attr.meta {
1191 syn::Meta::Path(_) => None,
1192 syn::Meta::List(list_value) => {
1193 for token in list_value.tokens.clone().into_iter() {
1195 if let proc_macro2::TokenTree::Literal(lit) = token {
1196 if let Ok(val) = lit.to_string().parse::<i32>() {
1197 return Some(val);
1198 }
1199 }
1200 }
1201
1202 None
1203 }
1204 syn::Meta::NameValue(name_value) => {
1205 if let syn::Expr::Lit(lit_expr) = &name_value.value {
1206 if let Lit::Int(lit_int) = &lit_expr.lit {
1207 return Some(lit_int.base10_parse().expect("Not a valid int value"));
1208 }
1209 }
1210
1211 None
1212 }
1213 }
1214}
1215
1216fn get_inner_type(path: &syn::Path) -> Option<&syn::Type> {
1217 if let Some(PathArguments::AngleBracketed(args)) =
1218 path.segments.last().map(|seg| &seg.arguments)
1219 {
1220 if let Some(arg) = args.args.first() {
1221 if let syn::GenericArgument::Type(inner_type) = arg {
1222 return Some(inner_type);
1223 }
1224 }
1225 }
1226
1227 None
1228}
1229
1230fn get_two_types(path: &syn::Path) -> Option<(&syn::Type, &syn::Type)> {
1231 if let Some(PathArguments::AngleBracketed(args)) =
1232 path.segments.last().map(|seg| &seg.arguments)
1233 {
1234 let mut types = args.args.iter().filter_map(|arg| {
1235 if let syn::GenericArgument::Type(inner_type) = arg {
1236 Some(inner_type)
1237 } else {
1238 None
1239 }
1240 });
1241
1242 if let (Some(t1), Some(t2)) = (types.next(), types.next()) {
1243 return Some((t1, t2));
1244 }
1245 }
1246
1247 None
1248}
1249
1250fn generate_dynint(read: bool) -> proc_macro2::TokenStream {
1251 if read {
1252 quote! {
1253 let _p_dyn = _p_stream.read_dyn_int()?;
1254 }
1255 } else {
1256 quote! {
1257 _p_stream.write_dyn_int(_p_dyn);
1258 }
1259 }
1260}