binary_codec_derive/
lib.rs

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    // Parse code input (TokenStream) to AST
56    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    // Iterate all fields in the struct
74    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        // Search attributes for length/toggle declarations
95        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                // None => continue
111            }
112        }
113
114        // Runtime toggle_key
115        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        // Runtime length_key
128        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        // Runtime variant_key
141        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        // Compose code to handle field
154        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        // read bytes code
203        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        // write bytes code
220        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    // Search attributes for variant_by declarations
254    for attr in ast.attrs.iter() {
255        // #[no_disc_prefix] attribute
256        if attr.path().is_ident("no_discriminator") {
257            no_disc_prefix = true;
258        }
259    }
260
261    // Create discriminant getter
262    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    // Assign discriminant values starting from 0
280    let serialization_variants = data_enum.variants.iter().enumerate().map(|(i, variant)| {
281        let var_ident = &variant.ident;
282        let disc_value = i as u8; // Could be changed to u16/u32 if needed
283        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        // Extract attributes from enum field (same attrs supported for struct fields)
427        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            // Single segment without arguments
502            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            // Multiple segments, or arguments
645            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                            // If toggled_by is set, read or write it
670                            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 space available, read it, write it if not None
693                            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            // #[myattribute("value")]
949            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            // #[myattribute(value)]
976            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}