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