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 binary_codec::BinaryDeserializer for #struct_name {
205 fn from_bytes(bytes: &[u8], config: Option<&mut binary_codec::SerializerConfig>) -> Result<Self, #error_type> {
206 let mut _new_config = binary_codec::SerializerConfig::new();
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 binary_codec::BinarySerializer for #struct_name {
222 fn to_bytes(&self, config: Option<&mut binary_codec::SerializerConfig>) -> 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>) -> Result<(), #error_type> {
229 let mut _new_config = binary_codec::SerializerConfig::new();
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 binary_codec::BinaryDeserializer for #enum_name {
364 fn from_bytes(bytes: &[u8], config: Option<&mut binary_codec::SerializerConfig>) -> Result<Self, #error_type> {
365 let mut _new_config = binary_codec::SerializerConfig::new();
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 binary_codec::BinarySerializer for #enum_name {
386 fn to_bytes(&self, config: Option<&mut binary_codec::SerializerConfig>) -> 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>) -> Result<(), #error_type> {
393 let mut _new_config = binary_codec::SerializerConfig::new();
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 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 handle_field = generate_code_for_handling_field(
427 read,
428 field_type,
429 field_ident,
430 None,
431 None,
432 None,
433 None,
434 false,
435 false,
436 false,
437 false,
438 0,
439 );
440
441 if read {
442 quote! {
443 #handle_field
444 let #field_ident = _p_val;
445 }
446 } else {
447 quote! {
448 let _p_val = #field_ident;
449 #handle_field
450 }
451 }
452 });
453 field_serializations.collect()
454}
455
456fn generate_code_for_handling_field(
457 read: bool,
458 field_type: &Type,
459 field_name: &syn::Ident,
460 bits_count: Option<u8>,
461 toggled_by: Option<String>,
462 variant_by: Option<String>,
463 length_by: Option<String>,
464 is_dynamic_int: bool,
465 has_dynamic_length: bool,
466 key_dyn_length: bool,
467 val_dyn_length: bool,
468 level: usize,
469) -> proc_macro2::TokenStream {
470 if let Type::Path(path) = field_type {
471 let path = &path.path;
472
473 if let Some(ident) = path.get_ident() {
474 let ident_name = ident.to_string();
475
476 match ident_name.as_str() {
478 "bool" => {
479 if read {
480 quote! { let _p_val = binary_codec::dynamics::read_bool(_p_bytes, _p_config)?; }
481 } else {
482 quote! { binary_codec::dynamics::write_bool(*_p_val, _p_bytes, _p_config)?; }
483 }
484 }
485 "i8" => {
486 if let Some(bits_count) = bits_count.as_ref() {
487 if *bits_count < 1 || *bits_count > 7 {
488 panic!("Bits count should be between 1 and 7");
489 }
490
491 if read {
492 quote! { let _p_val = binary_codec::dynamics::read_small_dynamic_signed(_p_bytes, _p_config, #bits_count)?; }
493 } else {
494 quote! { binary_codec::dynamics::write_small_dynamic_signed(*_p_val, _p_bytes, _p_config, #bits_count)?; }
495 }
496 } else {
497 if read {
498 quote! {
499 let _p_val = binary_codec::dynamics::read_zigzag(_p_bytes, _p_config)?;
500 }
501 } else {
502 quote! {
503 binary_codec::dynamics::write_zigzag(*_p_val, _p_bytes, _p_config)?;
504 }
505 }
506 }
507 }
508 "u8" => {
509 if let Some(bits_count) = bits_count.as_ref() {
510 if *bits_count < 1 || *bits_count > 7 {
511 panic!("Bits count should be between 1 and 7");
512 }
513
514 if read {
515 quote! { let _p_val = binary_codec::dynamics::read_small_dynamic_unsigned(_p_bytes, _p_config, #bits_count)?; }
516 } else {
517 quote! { binary_codec::dynamics::write_small_dynamic_unsigned(*_p_val, _p_bytes, _p_config, #bits_count)?; }
518 }
519 } else {
520 if read {
521 quote! {
522 let _p_val = binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?;
523 }
524 } else {
525 quote! {
526 binary_codec::fixed_int::FixedInt::write(*_p_val, _p_bytes, _p_config)?;
527 }
528 }
529 }
530 }
531 "u16" | "u32" | "u64" | "u128" => {
532 if is_dynamic_int {
533 let dynint: proc_macro2::TokenStream = generate_dynint(read);
534 if read {
535 quote! {
536 #dynint
537 let _p_val = _p_dyn as #ident;
538 }
539 } else {
540 quote! {
541 let _p_dyn = *_p_val as u128;
542 #dynint
543 }
544 }
545 } else {
546 if read {
547 quote! {
548 let _p_val = binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?;
549 }
550 } else {
551 quote! {
552 binary_codec::fixed_int::FixedInt::write(*_p_val, _p_bytes, _p_config)?;
553 }
554 }
555 }
556 }
557 "i16" | "i32" | "i64" | "i128" => {
558 if is_dynamic_int {
559 let dynint: proc_macro2::TokenStream = generate_dynint(read);
560 if read {
561 quote! {
562 #dynint
563 let _p_val: #ident = binary_codec::fixed_int::ZigZag::to_signed(_p_dyn);
564 }
565 } else {
566 quote! {
567 let _p_dyn = binary_codec::fixed_int::ZigZag::to_unsigned(*_p_val) as u128;
568 #dynint
569 }
570 }
571 } else {
572 if read {
573 quote! {
574 let _p_val = binary_codec::fixed_int::read_zigzag(_p_bytes, _p_config)?;
575 }
576 } else {
577 quote! {
578 binary_codec::fixed_int::write_zigzag(*_p_val, _p_bytes, _p_config)?;
579 }
580 }
581 }
582 }
583 "String" => {
584 let size_key = generate_size_key(length_by, has_dynamic_length).1;
585
586 if read {
587 quote! {
588 let _p_val = binary_codec::variable::read_string(_p_bytes, #size_key, _p_config)?;
589 }
590 } else {
591 quote! {
592 binary_codec::variable::write_string(_p_val, #size_key, _p_bytes, _p_config)?;
593 }
594 }
595 }
596 _ => {
597 let size_key = generate_size_key(length_by, has_dynamic_length).1;
598
599 let variant_code = if variant_by.is_some() {
600 quote! {
601 _p_config.discriminator = _p_config.get_variant(#variant_by);
602 }
603 } else { quote! {} };
604
605 if read {
606 quote! {
607 #variant_code
608 let _p_val = binary_codec::variable::read_object(_p_bytes, #size_key, _p_config)?;
609 }
610 } else {
611 quote! {
612 #variant_code
613 binary_codec::variable::write_object(_p_val, #size_key, _p_bytes, _p_config)?;
614 }
615 }
616 }
617 }
618 } else {
619 if path.segments.len() == 1 {
621 let ident = &path.segments[0].ident;
622 let ident_name = ident.to_string();
623
624 match ident_name.as_ref() {
625 "Option" => {
626 let inner_type = get_inner_type(path).expect("Option missing inner type");
627 let handle = generate_code_for_handling_field(
628 read,
629 inner_type,
630 field_name,
631 bits_count,
632 None,
633 variant_by,
634 length_by,
635 is_dynamic_int,
636 has_dynamic_length,
637 key_dyn_length,
638 val_dyn_length,
639 level + 1,
640 );
641 let option_name: syn::Ident = format_ident!("__option_{}", level);
642
643 if let Some(toggled_by) = toggled_by {
644 let toggled_by = quote! {
646 _p_config.get_toggle(#toggled_by).unwrap_or(false)
647 };
648
649 if read {
650 quote! {
651 let mut #option_name: Option<#inner_type> = None;
652 if #toggled_by {
653 #handle
654 #option_name = Some(_p_val);
655 }
656 let _p_val = #option_name;
657 }
658 } else {
659 quote! {
660 if #toggled_by {
661 let _p_val = _p_val.as_ref().expect("Expected Some value, because toggled_by field is true");
662 #handle
663 }
664 }
665 }
666 } else {
667 if read {
669 quote! {
670 let mut #option_name: Option<#inner_type> = None;
671 if _p_config.next_reset_bits_pos() < _p_bytes.len() {
672 #handle
673 #option_name = Some(_p_val);
674 }
675 let _p_val = #option_name;
676 }
677 } else {
678 quote! {
679 if let Some(_p_val) = _p_val.as_ref() {
680 #handle
681 }
682 }
683 }
684 }
685 }
686 "Vec" => {
687 let vec_name = format_ident!("__val_{}", level);
688 let inner_type = get_inner_type(path).expect("Vec missing inner type");
689 let handle = generate_code_for_handling_field(
690 read,
691 inner_type,
692 field_name,
693 bits_count,
694 None,
695 None,
696 None,
697 is_dynamic_int,
698 val_dyn_length,
699 false,
700 false,
701 level + 1,
702 );
703
704 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
705
706 let write_code = quote! {
707 for _p_val in _p_val {
708 #handle
709 }
710 };
711
712 if has_size {
713 if read {
714 quote! {
715 let _p_len = binary_codec::utils::get_read_size(_p_bytes, #size_key, _p_config)?;
716 let mut #vec_name = Vec::<#inner_type>::with_capacity(_p_len);
717 for _ in 0.._p_len {
718 #handle
719 #vec_name.push(_p_val);
720 }
721 let _p_val = #vec_name;
722 }
723 } else {
724 quote! {
725 let _p_len = _p_val.len();
726 binary_codec::utils::write_size(_p_len, #size_key, _p_bytes, _p_config)?;
727 #write_code
728 }
729 }
730 } else {
731 if read {
732 quote! {
733 let mut #vec_name = Vec::<#inner_type>::new();
734 while _p_config.next_reset_bits_pos() < _p_bytes.len() {
735 #handle
736 #vec_name.push(_p_val);
737 }
738 let _p_val = #vec_name;
739 }
740 } else {
741 quote! {
742 #write_code
743 }
744 }
745 }
746 }
747 "HashMap" => {
748 let (key_type, value_type) =
749 get_two_types(path).expect("Failed to get HashMap types");
750
751 let handle_key = generate_code_for_handling_field(
752 read,
753 key_type,
754 field_name,
755 None,
756 None,
757 None,
758 None,
759 is_dynamic_int,
760 key_dyn_length,
761 false,
762 false,
763 level + 1,
764 );
765
766 let handle_value = generate_code_for_handling_field(
767 read,
768 value_type,
769 field_name,
770 None,
771 None,
772 None,
773 None,
774 is_dynamic_int,
775 val_dyn_length,
776 false,
777 false,
778 level + 1,
779 );
780
781 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
782
783 let write_code = quote! {
784 for (key, value) in _p_val {
785 let _p_val = key;
786 #handle_key
787 let _p_val = value;
788 #handle_value
789 }
790 };
791
792 if read {
793 if has_size {
794 quote! {
795 let _p_len = binary_codec::utils::get_read_size(_p_bytes, #size_key, _p_config)?;
796 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::with_capacity(_p_len);
797 for _ in 0.._p_len {
798 let _p_key;
799 #handle_key
800 _p_key = _p_val;
801 let _p_value;
802 #handle_value
803 _p_value = _p_val;
804 _p_map.insert(_p_key, _p_value);
805 }
806 let _p_val = _p_map;
807 }
808 } else {
809 quote! {
810 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::new();
811 while _p_config.next_reset_bits_pos() < _p_bytes.len() {
812 let _p_key;
813 #handle_key
814 _p_key = _p_val;
815 let _p_value;
816 #handle_value
817 _p_value = _p_val;
818 _p_map.insert(_p_key, _p_value);
819 }
820 let _p_val = _p_map;
821 }
822 }
823 } else {
824 if has_size {
825 quote! {
826 let _p_len = _p_val.len();
827 binary_codec::utils::write_size(_p_len, #size_key, _p_bytes, _p_config)?;
828 #write_code
829 }
830 } else {
831 quote! {
832 #write_code
833 }
834 }
835 }
836 }
837 _ => {
838 panic!("Type not implemented")
839 }
840 }
841 } else {
842 panic!("Multi-segment paths are not supported");
843 }
844 }
845 } else if let Type::Array(array) = field_type {
846 let len: usize = if let syn::Expr::Lit(ref arr_len_lit) = array.len {
847 if let Lit::Int(ref lit_int) = arr_len_lit.lit {
848 lit_int
849 .base10_parse()
850 .expect("Failed to parse literal to usize")
851 } else {
852 panic!("Expected an int to determine array length");
853 }
854 } else {
855 panic!("Expected literal to determine array length");
856 };
857
858 let array_type = &array.elem;
859 let handle = generate_code_for_handling_field(
860 read,
861 array_type,
862 field_name,
863 bits_count,
864 None,
865 None,
866 None,
867 is_dynamic_int,
868 val_dyn_length,
869 false,
870 false,
871 level + 1,
872 );
873
874 let array_name = format_ident!("__val_{}", level);
875
876 if read {
877 quote! {
878 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
879 for _ in 0..#len {
880 #handle;
881 #array_name.push(_p_val);
882 }
883 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
884 }
885 } else {
886 quote! {
887 for _p_val in _p_val {
888 #handle
889 }
890 }
891 }
892 } else {
893 panic!("Field type of '{:?}' not supported", field_name);
894 }
895}
896
897fn generate_error_type(read: bool) -> proc_macro2::TokenStream {
898 if read {
899 quote! { binary_codec::DeserializationError }
900 } else {
901 quote! { binary_codec::SerializationError }
902 }
903}
904
905fn generate_size_key(length_by: Option<String>, has_dynamic_length: bool) -> (bool, proc_macro2::TokenStream) {
906 if let Some(length_by) = length_by.as_ref() {
907 (true, quote! { Some(#length_by) })
908 } else if has_dynamic_length {
909 (true, quote! { Some("__dynamic") })
910 } else {
911 (false, quote! { None })
912 }
913}
914
915fn get_string_value_from_attribute(
916 attr: &Attribute
917) -> Option<String> {
918 match &attr.meta {
919 syn::Meta::Path(_) => {
920 None
921 }
922 syn::Meta::List(list_value) => {
923 for token in list_value.tokens.clone().into_iter() {
925 if let proc_macro2::TokenTree::Literal(lit) = token {
926 return Some(lit.to_string().trim_matches('"').to_string());
927 }
928 }
929
930 None
931 }
932 syn::Meta::NameValue(name_value) => {
933 if let syn::Expr::Lit(lit_expr) = &name_value.value {
934 if let Lit::Str(lit_str) = &lit_expr.lit {
935 return Some(lit_str.value());
936 }
937 }
938
939 None
940 }
941 }
942}
943
944fn get_int_value_from_attribute(attr: &Attribute) -> Option<i32> {
945 match &attr.meta {
946 syn::Meta::Path(_) => {
947 None
948 }
949 syn::Meta::List(list_value) => {
950 for token in list_value.tokens.clone().into_iter() {
952 if let proc_macro2::TokenTree::Literal(lit) = token {
953 if let Ok(val) = lit.to_string().parse::<i32>() {
954 return Some(val);
955 }
956 }
957 }
958
959 None
960 }
961 syn::Meta::NameValue(name_value) => {
962 if let syn::Expr::Lit(lit_expr) = &name_value.value {
963 if let Lit::Int(lit_int) = &lit_expr.lit {
964 return Some(lit_int.base10_parse().expect("Not a valid int value"));
965 }
966 }
967
968 None
969 }
970 }
971}
972
973fn get_inner_type(path: &syn::Path) -> Option<&syn::Type> {
974 if let Some(PathArguments::AngleBracketed(args)) =
975 path.segments.last().map(|seg| &seg.arguments)
976 {
977 if let Some(arg) = args.args.first() {
978 if let syn::GenericArgument::Type(inner_type) = arg {
979 return Some(inner_type);
980 }
981 }
982 }
983
984 None
985}
986
987fn get_two_types(path: &syn::Path) -> Option<(&syn::Type, &syn::Type)> {
988 if let Some(PathArguments::AngleBracketed(args)) =
989 path.segments.last().map(|seg| &seg.arguments)
990 {
991 let mut types = args.args.iter().filter_map(|arg| {
992 if let syn::GenericArgument::Type(inner_type) = arg {
993 Some(inner_type)
994 } else {
995 None
996 }
997 });
998
999 if let (Some(t1), Some(t2)) = (types.next(), types.next()) {
1000 return Some((t1, t2));
1001 }
1002 }
1003
1004 None
1005}
1006
1007fn generate_dynint(read: bool) -> proc_macro2::TokenStream {
1008 if read {
1009 quote! {
1010 let _p_dyn = binary_codec::dyn_int::read_dynint(_p_bytes, _p_config)?;
1011 }
1012 } else {
1013 quote! {
1014 binary_codec::dyn_int::write_dynint(_p_dyn, _p_bytes, _p_config)?;
1015 }
1016 }
1017}