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
9type FieldReference<'a> = (&'a syn::Ident, Option<usize>);
10
11#[proc_macro_derive(
12 ToBytes,
13 attributes(
14 length_determined_by,
15 toggled_by,
16 bits,
17 dynamic,
18 dynamic_len,
19 variant_by,
20 no_disc_prefix
21 )
22)]
23pub fn generate_code_to_bytes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
24 generate_code_binary_serializer(false, input)
25}
26
27#[proc_macro_derive(
28 FromBytes,
29 attributes(
30 length_determined_by,
31 toggled_by,
32 bits,
33 dynamic,
34 dynamic_len,
35 variant_by,
36 no_disc_prefix
37 )
38)]
39pub fn generate_code_from_bytes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
40 generate_code_binary_serializer(true, input)
41}
42
43fn generate_code_binary_serializer(
44 read: bool,
45 input: proc_macro::TokenStream,
46) -> proc_macro::TokenStream {
47 let ast = parse_macro_input!(input as DeriveInput);
49
50 match ast.data {
51 Data::Struct(ref data) => generate_struct_serializer(read, &ast, data),
52 Data::Enum(ref data) => generate_enum_serializer(read, &ast, data),
53 _ => panic!("ToBytes can only be used on structs"),
54 }
55}
56
57fn generate_struct_serializer(
58 read: bool,
59 ast: &DeriveInput,
60 data_struct: &syn::DataStruct,
61) -> proc_macro::TokenStream {
62 let fields = &data_struct.fields;
63 let struct_name = &ast.ident;
64
65 let field_serializations = fields.iter().map(|field| {
67 let field_name = field
68 .ident
69 .as_ref()
70 .expect("ToBytes does not support fields without a name");
71
72 let field_type = &field.ty;
73
74 let mut length_determining_field = None;
75 let mut toggled_by_field = None;
76 let mut variant_by_field = None;
77 let mut bits_count_type = None;
78 let mut is_dynamic = false;
79 let mut dynamic_length_depth = None;
80
81 for attr in field.attrs.iter() {
83 if attr.path().is_ident("length_determined_by") {
86 length_determining_field = Some(get_field_name_from_attribute(
87 "length_determined_by",
88 attr,
89 fields,
90 field_name,
91 ))
92 }
93
94 if attr.path().is_ident("toggled_by") {
97 toggled_by_field = Some(get_field_name_from_attribute(
98 "toggled_by",
99 attr,
100 fields,
101 field_name,
102 ))
103 }
104
105 if attr.path().is_ident("variant_by") {
108 variant_by_field = Some(get_field_name_from_attribute(
109 "variant_by",
110 attr,
111 fields,
112 field_name,
113 ))
114 }
115
116 if attr.path().is_ident("bits") {
118 let bits_count = get_int_value_from_attribute("bits", attr, field_name);
119 bits_count_type = Some(bits_count as u8);
120 }
121
122 if attr.path().is_ident("dynamic") {
124 is_dynamic = true;
125 }
126
127 if attr.path().is_ident("dynamic_len") {
130 let dynamic_len_value: Option<usize> = get_int_value_from_attribute_2(attr)
132 .or_else(|| Some(1));
133
134 dynamic_length_depth = dynamic_len_value;
135 }
136 }
137
138 let before = if read {
140 quote! {}
141 } else {
142 quote! {
143 let _p_val = &self.#field_name;
144 }
145 };
146
147 let after = if read {
148 quote! {
149 let #field_name = _p_val;
150 }
151 } else {
152 quote! {}
153 };
154
155 let handle_field = generate_code_for_handling_field(
156 read,
157 field_type,
158 field_name,
159 bits_count_type,
160 is_dynamic,
161 dynamic_length_depth,
162 length_determining_field,
163 toggled_by_field,
164 variant_by_field,
165 0,
166 );
167
168 quote! {
169 #before
170 #handle_field
171 #after
172 }
173 });
174
175 let error_type = generate_error_type(read);
176 let serializer_code = if read {
177 let vars = fields.iter().map(|f| f.ident.as_ref().unwrap());
178
179 quote! {
181 fn from_bytes_internal(_p_bytes: &[u8], _p_pos: &mut usize, _p_bits: &mut u8, _p_config: &binary_codec::SerializationConfig) -> Result<Self, #error_type> {
182 #(#field_serializations)*
183
184 Ok(Self {
185 #(#vars),*
186 })
187 }
188
189 pub fn from_bytes(bytes: &[u8], config: &binary_codec::SerializationConfig) -> Result<Self, #error_type> {
190 let mut bits = 0;
191 let mut pos = 0;
192 Self::from_bytes_internal(bytes, &mut pos, &mut bits, config)
193 }
194 }
195 } else {
196 quote! {
198 fn to_bytes_internal(&self, _p_bytes: &mut Vec<u8>, _p_pos: &mut usize, _p_bits: &mut u8, _p_config: &binary_codec::SerializationConfig) -> Result<(), #error_type> {
199 #(#field_serializations)*
200 Ok(())
201 }
202
203 pub fn to_bytes(&self, config: &binary_codec::SerializationConfig) -> Result<Vec<u8>, #error_type> {
204 let mut bytes = Vec::new();
205 let mut bits = 0;
206 let mut pos = 0;
207 self.to_bytes_internal(&mut bytes, &mut pos, &mut bits, config)?;
208 Ok(bytes)
209 }
210 }
211 };
212
213 quote! {
214 impl #struct_name {
215 #serializer_code
216 }
217 }
218 .into()
219}
220
221fn generate_enum_serializer(
222 read: bool,
223 ast: &DeriveInput,
224 data_enum: &syn::DataEnum,
225) -> proc_macro::TokenStream {
226 let enum_name = &ast.ident;
227 let error_type = generate_error_type(read);
228
229 let mut no_disc_prefix = false;
230
231 for attr in ast.attrs.iter() {
233 if attr.path().is_ident("no_disc_prefix") {
235 no_disc_prefix = true;
236 }
237 }
238
239 let variants = data_enum.variants.iter().enumerate().map(|(i, variant)| {
241 let var_ident = &variant.ident;
242 let disc_value = i as u8; let fields = &variant.fields;
244
245 let write_disc = if no_disc_prefix {
246 quote! {}
247 } else {
248 quote! {
249 let _p_disc: u8 = #disc_value;
250 binary_codec::encodings::FixedInt::write(_p_disc, _p_bytes, _p_pos, _p_bits)?;
251 }
252 };
253
254 match fields {
255 Fields::Unit => {
256 if read {
257 quote! {
258 #disc_value => {
259 Ok(Self::#var_ident)
260 }
261 }
262 } else {
263 quote! {
264 Self::#var_ident => {
265 #write_disc
266 }
267 }
268 }
269 }
270 Fields::Unnamed(fields_unnamed) => {
271 let field_count = fields_unnamed.unnamed.len();
272 let idents: Vec<_> = (0..field_count).map(|i| format_ident!("f{}", i)).collect();
273 let ident_refs: Vec<&syn::Ident> = idents.iter().collect();
274 let field_serializations =
275 generate_enum_field_serializations(read, &ident_refs, &fields_unnamed.unnamed);
276 if read {
277 quote! {
278 #disc_value => {
279 #(#field_serializations)*
280 Ok(Self::#var_ident(#(#idents),*))
281 }
282 }
283 } else {
284 quote! {
285 Self::#var_ident(#(#idents),*) => {
286 #write_disc
287 #(#field_serializations)*
288 }
289 }
290 }
291 }
292 Fields::Named(fields_named) => {
293 let field_idents: Vec<_> = fields_named
294 .named
295 .iter()
296 .map(|f| f.ident.as_ref().unwrap())
297 .collect();
298
299 let field_serializations =
300 generate_enum_field_serializations(read, &field_idents, &fields_named.named);
301
302 if read {
303 quote! {
304 #disc_value => {
305 #(#field_serializations)*
306 Ok(Self::#var_ident { #(#field_idents),* })
307 }
308 }
309 } else {
310 quote! {
311 Self::#var_ident { #(#field_idents),* } => {
312 #write_disc
313 #(#field_serializations)*
314 }
315 }
316 }
317 }
318 }
319 });
320
321 if read {
322 quote! {
323 impl #enum_name {
324 fn from_bytes_internal_with_disc(_p_disc: u8, _p_bytes: &[u8], _p_pos: &mut usize, _p_bits: &mut u8, _p_config: &binary_codec::SerializationConfig) -> Result<Self, #error_type> {
325 match _p_disc {
326 #(#variants,)*
327 _ => Err(#error_type::UnknownDiscriminant(_p_disc)),
328 }
329 }
330
331 fn from_bytes_internal(bytes: &[u8], pos: &mut usize, bits: &mut u8, config: &binary_codec::SerializationConfig) -> Result<Self, #error_type> {
332 let _p_disc: u8 = binary_codec::encodings::FixedInt::read(bytes, pos, bits)?;
333 Self::from_bytes_internal_with_disc(_p_disc, bytes, pos, bits, config)
334 }
335
336 pub fn from_bytes(bytes: &[u8], config: &binary_codec::SerializationConfig) -> Result<Self, #error_type> {
337 let mut pos = 0;
338 let mut bits = 0;
339 Self::from_bytes_internal(bytes, &mut pos, &mut bits, config)
340 }
341 }
342 }
343 .into()
344 } else {
345 quote! {
346 impl #enum_name {
347 fn to_bytes_internal(&self, _p_bytes: &mut Vec<u8>, _p_pos: &mut usize, _p_bits: &mut u8, _p_config: &binary_codec::SerializationConfig) -> Result<(), #error_type> {
348 match self {
349 #(#variants)*
350 }
351 Ok(())
352 }
353
354 pub fn to_bytes(&self, config: &binary_codec::SerializationConfig) -> Result<Vec<u8>, #error_type> {
355 let mut bytes = Vec::new();
356 let mut pos = 0;
357 let mut bits = 0;
358 self.to_bytes_internal(&mut bytes, &mut pos, &mut bits, config)?;
359 Ok(bytes)
360 }
361 }
362 }
363 .into()
364 }
365}
366
367fn generate_enum_field_serializations(
368 read: bool,
369 idents: &Vec<&syn::Ident>,
370 fields: &Punctuated<syn::Field, Comma>,
371) -> Vec<proc_macro2::TokenStream> {
372 let field_serializations = fields.iter().enumerate().map(|(i, f)| {
373 let field_type = &f.ty;
374 let field_ident = &idents[i];
375
376 let handle_field = generate_code_for_handling_field(
377 read,
378 field_type,
379 field_ident,
380 None,
381 false,
382 None,
383 None,
384 None,
385 None,
386 0,
387 );
388
389 if read {
390 quote! {
391 #handle_field
392 let #field_ident = _p_val;
393 }
394 } else {
395 quote! {
396 let _p_val = #field_ident;
397 #handle_field
398 }
399 }
400 });
401 field_serializations.collect()
402}
403
404fn generate_code_for_handling_field(
405 read: bool,
406 field_type: &Type,
407 field_name: &syn::Ident,
408 bits_count_type: Option<u8>,
409 is_dynamic: bool,
410 dynamic_length_depth: Option<usize>,
411 length_determining_field: Option<FieldReference>,
412 toggled_by_field: Option<FieldReference>,
413 variant_by_field: Option<FieldReference>,
414 level: usize,
415) -> proc_macro2::TokenStream {
416 if let Type::Path(path) = field_type {
417 let path = &path.path;
418
419 if let Some(ident) = path.get_ident() {
420 let ident_name = ident.to_string();
421 match ident_name.as_str() {
428 "bool" => {
429 if read {
430 quote! { let _p_val = binary_codec::serializers::read_bool(_p_bytes, _p_pos, _p_bits)?; }
431 } else {
432 quote! { binary_codec::serializers::write_bool(*_p_val, _p_bytes, _p_pos, _p_bits)?; }
433 }
434 }
435 "i8" => {
436 if let Some(bits_count) = bits_count_type.as_ref() {
437 if *bits_count < 1 || *bits_count > 7 {
438 panic!("Bits count should be between 1 and 7");
439 }
440
441 if read {
442 quote! { let _p_val = binary_codec::serializers::read_small_dynamic_signed(_p_bytes, _p_pos, _p_bits, #bits_count)?; }
443 } else {
444 quote! { binary_codec::serializers::write_small_dynamic_signed(*_p_val, _p_bytes, _p_pos, _p_bits, #bits_count)?; }
445 }
446 } else {
447 if read {
448 quote! {
449 let _p_val = binary_codec::encodings::read_zigzag(_p_bytes, _p_pos, _p_bits)?;
450 }
451 } else {
452 quote! {
453 binary_codec::encodings::write_zigzag(*_p_val, _p_bytes, _p_pos, _p_bits)?;
454 }
455 }
456 }
457 }
458 "u8" => {
459 if let Some(bits_count) = bits_count_type.as_ref() {
460 if *bits_count < 1 || *bits_count > 7 {
461 panic!("Bits count should be between 1 and 7");
462 }
463
464 if read {
465 quote! { let _p_val = binary_codec::serializers::read_small_dynamic_unsigned(_p_bytes, _p_pos, _p_bits, #bits_count)?; }
466 } else {
467 quote! { binary_codec::serializers::write_small_dynamic_unsigned(*_p_val, _p_bytes, _p_pos, _p_bits, #bits_count)?; }
468 }
469 } else {
470 if read {
471 quote! {
472 let _p_val = binary_codec::encodings::FixedInt::read(_p_bytes, _p_pos, _p_bits)?;
473 }
474 } else {
475 quote! {
476 binary_codec::encodings::FixedInt::write(*_p_val, _p_bytes, _p_pos, _p_bits)?;
477 }
478 }
479 }
480 }
481 "u16" | "u32" | "u64" | "u128" => {
482 if is_dynamic {
483 let dynint: proc_macro2::TokenStream = generate_dynint(read);
484 if read {
485 quote! {
486 #dynint
487 let _p_val = _p_dyn as #ident;
488 }
489 } else {
490 quote! {
491 let _p_dyn = *_p_val as u128;
492 #dynint
493 }
494 }
495 } else {
496 if read {
497 quote! {
498 let _p_val = binary_codec::encodings::FixedInt::read(_p_bytes, _p_pos, _p_bits)?;
499 }
500 } else {
501 quote! {
502 binary_codec::encodings::FixedInt::write(*_p_val, _p_bytes, _p_pos, _p_bits)?;
503 }
504 }
505 }
506 }
507 "i16" | "i32" | "i64" | "i128" => {
508 if is_dynamic {
509 let dynint: proc_macro2::TokenStream = generate_dynint(read);
510 if read {
511 quote! {
512 #dynint
513 let _p_val: #ident = binary_codec::encodings::ZigZag::to_signed(_p_dyn);
514 }
515 } else {
516 quote! {
517 let _p_dyn = binary_codec::encodings::ZigZag::to_unsigned(*_p_val) as u128;
518 #dynint
519 }
520 }
521 } else {
522 if read {
523 quote! {
524 let _p_val = binary_codec::encodings::read_zigzag(_p_bytes, _p_pos, _p_bits)?;
525 }
526 } else {
527 quote! {
528 binary_codec::encodings::write_zigzag(*_p_val, _p_bytes, _p_pos, _p_bits)?;
529 }
530 }
531 }
532 }
533 "String" => {
534 let (len_specified, dynamic_len) = generate_dynamic_length(
540 read,
541 length_determining_field,
542 dynamic_length_depth,
543 quote! { _string },
544 );
545
546 if read {
547 if len_specified {
548 quote! {
549 #dynamic_len
550 let _string = &_p_bytes[*_p_pos..*_p_pos + _p_len];
551 let _p_val = String::from_utf8(_string.to_vec()).expect("Invalid string");
552 *_p_pos += _string.len();
553 *_p_bits = 0; }
555 } else {
556 quote! {
557 let _string = &_p_bytes[*_p_pos..];
558 let _p_val = String::from_utf8(_string.to_vec()).expect("Invalid string");
559 *_p_pos += _string.len();
560 *_p_bits = 0; }
562 }
563 } else {
564 quote! {
565 let _string = _p_val.as_bytes();
566 #dynamic_len
567 _p_bytes.extend_from_slice(_string);
568 *_p_pos += _string.len();
569 *_p_bits = 0;
570 }
571 }
572 }
573 _ => {
574 let (len_specified, dynamic_len) = generate_dynamic_length(
577 read,
578 length_determining_field,
579 dynamic_length_depth,
580 quote! { _p_slice },
581 );
582
583 if read {
584 let read_code = if let Some(variant_by) = variant_by_field {
585 let variant_by = get_reference_accessor(variant_by);
586 quote! {
587 let _p_disc = #variant_by;
588 let _p_val = #field_type::from_bytes_internal_with_disc(_p_disc, _p_slice, &mut _s_pos, _p_bits, _p_config)?;
589 }
590 } else {
591 quote! {
592 let _p_val = #field_type::from_bytes_internal(_p_slice, &mut _s_pos, _p_bits, _p_config)?;
593 }
594 };
595
596 let handle = if len_specified {
597 quote! {
598 #dynamic_len
599 let __s_pos = if *_p_bits != 0 && *_p_pos != 0 {
600 *_p_pos - 1
601 } else {
602 *_p_pos
603 };
604 let _p_slice = &_p_bytes[__s_pos..__s_pos + _p_len];
605 }
606 } else {
607 quote! {
608 let __s_pos = if *_p_bits != 0 && *_p_pos != 0 {
609 *_p_pos - 1
610 } else {
611 *_p_pos
612 };
613 let _p_slice = &_p_bytes[__s_pos..];
614 }
615 };
616
617 quote! {
619 #handle
620 let mut _s_pos = 0;
621 #read_code
622 *_p_pos += _s_pos;
623 }
624 } else {
625 if len_specified {
626 quote! {
627 let mut _s_pos = 0;
628 let mut _vec: Vec<u8> = Vec::new();
629 _p_val.to_bytes_internal(&mut _vec, &mut _s_pos, _p_bits, _p_config)?;
630 let _p_slice = &_vec;
631 #dynamic_len
632 _p_bytes.extend_from_slice(_p_slice);
633 *_p_pos += _s_pos;
634 }
635 } else {
636 quote! {
637 _p_val.to_bytes_internal(_p_bytes, _p_pos, _p_bits, _p_config)?;
638 }
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() {
655 "Option" => {
656 let inner_type = get_inner_type(path).expect("Option missing inner type");
657 let handle = generate_code_for_handling_field(
658 read,
659 inner_type,
660 field_name,
661 bits_count_type,
662 is_dynamic,
663 dynamic_length_depth,
664 length_determining_field,
665 None,
666 variant_by_field,
667 level + 1,
668 );
669 let option_name: syn::Ident = format_ident!("__option_{}", level);
670
671 if let Some(toggled_by) = toggled_by_field {
672 let toggled_by = get_reference_accessor(toggled_by);
673 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 self.#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_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_type,
719 is_dynamic,
720 dynamic_length_depth.map(|d| d - 1),
721 None,
722 None,
723 None,
724 level + 1,
725 );
726
727 let (len_specified, dynamic_len) = generate_dynamic_length(
728 read,
729 length_determining_field,
730 dynamic_length_depth,
731 quote! { _p_val },
732 );
733
734 if read {
735 if len_specified {
736 quote! {
737 #dynamic_len
738 let mut #vec_name = Vec::<#inner_type>::with_capacity(_p_len);
739 for _ in 0.._p_len {
740 #handle
741 #vec_name.push(_p_val);
742 }
743 let _p_val = #vec_name;
744 }
745 } else {
746 quote! {
747 let mut #vec_name = Vec::<#inner_type>::new();
748 while *_p_pos < _p_bytes.len() {
749 #handle
750 #vec_name.push(_p_val);
751 }
752 let _p_val = #vec_name;
753 }
754 }
755 } else {
756 quote! {
757 #dynamic_len
758 for _p_val in _p_val {
759 #handle
760 }
761 }
762 }
763 }
764 "HashMap" => {
765 let (key_type, value_type) =
766 get_two_types(path).expect("Failed to get HashMap types");
767 let handle_key = generate_code_for_handling_field(
768 read,
769 key_type,
770 field_name,
771 bits_count_type,
772 is_dynamic,
773 dynamic_length_depth.map(|d| d - 1),
774 None,
775 None,
776 None,
777 level + 1,
778 );
779
780 let handle_value = generate_code_for_handling_field(
781 read,
782 value_type,
783 field_name,
784 bits_count_type,
785 is_dynamic,
786 dynamic_length_depth.map(|d| d - 1),
787 None,
788 None,
789 None,
790 level + 1,
791 );
792
793 let (len_specified, dynamic_len) = generate_dynamic_length(
794 read,
795 length_determining_field,
796 dynamic_length_depth,
797 quote! { _p_val },
798 );
799
800 if read {
801 if len_specified {
802 quote! {
803 #dynamic_len
804 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::with_capacity(_p_len);
805 for _ in 0.._p_len {
806 let _p_key;
807 #handle_key
808 _p_key = _p_val;
809 let _p_value;
810 #handle_value
811 _p_value = _p_val;
812 _p_map.insert(_p_key, _p_value);
813 }
814 let _p_val = _p_map;
815 }
816 } else {
817 quote! {
818 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::new();
819 while *_p_pos < _p_bytes.len() {
820 let _p_key;
821 #handle_key
822 _p_key = _p_val;
823 let _p_value;
824 #handle_value
825 _p_value = _p_val;
826 _p_map.insert(_p_key, _p_value);
827 }
828 let _p_val = _p_map;
829 }
830 }
831 } else {
832 quote! {
833 #dynamic_len
834 for (key, value) in _p_val {
835 let _p_val = key;
836 #handle_key
837 let _p_val = value;
838 #handle_value
839 }
840 }
841 }
842 }
843 _ => {
844 panic!("Type not implemented")
845 }
846 }
847 } else {
848 panic!("Multi-segment paths are not supported");
849 }
850 }
851 } else if let Type::Array(array) = field_type {
852 let len: usize = if let syn::Expr::Lit(ref arr_len_lit) = array.len {
853 if let Lit::Int(ref lit_int) = arr_len_lit.lit {
854 lit_int
855 .base10_parse()
856 .expect("Failed to parse literal to usize")
857 } else {
858 panic!("Expected an int to determine array length");
859 }
860 } else {
861 panic!("Expected literal to determine array length");
862 };
863
864 let array_type = &array.elem;
867 let handle = generate_code_for_handling_field(
868 read,
869 array_type,
870 field_name,
871 bits_count_type,
872 is_dynamic,
873 dynamic_length_depth,
874 None,
875 None,
876 None,
877 level + 1,
878 );
879
880 let array_name = format_ident!("__val_{}", level);
881
882 if read {
883 quote! {
884 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
885 for _ in 0..#len {
886 #handle;
887 #array_name.push(_p_val);
888 }
889 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
890 }
891 } else {
892 quote! {
893 for _p_val in _p_val {
894 #handle
895 }
896 }
897 }
898 } else {
899 panic!("Field type of '{:?}' not supported", field_name);
900 }
901}
902
903fn generate_error_type(read: bool) -> proc_macro2::TokenStream {
904 if read {
905 quote! { binary_codec::DeserializationError }
906 } else {
907 quote! { binary_codec::SerializationError }
908 }
909}
910
911fn get_string_value_from_attribute(
912 attribute_name: &str,
913 attr: &Attribute,
914 field_name: &syn::Ident,
915) -> String {
916 if let syn::Meta::NameValue(name_value) = &attr.meta {
917 if let syn::Expr::Lit(lit_expr) = &name_value.value {
918 if let Lit::Str(lit_str) = &lit_expr.lit {
919 lit_str.value()
920 } else {
921 panic!(
922 "Expected a string for {} above '{}'",
923 attribute_name, field_name
924 );
925 }
926 } else {
927 panic!(
928 "Expected field name for {} above '{}'",
929 attribute_name, field_name
930 );
931 }
932 } else {
933 panic!(
934 "Expected '{}' {} to specify field name",
935 attribute_name, field_name
936 );
937 }
938}
939
940fn get_int_value_from_attribute(
941 attribute_name: &str,
942 attr: &Attribute,
943 field_name: &syn::Ident,
944) -> i32 {
945 if let syn::Meta::NameValue(name_value) = &attr.meta {
946 if let syn::Expr::Lit(lit_expr) = &name_value.value {
947 if let Lit::Int(lit_str) = &lit_expr.lit {
948 lit_str.base10_parse().expect("Not a valid int value")
949 } else {
950 panic!(
951 "Expected a int for {} above '{}'",
952 attribute_name, field_name
953 );
954 }
955 } else {
956 panic!(
957 "Expected field name for {} above '{}'",
958 attribute_name, field_name
959 );
960 }
961 } else {
962 panic!(
963 "Expected '{}' {} to specify field name",
964 attribute_name, field_name
965 );
966 }
967}
968
969fn get_int_value_from_attribute_2(attr: &Attribute) -> Option<usize> {
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::<usize>() {
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_field_name_from_attribute<'a>(
999 attribute_name: &str,
1000 attr: &Attribute,
1001 fields: &'a Fields,
1002 field_name: &syn::Ident,
1003) -> (&'a syn::Ident, Option<usize>) {
1004 let field_name = get_string_value_from_attribute(attribute_name, attr, field_name);
1005 let mut index: Option<usize> = None;
1006
1007 let field_name = if field_name.contains('.') {
1008 let parts: Vec<&str> = field_name.split('.').collect();
1009 if parts.len() != 2 {
1010 panic!(
1011 "Invalid field name '{}' for attribute '{}', expected 'field_name.index'",
1012 field_name, attribute_name
1013 );
1014 }
1015
1016 index = parts[1].parse().ok();
1017 parts[0].to_string()
1018 } else {
1019 field_name
1020 };
1021
1022 let determining_field = fields
1023 .iter()
1024 .find(|f| f.ident.as_ref().is_some_and(|i| i == &field_name))
1025 .expect(&format!("Referenced field '{}' not found", field_name));
1026
1027 let field = determining_field.ident.as_ref().expect(&format!(
1028 "Referenced field '{}' has no name, which is not supported",
1029 field_name
1030 ));
1031
1032 (field, index)
1033}
1034
1035fn get_inner_type(path: &syn::Path) -> Option<&syn::Type> {
1036 if let Some(PathArguments::AngleBracketed(args)) =
1037 path.segments.last().map(|seg| &seg.arguments)
1038 {
1039 if let Some(arg) = args.args.first() {
1040 if let syn::GenericArgument::Type(inner_type) = arg {
1041 return Some(inner_type);
1042 }
1043 }
1044 }
1045
1046 None
1047}
1048
1049fn get_two_types(path: &syn::Path) -> Option<(&syn::Type, &syn::Type)> {
1050 if let Some(PathArguments::AngleBracketed(args)) =
1051 path.segments.last().map(|seg| &seg.arguments)
1052 {
1053 let mut types = args.args.iter().filter_map(|arg| {
1054 if let syn::GenericArgument::Type(inner_type) = arg {
1055 Some(inner_type)
1056 } else {
1057 None
1058 }
1059 });
1060
1061 if let (Some(t1), Some(t2)) = (types.next(), types.next()) {
1062 return Some((t1, t2));
1063 }
1064 }
1065
1066 None
1067}
1068
1069fn get_reference_accessor(field_reference: FieldReference) -> proc_macro2::TokenStream {
1070 let name = field_reference.0;
1071 if let Some(index) = field_reference.1 {
1072 quote! { #name[#index] }
1073 } else {
1074 quote! { #name }
1075 }
1076}
1077
1078fn generate_dynint(read: bool) -> proc_macro2::TokenStream {
1079 if read {
1080 quote! {
1081 let (_p_dyn, _bytes_read) = binary_codec::dyn_int::read_from_slice(&_p_bytes[*_p_pos..])?;
1082 *_p_pos += _bytes_read;
1083 *_p_bits = 0;
1084 }
1085 } else {
1086 quote! {
1087 let _p_enc = binary_codec::dyn_int::encode(_p_dyn);
1088 _p_bytes.extend_from_slice(&_p_enc);
1089 *_p_pos += _p_enc.len();
1090 *_p_bits = 0;
1091 }
1092 }
1093}
1094
1095fn generate_dynamic_length(
1102 read: bool,
1103 length_determining_field: Option<(&syn::Ident, Option<usize>)>,
1104 dynamic_length_depth: Option<usize>,
1105 item: proc_macro2::TokenStream,
1106) -> (bool, proc_macro2::TokenStream) {
1107 let dynint = generate_dynint(read);
1108 if read {
1109 if let Some(length_determining_field) = length_determining_field {
1110 let length_determining_field = get_reference_accessor(length_determining_field);
1111 (
1112 true,
1113 quote! {
1114 let _p_len = #length_determining_field as usize;
1115 },
1116 )
1117 } else {
1118 if dynamic_length_depth.is_some_and(|v| v > 0) {
1119 (
1120 true,
1121 quote! {
1122 #dynint
1123 let _p_len = _p_dyn as usize;
1124 },
1125 )
1126 } else {
1127 (false, quote! {})
1128 }
1129 }
1130 } else {
1131 if let Some(length_determining_field) = length_determining_field {
1132 let length_determining_field = get_reference_accessor(length_determining_field);
1133 (
1134 true,
1135 quote! {
1136 let expected_len = self.#length_determining_field as usize;
1137 if #item.len() != expected_len {
1138 return Err(binary_codec::SerializationError::UnexpectedLength(expected_len, #item.len()));
1139 }
1140 },
1141 )
1142 } else {
1143 if dynamic_length_depth.is_some_and(|v| v > 0) {
1144 (
1145 true,
1146 quote! {
1147 let _p_dyn = #item.len() as u128;
1148 #dynint
1149 },
1150 )
1151 } else {
1152 (false, quote! {})
1153 }
1154 }
1155 }
1156}