1extern crate proc_macro;
2
3use quote::{format_ident, quote};
4use syn::{
5 parse_macro_input, punctuated::Punctuated, token::Comma, Attribute, Data, DeriveInput, Fields,
6 Lit, PathArguments, Type,
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 no_discriminator
24 )
25)]
26pub fn generate_code_to_bytes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
27 generate_code_binary_serializer(false, input)
28}
29
30#[proc_macro_derive(
31 FromBytes,
32 attributes(
33 bits,
34 dyn_int,
35 key_dyn_length,
36 val_dyn_length,
37 dyn_length,
38 toggles,
39 toggled_by,
40 length_for,
41 length_by,
42 variant_for,
43 variant_by,
44 no_discriminator
45 )
46)]
47pub fn generate_code_from_bytes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
48 generate_code_binary_serializer(true, input)
49}
50
51fn generate_code_binary_serializer(
52 read: bool,
53 input: proc_macro::TokenStream,
54) -> proc_macro::TokenStream {
55 let ast = parse_macro_input!(input as DeriveInput);
57
58 match ast.data {
59 Data::Struct(ref data) => generate_struct_serializer(read, &ast, data),
60 Data::Enum(ref data) => generate_enum_serializer(read, &ast, data),
61 _ => panic!("ToBytes can only be used on structs"),
62 }
63}
64
65fn generate_struct_serializer(
66 read: bool,
67 ast: &DeriveInput,
68 data_struct: &syn::DataStruct,
69) -> proc_macro::TokenStream {
70 let fields = &data_struct.fields;
71 let struct_name = &ast.ident;
72
73 let field_serializations = fields.iter().map(|field| {
75 let field_name = field
76 .ident
77 .as_ref()
78 .expect("ToBytes does not support fields without a name");
79
80 let field_type = &field.ty;
81
82 let mut toggle_key = None;
83 let mut variant_key = None;
84 let mut length_key = None;
85 let mut toggled_by = None;
86 let mut variant_by = None;
87 let mut length_by = None;
88 let mut is_dynamic_int = false;
89 let mut has_dynamic_length = false;
90 let mut bits_count = None;
91 let mut key_dyn_length = false;
92 let mut val_dyn_length = false;
93
94 for attr in field.attrs.iter() {
96 let ident = attr.path().get_ident().map(|i| i.clone().to_string());
97 match ident.as_deref() {
98 Some("dyn_int") => is_dynamic_int = true,
99 Some("dyn_length") => has_dynamic_length = true,
100 Some("key_dyn_length") => key_dyn_length = true,
101 Some("val_dyn_length") => val_dyn_length = true,
102 Some("toggles") => toggle_key = get_string_value_from_attribute(attr),
103 Some("variant_for") => variant_key = get_string_value_from_attribute(attr),
104 Some("length_for") => length_key = get_string_value_from_attribute(attr),
105 Some("toggled_by") => toggled_by = get_string_value_from_attribute(attr),
106 Some("variant_by") => variant_by = get_string_value_from_attribute(attr),
107 Some("length_by") => length_by = get_string_value_from_attribute(attr),
108 Some("bits") => bits_count = get_int_value_from_attribute(attr).map(|b| b as u8),
109 _ => {}
110 }
112 }
113
114 let toggles = if let Some(key) = toggle_key {
116 if read {
117 quote! {
118 _p_config.set_toggle(#key, _p_val);
119 }
120 } else {
121 quote! {
122 _p_config.set_toggle(#key, *_p_val);
123 }
124 }
125 } else { quote! {} };
126
127 let length = if let Some(key) = length_key {
129 if read {
130 quote! {
131 _p_config.set_length(#key, _p_val as usize);
132 }
133 } else {
134 quote! {
135 _p_config.set_length(#key, *_p_val as usize);
136 }
137 }
138 } else { quote! {} };
139
140 let variant = if let Some(key) = variant_key {
142 if read {
143 quote! {
144 _p_config.set_variant(#key, _p_val as u8);
145 }
146 } else {
147 quote! {
148 _p_config.set_variant(#key, *_p_val as u8);
149 }
150 }
151 } else { quote! {} };
152
153 let before = if read {
155 quote! {}
156 } else {
157 quote! {
158 let _p_val = &self.#field_name;
159 #toggles
160 #length
161 #variant
162 }
163 };
164
165 let after = if read {
166 quote! {
167 let #field_name = _p_val;
168 #toggles
169 #length
170 #variant
171 }
172 } else {
173 quote! {}
174 };
175
176 let handle_field = generate_code_for_handling_field(
177 read,
178 field_type,
179 field_name,
180 bits_count,
181 toggled_by,
182 variant_by,
183 length_by,
184 is_dynamic_int,
185 has_dynamic_length,
186 key_dyn_length,
187 val_dyn_length,
188 0,
189 );
190
191 quote! {
192 #before
193 #handle_field
194 #after
195 }
196 });
197
198 let error_type = generate_error_type(read);
199 let serializer_code = if read {
200 let vars = fields.iter().map(|f| f.ident.as_ref().unwrap());
201
202 quote! {
204 impl<T : Clone> binary_codec::BinaryDeserializer<T> for #struct_name {
205 fn deserialize(bytes: &[u8], config: Option<&mut binary_codec::SerializerConfig<T>>) -> Result<Self, #error_type> {
206 let mut _new_config = binary_codec::SerializerConfig::new(None);
207 let _p_config = config.unwrap_or(&mut _new_config);
208 let _p_bytes = bytes;
209
210 #(#field_serializations)*
211
212 Ok(Self {
213 #(#vars),*
214 })
215 }
216 }
217 }
218 } else {
219 quote! {
221 impl<T : Clone> binary_codec::BinarySerializer<T> for #struct_name {
222 fn serialize(&self, config: Option<&mut binary_codec::SerializerConfig<T>>) -> Result<Vec<u8>, #error_type> {
223 let mut bytes = Vec::new();
224 Self::write_bytes(self, &mut bytes, config)?;
225 Ok(bytes)
226 }
227
228 fn write_bytes(&self, buffer: &mut Vec<u8>, config: Option<&mut binary_codec::SerializerConfig<T>>) -> Result<(), #error_type> {
229 let mut _new_config = binary_codec::SerializerConfig::new(None);
230 let _p_config = config.unwrap_or(&mut _new_config);
231 let _p_bytes = buffer;
232
233 #(#field_serializations)*
234 Ok(())
235 }
236 }
237 }
238 };
239
240 serializer_code.into()
241}
242
243fn generate_enum_serializer(
244 read: bool,
245 ast: &DeriveInput,
246 data_enum: &syn::DataEnum,
247) -> proc_macro::TokenStream {
248 let enum_name = &ast.ident;
249 let error_type = generate_error_type(read);
250
251 let mut no_disc_prefix = false;
252
253 for attr in ast.attrs.iter() {
255 if attr.path().is_ident("no_discriminator") {
257 no_disc_prefix = true;
258 }
259 }
260
261 let disc_variants = data_enum.variants.iter().enumerate().map(|(i, variant)| {
263 let var_ident = &variant.ident;
264 let disc_value = i as u8;
265
266 match &variant.fields {
267 Fields::Unit => quote! {
268 Self::#var_ident => #disc_value
269 },
270 Fields::Unnamed(_) => quote! {
271 Self::#var_ident(..) => #disc_value
272 },
273 Fields::Named(_) => quote! {
274 Self::#var_ident { .. } => #disc_value
275 },
276 }
277 });
278
279 let serialization_variants = data_enum.variants.iter().enumerate().map(|(i, variant)| {
281 let var_ident = &variant.ident;
282 let disc_value = i as u8; let fields = &variant.fields;
284
285 let write_disc = if no_disc_prefix {
286 quote! {}
287 } else {
288 quote! {
289 let _p_disc: u8 = #disc_value;
290 binary_codec::fixed_int::FixedInt::write(_p_disc, _p_bytes, _p_config)?;
291 }
292 };
293
294 match fields {
295 Fields::Unit => {
296 if read {
297 quote! {
298 #disc_value => {
299 Ok(Self::#var_ident)
300 }
301 }
302 } else {
303 quote! {
304 Self::#var_ident => {
305 #write_disc
306 }
307 }
308 }
309 }
310 Fields::Unnamed(fields_unnamed) => {
311 let field_count = fields_unnamed.unnamed.len();
312 let idents: Vec<_> = (0..field_count).map(|i| format_ident!("f{}", i)).collect();
313 let ident_refs: Vec<&syn::Ident> = idents.iter().collect();
314 let field_serializations =
315 generate_enum_field_serializations(read, &ident_refs, &fields_unnamed.unnamed);
316 if read {
317 quote! {
318 #disc_value => {
319 #(#field_serializations)*
320 Ok(Self::#var_ident(#(#idents),*))
321 }
322 }
323 } else {
324 quote! {
325 Self::#var_ident(#(#idents),*) => {
326 #write_disc
327 #(#field_serializations)*
328 }
329 }
330 }
331 }
332 Fields::Named(fields_named) => {
333 let field_idents: Vec<_> = fields_named
334 .named
335 .iter()
336 .map(|f| f.ident.as_ref().unwrap())
337 .collect();
338
339 let field_serializations =
340 generate_enum_field_serializations(read, &field_idents, &fields_named.named);
341
342 if read {
343 quote! {
344 #disc_value => {
345 #(#field_serializations)*
346 Ok(Self::#var_ident { #(#field_idents),* })
347 }
348 }
349 } else {
350 quote! {
351 Self::#var_ident { #(#field_idents),* } => {
352 #write_disc
353 #(#field_serializations)*
354 }
355 }
356 }
357 }
358 }
359 });
360
361 if read {
362 quote! {
363 impl<T : Clone> binary_codec::BinaryDeserializer<T> for #enum_name {
364 fn deserialize(bytes: &[u8], config: Option<&mut binary_codec::SerializerConfig<T>>) -> Result<Self, #error_type> {
365 let mut _new_config = binary_codec::SerializerConfig::new(None);
366 let _p_config = config.unwrap_or(&mut _new_config);
367 let _p_bytes = bytes;
368
369 let _p_disc = if let Some(disc) = _p_config.discriminator.take() {
370 disc
371 } else {
372 binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?
373 };
374
375 match _p_disc {
376 #(#serialization_variants,)*
377 _ => Err(#error_type::UnknownDiscriminant(_p_disc)),
378 }
379 }
380 }
381 }
382 .into()
383 } else {
384 quote! {
385 impl<T : Clone> binary_codec::BinarySerializer<T> for #enum_name {
386 fn serialize(&self, config: Option<&mut binary_codec::SerializerConfig<T>>) -> Result<Vec<u8>, #error_type> {
387 let mut bytes = Vec::new();
388 Self::write_bytes(self, &mut bytes, config)?;
389 Ok(bytes)
390 }
391
392 fn write_bytes(&self, buffer: &mut Vec<u8>, config: Option<&mut binary_codec::SerializerConfig<T>>) -> Result<(), #error_type> {
393 let mut _new_config = binary_codec::SerializerConfig::new(None);
394 let _p_config = config.unwrap_or(&mut _new_config);
395 let _p_bytes = buffer;
396
397 match self {
398 #(#serialization_variants)*
399 }
400
401 Ok(())
402 }
403 }
404
405 impl #enum_name {
406 pub fn get_discriminator(&self) -> u8 {
407 match self {
408 #(#disc_variants,)*
409 }
410 }
411 }
412 }
413 .into()
414 }
415}
416
417fn generate_enum_field_serializations(
418 read: bool,
419 idents: &Vec<&syn::Ident>,
420 fields: &Punctuated<syn::Field, Comma>,
421) -> Vec<proc_macro2::TokenStream> {
422 let field_serializations = fields.iter().enumerate().map(|(i, f)| {
423 let field_type = &f.ty;
424 let field_ident = &idents[i];
425
426 let mut toggled_by = None;
428 let mut variant_by = None;
429 let mut length_by = None;
430 let mut is_dynamic_int = false;
431 let mut has_dynamic_length = false;
432 let mut bits_count = None;
433 let mut key_dyn_length = false;
434 let mut val_dyn_length = false;
435
436 for attr in f.attrs.iter() {
437 let ident = attr.path().get_ident().map(|i| i.clone().to_string());
438 match ident.as_deref() {
439 Some("dyn_int") => is_dynamic_int = true,
440 Some("dyn_length") => has_dynamic_length = true,
441 Some("key_dyn_length") => key_dyn_length = true,
442 Some("val_dyn_length") => val_dyn_length = true,
443 Some("toggled_by") => toggled_by = get_string_value_from_attribute(attr),
444 Some("variant_by") => variant_by = get_string_value_from_attribute(attr),
445 Some("length_by") => length_by = get_string_value_from_attribute(attr),
446 Some("bits") => bits_count = get_int_value_from_attribute(attr).map(|b| b as u8),
447 _ => {}
448 }
449 }
450
451 let handle_field = generate_code_for_handling_field(
452 read,
453 field_type,
454 field_ident,
455 bits_count,
456 toggled_by,
457 variant_by,
458 length_by,
459 is_dynamic_int,
460 has_dynamic_length,
461 key_dyn_length,
462 val_dyn_length,
463 0,
464 );
465
466 if read {
467 quote! {
468 #handle_field
469 let #field_ident = _p_val;
470 }
471 } else {
472 quote! {
473 let _p_val = #field_ident;
474 #handle_field
475 }
476 }
477 });
478 field_serializations.collect()
479}
480
481fn generate_code_for_handling_field(
482 read: bool,
483 field_type: &Type,
484 field_name: &syn::Ident,
485 bits_count: Option<u8>,
486 toggled_by: Option<String>,
487 variant_by: Option<String>,
488 length_by: Option<String>,
489 is_dynamic_int: bool,
490 has_dynamic_length: bool,
491 key_dyn_length: bool,
492 val_dyn_length: bool,
493 level: usize,
494) -> proc_macro2::TokenStream {
495 if let Type::Path(path) = field_type {
496 let path = &path.path;
497
498 if let Some(ident) = path.get_ident() {
499 let ident_name = ident.to_string();
500
501 match ident_name.as_str() {
503 "bool" => {
504 if read {
505 quote! { let _p_val = binary_codec::dynamics::read_bool(_p_bytes, _p_config)?; }
506 } else {
507 quote! { binary_codec::dynamics::write_bool(*_p_val, _p_bytes, _p_config)?; }
508 }
509 }
510 "i8" => {
511 if let Some(bits_count) = bits_count.as_ref() {
512 if *bits_count < 1 || *bits_count > 7 {
513 panic!("Bits count should be between 1 and 7");
514 }
515
516 if read {
517 quote! { let _p_val = binary_codec::dynamics::read_small_dynamic_signed(_p_bytes, _p_config, #bits_count)?; }
518 } else {
519 quote! { binary_codec::dynamics::write_small_dynamic_signed(*_p_val, _p_bytes, _p_config, #bits_count)?; }
520 }
521 } else {
522 if read {
523 quote! {
524 let _p_val = binary_codec::dynamics::read_zigzag(_p_bytes, _p_config)?;
525 }
526 } else {
527 quote! {
528 binary_codec::dynamics::write_zigzag(*_p_val, _p_bytes, _p_config)?;
529 }
530 }
531 }
532 }
533 "u8" => {
534 if let Some(bits_count) = bits_count.as_ref() {
535 if *bits_count < 1 || *bits_count > 7 {
536 panic!("Bits count should be between 1 and 7");
537 }
538
539 if read {
540 quote! { let _p_val = binary_codec::dynamics::read_small_dynamic_unsigned(_p_bytes, _p_config, #bits_count)?; }
541 } else {
542 quote! { binary_codec::dynamics::write_small_dynamic_unsigned(*_p_val, _p_bytes, _p_config, #bits_count)?; }
543 }
544 } else {
545 if read {
546 quote! {
547 let _p_val = binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?;
548 }
549 } else {
550 quote! {
551 binary_codec::fixed_int::FixedInt::write(*_p_val, _p_bytes, _p_config)?;
552 }
553 }
554 }
555 }
556 "u16" | "u32" | "u64" | "u128" => {
557 if is_dynamic_int {
558 let dynint: proc_macro2::TokenStream = generate_dynint(read);
559 if read {
560 quote! {
561 #dynint
562 let _p_val = _p_dyn as #ident;
563 }
564 } else {
565 quote! {
566 let _p_dyn = *_p_val as u128;
567 #dynint
568 }
569 }
570 } else {
571 if read {
572 quote! {
573 let _p_val = binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?;
574 }
575 } else {
576 quote! {
577 binary_codec::fixed_int::FixedInt::write(*_p_val, _p_bytes, _p_config)?;
578 }
579 }
580 }
581 }
582 "i16" | "i32" | "i64" | "i128" => {
583 if is_dynamic_int {
584 let dynint: proc_macro2::TokenStream = generate_dynint(read);
585 if read {
586 quote! {
587 #dynint
588 let _p_val: #ident = binary_codec::fixed_int::ZigZag::to_signed(_p_dyn);
589 }
590 } else {
591 quote! {
592 let _p_dyn = binary_codec::fixed_int::ZigZag::to_unsigned(*_p_val) as u128;
593 #dynint
594 }
595 }
596 } else {
597 if read {
598 quote! {
599 let _p_val = binary_codec::fixed_int::read_zigzag(_p_bytes, _p_config)?;
600 }
601 } else {
602 quote! {
603 binary_codec::fixed_int::write_zigzag(*_p_val, _p_bytes, _p_config)?;
604 }
605 }
606 }
607 }
608 "String" => {
609 let size_key = generate_size_key(length_by, has_dynamic_length).1;
610
611 if read {
612 quote! {
613 let _p_val = binary_codec::variable::read_string(_p_bytes, #size_key, _p_config)?;
614 }
615 } else {
616 quote! {
617 binary_codec::variable::write_string(_p_val, #size_key, _p_bytes, _p_config)?;
618 }
619 }
620 }
621 _ => {
622 let size_key = generate_size_key(length_by, has_dynamic_length).1;
623
624 let variant_code = if variant_by.is_some() {
625 quote! {
626 _p_config.discriminator = _p_config.get_variant(#variant_by);
627 }
628 } else { quote! {} };
629
630 if read {
631 quote! {
632 #variant_code
633 let _p_val = binary_codec::variable::read_object(_p_bytes, #size_key, _p_config)?;
634 }
635 } else {
636 quote! {
637 #variant_code
638 binary_codec::variable::write_object(_p_val, #size_key, _p_bytes, _p_config)?;
639 }
640 }
641 }
642 }
643 } else {
644 if path.segments.len() == 1 {
646 let ident = &path.segments[0].ident;
647 let ident_name = ident.to_string();
648
649 match ident_name.as_ref() {
650 "Option" => {
651 let inner_type = get_inner_type(path).expect("Option missing inner type");
652 let handle = generate_code_for_handling_field(
653 read,
654 inner_type,
655 field_name,
656 bits_count,
657 None,
658 variant_by,
659 length_by,
660 is_dynamic_int,
661 has_dynamic_length,
662 key_dyn_length,
663 val_dyn_length,
664 level + 1,
665 );
666 let option_name: syn::Ident = format_ident!("__option_{}", level);
667
668 if let Some(toggled_by) = toggled_by {
669 let toggled_by = quote! {
671 _p_config.get_toggle(#toggled_by).unwrap_or(false)
672 };
673
674 if read {
675 quote! {
676 let mut #option_name: Option<#inner_type> = None;
677 if #toggled_by {
678 #handle
679 #option_name = Some(_p_val);
680 }
681 let _p_val = #option_name;
682 }
683 } else {
684 quote! {
685 if #toggled_by {
686 let _p_val = _p_val.as_ref().expect("Expected Some value, because toggled_by field is true");
687 #handle
688 }
689 }
690 }
691 } else {
692 if read {
694 quote! {
695 let mut #option_name: Option<#inner_type> = None;
696 if _p_config.next_reset_bits_pos() < _p_bytes.len() {
697 #handle
698 #option_name = Some(_p_val);
699 }
700 let _p_val = #option_name;
701 }
702 } else {
703 quote! {
704 if let Some(_p_val) = _p_val.as_ref() {
705 #handle
706 }
707 }
708 }
709 }
710 }
711 "Vec" => {
712 let vec_name = format_ident!("__val_{}", level);
713 let inner_type = get_inner_type(path).expect("Vec missing inner type");
714 let handle = generate_code_for_handling_field(
715 read,
716 inner_type,
717 field_name,
718 bits_count,
719 None,
720 None,
721 None,
722 is_dynamic_int,
723 val_dyn_length,
724 false,
725 false,
726 level + 1,
727 );
728
729 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
730
731 let write_code = quote! {
732 for _p_val in _p_val {
733 #handle
734 }
735 };
736
737 if has_size {
738 if read {
739 quote! {
740 let _p_len = binary_codec::utils::get_read_size(_p_bytes, #size_key, _p_config)?;
741 let mut #vec_name = Vec::<#inner_type>::with_capacity(_p_len);
742 for _ in 0.._p_len {
743 #handle
744 #vec_name.push(_p_val);
745 }
746 let _p_val = #vec_name;
747 }
748 } else {
749 quote! {
750 let _p_len = _p_val.len();
751 binary_codec::utils::write_size(_p_len, #size_key, _p_bytes, _p_config)?;
752 #write_code
753 }
754 }
755 } else {
756 if read {
757 quote! {
758 let mut #vec_name = Vec::<#inner_type>::new();
759 while _p_config.next_reset_bits_pos() < _p_bytes.len() {
760 #handle
761 #vec_name.push(_p_val);
762 }
763 let _p_val = #vec_name;
764 }
765 } else {
766 quote! {
767 #write_code
768 }
769 }
770 }
771 }
772 "HashMap" => {
773 let (key_type, value_type) =
774 get_two_types(path).expect("Failed to get HashMap types");
775
776 let handle_key = generate_code_for_handling_field(
777 read,
778 key_type,
779 field_name,
780 None,
781 None,
782 None,
783 None,
784 is_dynamic_int,
785 key_dyn_length,
786 false,
787 false,
788 level + 1,
789 );
790
791 let handle_value = generate_code_for_handling_field(
792 read,
793 value_type,
794 field_name,
795 None,
796 None,
797 None,
798 None,
799 is_dynamic_int,
800 val_dyn_length,
801 false,
802 false,
803 level + 1,
804 );
805
806 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
807
808 let write_code = quote! {
809 for (key, value) in _p_val {
810 let _p_val = key;
811 #handle_key
812 let _p_val = value;
813 #handle_value
814 }
815 };
816
817 if read {
818 if has_size {
819 quote! {
820 let _p_len = binary_codec::utils::get_read_size(_p_bytes, #size_key, _p_config)?;
821 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::with_capacity(_p_len);
822 for _ in 0.._p_len {
823 let _p_key;
824 #handle_key
825 _p_key = _p_val;
826 let _p_value;
827 #handle_value
828 _p_value = _p_val;
829 _p_map.insert(_p_key, _p_value);
830 }
831 let _p_val = _p_map;
832 }
833 } else {
834 quote! {
835 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::new();
836 while _p_config.next_reset_bits_pos() < _p_bytes.len() {
837 let _p_key;
838 #handle_key
839 _p_key = _p_val;
840 let _p_value;
841 #handle_value
842 _p_value = _p_val;
843 _p_map.insert(_p_key, _p_value);
844 }
845 let _p_val = _p_map;
846 }
847 }
848 } else {
849 if has_size {
850 quote! {
851 let _p_len = _p_val.len();
852 binary_codec::utils::write_size(_p_len, #size_key, _p_bytes, _p_config)?;
853 #write_code
854 }
855 } else {
856 quote! {
857 #write_code
858 }
859 }
860 }
861 }
862 _ => {
863 panic!("Type not implemented")
864 }
865 }
866 } else {
867 panic!("Multi-segment paths are not supported");
868 }
869 }
870 } else if let Type::Array(array) = field_type {
871 let len: usize = if let syn::Expr::Lit(ref arr_len_lit) = array.len {
872 if let Lit::Int(ref lit_int) = arr_len_lit.lit {
873 lit_int
874 .base10_parse()
875 .expect("Failed to parse literal to usize")
876 } else {
877 panic!("Expected an int to determine array length");
878 }
879 } else {
880 panic!("Expected literal to determine array length");
881 };
882
883 let array_type = &array.elem;
884 let handle = generate_code_for_handling_field(
885 read,
886 array_type,
887 field_name,
888 bits_count,
889 None,
890 None,
891 None,
892 is_dynamic_int,
893 val_dyn_length,
894 false,
895 false,
896 level + 1,
897 );
898
899 let array_name = format_ident!("__val_{}", level);
900
901 if read {
902 quote! {
903 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
904 for _ in 0..#len {
905 #handle;
906 #array_name.push(_p_val);
907 }
908 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
909 }
910 } else {
911 quote! {
912 for _p_val in _p_val {
913 #handle
914 }
915 }
916 }
917 } else {
918 panic!("Field type of '{:?}' not supported", field_name);
919 }
920}
921
922fn generate_error_type(read: bool) -> proc_macro2::TokenStream {
923 if read {
924 quote! { binary_codec::DeserializationError }
925 } else {
926 quote! { binary_codec::SerializationError }
927 }
928}
929
930fn generate_size_key(length_by: Option<String>, has_dynamic_length: bool) -> (bool, proc_macro2::TokenStream) {
931 if let Some(length_by) = length_by.as_ref() {
932 (true, quote! { Some(#length_by) })
933 } else if has_dynamic_length {
934 (true, quote! { Some("__dynamic") })
935 } else {
936 (false, quote! { None })
937 }
938}
939
940fn get_string_value_from_attribute(
941 attr: &Attribute
942) -> Option<String> {
943 match &attr.meta {
944 syn::Meta::Path(_) => {
945 None
946 }
947 syn::Meta::List(list_value) => {
948 for token in list_value.tokens.clone().into_iter() {
950 if let proc_macro2::TokenTree::Literal(lit) = token {
951 return Some(lit.to_string().trim_matches('"').to_string());
952 }
953 }
954
955 None
956 }
957 syn::Meta::NameValue(name_value) => {
958 if let syn::Expr::Lit(lit_expr) = &name_value.value {
959 if let Lit::Str(lit_str) = &lit_expr.lit {
960 return Some(lit_str.value());
961 }
962 }
963
964 None
965 }
966 }
967}
968
969fn get_int_value_from_attribute(attr: &Attribute) -> Option<i32> {
970 match &attr.meta {
971 syn::Meta::Path(_) => {
972 None
973 }
974 syn::Meta::List(list_value) => {
975 for token in list_value.tokens.clone().into_iter() {
977 if let proc_macro2::TokenTree::Literal(lit) = token {
978 if let Ok(val) = lit.to_string().parse::<i32>() {
979 return Some(val);
980 }
981 }
982 }
983
984 None
985 }
986 syn::Meta::NameValue(name_value) => {
987 if let syn::Expr::Lit(lit_expr) = &name_value.value {
988 if let Lit::Int(lit_int) = &lit_expr.lit {
989 return Some(lit_int.base10_parse().expect("Not a valid int value"));
990 }
991 }
992
993 None
994 }
995 }
996}
997
998fn get_inner_type(path: &syn::Path) -> Option<&syn::Type> {
999 if let Some(PathArguments::AngleBracketed(args)) =
1000 path.segments.last().map(|seg| &seg.arguments)
1001 {
1002 if let Some(arg) = args.args.first() {
1003 if let syn::GenericArgument::Type(inner_type) = arg {
1004 return Some(inner_type);
1005 }
1006 }
1007 }
1008
1009 None
1010}
1011
1012fn get_two_types(path: &syn::Path) -> Option<(&syn::Type, &syn::Type)> {
1013 if let Some(PathArguments::AngleBracketed(args)) =
1014 path.segments.last().map(|seg| &seg.arguments)
1015 {
1016 let mut types = args.args.iter().filter_map(|arg| {
1017 if let syn::GenericArgument::Type(inner_type) = arg {
1018 Some(inner_type)
1019 } else {
1020 None
1021 }
1022 });
1023
1024 if let (Some(t1), Some(t2)) = (types.next(), types.next()) {
1025 return Some((t1, t2));
1026 }
1027 }
1028
1029 None
1030}
1031
1032fn generate_dynint(read: bool) -> proc_macro2::TokenStream {
1033 if read {
1034 quote! {
1035 let _p_dyn = binary_codec::dyn_int::read_dynint(_p_bytes, _p_config)?;
1036 }
1037 } else {
1038 quote! {
1039 binary_codec::dyn_int::write_dynint(_p_dyn, _p_bytes, _p_config)?;
1040 }
1041 }
1042}