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