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