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