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 if no_disc_prefix {
267 quote! {
269 Self::#var_ident { .. } | Self::#var_ident(_) | Self::#var_ident => 0
270 }
271 } else {
272 match &variant.fields {
273 Fields::Unit => quote! {
274 Self::#var_ident => #disc_value
275 },
276 Fields::Unnamed(_) => quote! {
277 Self::#var_ident(..) => #disc_value
278 },
279 Fields::Named(_) => quote! {
280 Self::#var_ident { .. } => #disc_value
281 },
282 }
283 }
284 });
285
286 let serialization_variants = data_enum.variants.iter().enumerate().map(|(i, variant)| {
288 let var_ident = &variant.ident;
289 let disc_value = i as u8; let fields = &variant.fields;
291
292 let write_disc = if no_disc_prefix {
293 quote! {}
294 } else {
295 quote! {
296 let _p_disc: u8 = #disc_value;
297 binary_codec::fixed_int::FixedInt::write(_p_disc, _p_bytes, _p_config)?;
298 }
299 };
300
301 match fields {
302 Fields::Unit => {
303 if read {
304 quote! {
305 #disc_value => {
306 Ok(Self::#var_ident)
307 }
308 }
309 } else {
310 quote! {
311 Self::#var_ident => {
312 #write_disc
313 }
314 }
315 }
316 }
317 Fields::Unnamed(fields_unnamed) => {
318 let field_count = fields_unnamed.unnamed.len();
319 let idents: Vec<_> = (0..field_count).map(|i| format_ident!("f{}", i)).collect();
320 let ident_refs: Vec<&syn::Ident> = idents.iter().collect();
321 let field_serializations =
322 generate_enum_field_serializations(read, &ident_refs, &fields_unnamed.unnamed);
323 if read {
324 quote! {
325 #disc_value => {
326 #(#field_serializations)*
327 Ok(Self::#var_ident(#(#idents),*))
328 }
329 }
330 } else {
331 quote! {
332 Self::#var_ident(#(#idents),*) => {
333 #write_disc
334 #(#field_serializations)*
335 }
336 }
337 }
338 }
339 Fields::Named(fields_named) => {
340 let field_idents: Vec<_> = fields_named
341 .named
342 .iter()
343 .map(|f| f.ident.as_ref().unwrap())
344 .collect();
345
346 let field_serializations =
347 generate_enum_field_serializations(read, &field_idents, &fields_named.named);
348
349 if read {
350 quote! {
351 #disc_value => {
352 #(#field_serializations)*
353 Ok(Self::#var_ident { #(#field_idents),* })
354 }
355 }
356 } else {
357 quote! {
358 Self::#var_ident { #(#field_idents),* } => {
359 #write_disc
360 #(#field_serializations)*
361 }
362 }
363 }
364 }
365 }
366 });
367
368 if read {
369 quote! {
370 impl binary_codec::BinaryDeserializer for #enum_name {
371 fn from_bytes(bytes: &[u8], config: Option<&mut binary_codec::SerializerConfig>) -> Result<Self, #error_type> {
372 let mut _new_config = binary_codec::SerializerConfig::new();
373 let _p_config = config.unwrap_or(&mut _new_config);
374 let _p_bytes = bytes;
375
376 let _p_disc = if let Some(disc) = _p_config.discriminator.take() {
377 disc
378 } else {
379 binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?
380 };
381
382 match _p_disc {
383 #(#serialization_variants,)*
384 _ => Err(#error_type::UnknownDiscriminant(_p_disc)),
385 }
386 }
387 }
388 }
389 .into()
390 } else {
391 quote! {
392 impl binary_codec::BinarySerializer for #enum_name {
393 fn to_bytes(&self, config: Option<&mut binary_codec::SerializerConfig>) -> Result<Vec<u8>, #error_type> {
394 let mut bytes = Vec::new();
395 Self::write_bytes(self, &mut bytes, config)?;
396 Ok(bytes)
397 }
398
399 fn write_bytes(&self, buffer: &mut Vec<u8>, config: Option<&mut binary_codec::SerializerConfig>) -> Result<(), #error_type> {
400 let mut _new_config = binary_codec::SerializerConfig::new();
401 let _p_config = config.unwrap_or(&mut _new_config);
402 let _p_bytes = buffer;
403
404 match self {
405 #(#serialization_variants)*
406 }
407
408 Ok(())
409 }
410 }
411
412 impl #enum_name {
413 fn get_discriminator(&self) -> u8 {
414 match self {
415 #(#disc_variants,)*
416 }
417 }
418 }
419 }
420 .into()
421 }
422}
423
424fn generate_enum_field_serializations(
425 read: bool,
426 idents: &Vec<&syn::Ident>,
427 fields: &Punctuated<syn::Field, Comma>,
428) -> Vec<proc_macro2::TokenStream> {
429 let field_serializations = fields.iter().enumerate().map(|(i, f)| {
430 let field_type = &f.ty;
431 let field_ident = &idents[i];
432
433 let handle_field = generate_code_for_handling_field(
434 read,
435 field_type,
436 field_ident,
437 None,
438 None,
439 None,
440 None,
441 false,
442 false,
443 false,
444 false,
445 0,
446 );
447
448 if read {
449 quote! {
450 #handle_field
451 let #field_ident = _p_val;
452 }
453 } else {
454 quote! {
455 let _p_val = #field_ident;
456 #handle_field
457 }
458 }
459 });
460 field_serializations.collect()
461}
462
463fn generate_code_for_handling_field(
464 read: bool,
465 field_type: &Type,
466 field_name: &syn::Ident,
467 bits_count: Option<u8>,
468 toggled_by: Option<String>,
469 variant_by: Option<String>,
470 length_by: Option<String>,
471 is_dynamic_int: bool,
472 has_dynamic_length: bool,
473 key_dyn_length: bool,
474 val_dyn_length: bool,
475 level: usize,
476) -> proc_macro2::TokenStream {
477 if let Type::Path(path) = field_type {
478 let path = &path.path;
479
480 if let Some(ident) = path.get_ident() {
481 let ident_name = ident.to_string();
482
483 match ident_name.as_str() {
485 "bool" => {
486 if read {
487 quote! { let _p_val = binary_codec::dynamics::read_bool(_p_bytes, _p_config)?; }
488 } else {
489 quote! { binary_codec::dynamics::write_bool(*_p_val, _p_bytes, _p_config)?; }
490 }
491 }
492 "i8" => {
493 if let Some(bits_count) = bits_count.as_ref() {
494 if *bits_count < 1 || *bits_count > 7 {
495 panic!("Bits count should be between 1 and 7");
496 }
497
498 if read {
499 quote! { let _p_val = binary_codec::dynamics::read_small_dynamic_signed(_p_bytes, _p_config, #bits_count)?; }
500 } else {
501 quote! { binary_codec::dynamics::write_small_dynamic_signed(*_p_val, _p_bytes, _p_config, #bits_count)?; }
502 }
503 } else {
504 if read {
505 quote! {
506 let _p_val = binary_codec::dynamics::read_zigzag(_p_bytes, _p_config)?;
507 }
508 } else {
509 quote! {
510 binary_codec::dynamics::write_zigzag(*_p_val, _p_bytes, _p_config)?;
511 }
512 }
513 }
514 }
515 "u8" => {
516 if let Some(bits_count) = bits_count.as_ref() {
517 if *bits_count < 1 || *bits_count > 7 {
518 panic!("Bits count should be between 1 and 7");
519 }
520
521 if read {
522 quote! { let _p_val = binary_codec::dynamics::read_small_dynamic_unsigned(_p_bytes, _p_config, #bits_count)?; }
523 } else {
524 quote! { binary_codec::dynamics::write_small_dynamic_unsigned(*_p_val, _p_bytes, _p_config, #bits_count)?; }
525 }
526 } else {
527 if read {
528 quote! {
529 let _p_val = binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?;
530 }
531 } else {
532 quote! {
533 binary_codec::fixed_int::FixedInt::write(*_p_val, _p_bytes, _p_config)?;
534 }
535 }
536 }
537 }
538 "u16" | "u32" | "u64" | "u128" => {
539 if is_dynamic_int {
540 let dynint: proc_macro2::TokenStream = generate_dynint(read);
541 if read {
542 quote! {
543 #dynint
544 let _p_val = _p_dyn as #ident;
545 }
546 } else {
547 quote! {
548 let _p_dyn = *_p_val as u128;
549 #dynint
550 }
551 }
552 } else {
553 if read {
554 quote! {
555 let _p_val = binary_codec::fixed_int::FixedInt::read(_p_bytes, _p_config)?;
556 }
557 } else {
558 quote! {
559 binary_codec::fixed_int::FixedInt::write(*_p_val, _p_bytes, _p_config)?;
560 }
561 }
562 }
563 }
564 "i16" | "i32" | "i64" | "i128" => {
565 if is_dynamic_int {
566 let dynint: proc_macro2::TokenStream = generate_dynint(read);
567 if read {
568 quote! {
569 #dynint
570 let _p_val: #ident = binary_codec::fixed_int::ZigZag::to_signed(_p_dyn);
571 }
572 } else {
573 quote! {
574 let _p_dyn = binary_codec::fixed_int::ZigZag::to_unsigned(*_p_val) as u128;
575 #dynint
576 }
577 }
578 } else {
579 if read {
580 quote! {
581 let _p_val = binary_codec::fixed_int::read_zigzag(_p_bytes, _p_config)?;
582 }
583 } else {
584 quote! {
585 binary_codec::fixed_int::write_zigzag(*_p_val, _p_bytes, _p_config)?;
586 }
587 }
588 }
589 }
590 "String" => {
591 let size_key = generate_size_key(length_by, has_dynamic_length).1;
592
593 if read {
594 quote! {
595 let _p_val = binary_codec::variable::read_string(_p_bytes, #size_key, _p_config)?;
596 }
597 } else {
598 quote! {
599 binary_codec::variable::write_string(_p_val, #size_key, _p_bytes, _p_config)?;
600 }
601 }
602 }
603 _ => {
604 let size_key = generate_size_key(length_by, has_dynamic_length).1;
605
606 let variant_code = if variant_by.is_some() {
607 quote! {
608 _p_config.discriminator = _p_config.get_variant(#variant_by);
609 }
610 } else { quote! {} };
611
612 if read {
613 quote! {
614 #variant_code
615 let _p_val = binary_codec::variable::read_object(_p_bytes, #size_key, _p_config)?;
616 }
617 } else {
618 quote! {
619 #variant_code
620 binary_codec::variable::write_object(_p_val, #size_key, _p_bytes, _p_config)?;
621 }
622 }
623 }
624 }
625 } else {
626 if path.segments.len() == 1 {
628 let ident = &path.segments[0].ident;
629 let ident_name = ident.to_string();
630
631 match ident_name.as_ref() {
632 "Option" => {
633 let inner_type = get_inner_type(path).expect("Option missing inner type");
634 let handle = generate_code_for_handling_field(
635 read,
636 inner_type,
637 field_name,
638 bits_count,
639 None,
640 variant_by,
641 length_by,
642 is_dynamic_int,
643 has_dynamic_length,
644 key_dyn_length,
645 val_dyn_length,
646 level + 1,
647 );
648 let option_name: syn::Ident = format_ident!("__option_{}", level);
649
650 if let Some(toggled_by) = toggled_by {
651 let toggled_by = quote! {
653 _p_config.get_toggle(#toggled_by).unwrap_or(false)
654 };
655
656 if read {
657 quote! {
658 let mut #option_name: Option<#inner_type> = None;
659 if #toggled_by {
660 #handle
661 #option_name = Some(_p_val);
662 }
663 let _p_val = #option_name;
664 }
665 } else {
666 quote! {
667 if #toggled_by {
668 let _p_val = _p_val.as_ref().expect("Expected Some value, because toggled_by field is true");
669 #handle
670 }
671 }
672 }
673 } else {
674 if read {
676 quote! {
677 let mut #option_name: Option<#inner_type> = None;
678 if _p_config.next_reset_bits_pos() < _p_bytes.len() {
679 #handle
680 #option_name = Some(_p_val);
681 }
682 let _p_val = #option_name;
683 }
684 } else {
685 quote! {
686 if let Some(_p_val) = _p_val.as_ref() {
687 #handle
688 }
689 }
690 }
691 }
692 }
693 "Vec" => {
694 let vec_name = format_ident!("__val_{}", level);
695 let inner_type = get_inner_type(path).expect("Vec missing inner type");
696 let handle = generate_code_for_handling_field(
697 read,
698 inner_type,
699 field_name,
700 bits_count,
701 None,
702 None,
703 None,
704 is_dynamic_int,
705 val_dyn_length,
706 false,
707 false,
708 level + 1,
709 );
710
711 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
712
713 let write_code = quote! {
714 for _p_val in _p_val {
715 #handle
716 }
717 };
718
719 if has_size {
720 if read {
721 quote! {
722 let _p_len = binary_codec::utils::get_read_size(_p_bytes, #size_key, _p_config)?;
723 let mut #vec_name = Vec::<#inner_type>::with_capacity(_p_len);
724 for _ in 0.._p_len {
725 #handle
726 #vec_name.push(_p_val);
727 }
728 let _p_val = #vec_name;
729 }
730 } else {
731 quote! {
732 let _p_len = _p_val.len();
733 binary_codec::utils::write_size(_p_len, #size_key, _p_bytes, _p_config)?;
734 #write_code
735 }
736 }
737 } else {
738 if read {
739 quote! {
740 let mut #vec_name = Vec::<#inner_type>::new();
741 while _p_config.next_reset_bits_pos() < _p_bytes.len() {
742 #handle
743 #vec_name.push(_p_val);
744 }
745 let _p_val = #vec_name;
746 }
747 } else {
748 quote! {
749 #write_code
750 }
751 }
752 }
753 }
754 "HashMap" => {
755 let (key_type, value_type) =
756 get_two_types(path).expect("Failed to get HashMap types");
757
758 let handle_key = generate_code_for_handling_field(
759 read,
760 key_type,
761 field_name,
762 None,
763 None,
764 None,
765 None,
766 is_dynamic_int,
767 key_dyn_length,
768 false,
769 false,
770 level + 1,
771 );
772
773 let handle_value = generate_code_for_handling_field(
774 read,
775 value_type,
776 field_name,
777 None,
778 None,
779 None,
780 None,
781 is_dynamic_int,
782 val_dyn_length,
783 false,
784 false,
785 level + 1,
786 );
787
788 let (has_size, size_key) = generate_size_key(length_by, has_dynamic_length);
789
790 let write_code = quote! {
791 for (key, value) in _p_val {
792 let _p_val = key;
793 #handle_key
794 let _p_val = value;
795 #handle_value
796 }
797 };
798
799 if read {
800 if has_size {
801 quote! {
802 let _p_len = binary_codec::utils::get_read_size(_p_bytes, #size_key, _p_config)?;
803 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::with_capacity(_p_len);
804 for _ in 0.._p_len {
805 let _p_key;
806 #handle_key
807 _p_key = _p_val;
808 let _p_value;
809 #handle_value
810 _p_value = _p_val;
811 _p_map.insert(_p_key, _p_value);
812 }
813 let _p_val = _p_map;
814 }
815 } else {
816 quote! {
817 let mut _p_map = std::collections::HashMap::<#key_type, #value_type>::new();
818 while _p_config.next_reset_bits_pos() < _p_bytes.len() {
819 let _p_key;
820 #handle_key
821 _p_key = _p_val;
822 let _p_value;
823 #handle_value
824 _p_value = _p_val;
825 _p_map.insert(_p_key, _p_value);
826 }
827 let _p_val = _p_map;
828 }
829 }
830 } else {
831 if has_size {
832 quote! {
833 let _p_len = _p_val.len();
834 binary_codec::utils::write_size(_p_len, #size_key, _p_bytes, _p_config)?;
835 #write_code
836 }
837 } else {
838 quote! {
839 #write_code
840 }
841 }
842 }
843 }
844 _ => {
845 panic!("Type not implemented")
846 }
847 }
848 } else {
849 panic!("Multi-segment paths are not supported");
850 }
851 }
852 } else if let Type::Array(array) = field_type {
853 let len: usize = if let syn::Expr::Lit(ref arr_len_lit) = array.len {
854 if let Lit::Int(ref lit_int) = arr_len_lit.lit {
855 lit_int
856 .base10_parse()
857 .expect("Failed to parse literal to usize")
858 } else {
859 panic!("Expected an int to determine array length");
860 }
861 } else {
862 panic!("Expected literal to determine array length");
863 };
864
865 let array_type = &array.elem;
866 let handle = generate_code_for_handling_field(
867 read,
868 array_type,
869 field_name,
870 bits_count,
871 None,
872 None,
873 None,
874 is_dynamic_int,
875 val_dyn_length,
876 false,
877 false,
878 level + 1,
879 );
880
881 let array_name = format_ident!("__val_{}", level);
882
883 if read {
884 quote! {
885 let mut #array_name = Vec::<#array_type>::with_capacity(#len);
886 for _ in 0..#len {
887 #handle;
888 #array_name.push(_p_val);
889 }
890 let _p_val = TryInto::<[#array_type; #len]>::try_into(#array_name).expect("Failed to convert Vec to array");
891 }
892 } else {
893 quote! {
894 for _p_val in _p_val {
895 #handle
896 }
897 }
898 }
899 } else {
900 panic!("Field type of '{:?}' not supported", field_name);
901 }
902}
903
904fn generate_error_type(read: bool) -> proc_macro2::TokenStream {
905 if read {
906 quote! { binary_codec::DeserializationError }
907 } else {
908 quote! { binary_codec::SerializationError }
909 }
910}
911
912fn generate_size_key(length_by: Option<String>, has_dynamic_length: bool) -> (bool, proc_macro2::TokenStream) {
913 if let Some(length_by) = length_by.as_ref() {
914 (true, quote! { Some(#length_by) })
915 } else if has_dynamic_length {
916 (true, quote! { Some("__dynamic") })
917 } else {
918 (false, quote! { None })
919 }
920}
921
922fn get_string_value_from_attribute(
923 attr: &Attribute
924) -> Option<String> {
925 match &attr.meta {
926 syn::Meta::Path(_) => {
927 None
928 }
929 syn::Meta::List(list_value) => {
930 for token in list_value.tokens.clone().into_iter() {
932 if let proc_macro2::TokenTree::Literal(lit) = token {
933 return Some(lit.to_string().trim_matches('"').to_string());
934 }
935 }
936
937 None
938 }
939 syn::Meta::NameValue(name_value) => {
940 if let syn::Expr::Lit(lit_expr) = &name_value.value {
941 if let Lit::Str(lit_str) = &lit_expr.lit {
942 return Some(lit_str.value());
943 }
944 }
945
946 None
947 }
948 }
949}
950
951fn get_int_value_from_attribute(attr: &Attribute) -> Option<i32> {
952 match &attr.meta {
953 syn::Meta::Path(_) => {
954 None
955 }
956 syn::Meta::List(list_value) => {
957 for token in list_value.tokens.clone().into_iter() {
959 if let proc_macro2::TokenTree::Literal(lit) = token {
960 if let Ok(val) = lit.to_string().parse::<i32>() {
961 return Some(val);
962 }
963 }
964 }
965
966 None
967 }
968 syn::Meta::NameValue(name_value) => {
969 if let syn::Expr::Lit(lit_expr) = &name_value.value {
970 if let Lit::Int(lit_int) = &lit_expr.lit {
971 return Some(lit_int.base10_parse().expect("Not a valid int value"));
972 }
973 }
974
975 None
976 }
977 }
978}
979
980fn get_inner_type(path: &syn::Path) -> Option<&syn::Type> {
981 if let Some(PathArguments::AngleBracketed(args)) =
982 path.segments.last().map(|seg| &seg.arguments)
983 {
984 if let Some(arg) = args.args.first() {
985 if let syn::GenericArgument::Type(inner_type) = arg {
986 return Some(inner_type);
987 }
988 }
989 }
990
991 None
992}
993
994fn get_two_types(path: &syn::Path) -> Option<(&syn::Type, &syn::Type)> {
995 if let Some(PathArguments::AngleBracketed(args)) =
996 path.segments.last().map(|seg| &seg.arguments)
997 {
998 let mut types = args.args.iter().filter_map(|arg| {
999 if let syn::GenericArgument::Type(inner_type) = arg {
1000 Some(inner_type)
1001 } else {
1002 None
1003 }
1004 });
1005
1006 if let (Some(t1), Some(t2)) = (types.next(), types.next()) {
1007 return Some((t1, t2));
1008 }
1009 }
1010
1011 None
1012}
1013
1014fn generate_dynint(read: bool) -> proc_macro2::TokenStream {
1015 if read {
1016 quote! {
1017 let _p_dyn = binary_codec::dyn_int::read_dynint(_p_bytes, _p_config)?;
1018 }
1019 } else {
1020 quote! {
1021 binary_codec::dyn_int::write_dynint(_p_dyn, _p_bytes, _p_config)?;
1022 }
1023 }
1024}