1extern crate proc_macro;
2
3use crc::{Crc, CRC_64_ECMA_182};
4use itertools::izip;
5use proc_macro::TokenStream;
6use proc_macro2::Span;
7use quote::quote;
8use std::collections::{HashMap, HashSet};
9use syn::{
10 parse_macro_input, Attribute, Data, DeriveInput, Fields, GenericArgument, Ident, PathArguments,
11 Type,
12};
13
14const CRC64: Crc<u64> = Crc::<u64>::new(&CRC_64_ECMA_182);
16
17fn calculate_id_from_name(name: &str) -> u64 {
31 let crc64_hash = CRC64.checksum(name.as_bytes());
32 if crc64_hash == 0 {
34 u64::MAX
35 } else {
36 crc64_hash
37 }
38}
39
40fn has_default_attribute(attrs: &[Attribute]) -> bool {
42 attrs.iter().any(|attr| attr.path().is_ident("default"))
43}
44
45#[derive(Debug, Clone)]
59#[allow(dead_code)] struct FieldAttributes {
61 id: u64,
62 default: bool,
63 skip_encode: bool,
64 skip_decode: bool,
65 skip_default: bool,
66 rename: Option<String>,
67}
68
69fn get_field_attributes(attrs: &[Attribute], field_name: &str) -> FieldAttributes {
95 let mut id = None;
96 let mut default = false;
97 let mut skip_encode = false;
98 let mut skip_decode = false;
99 let mut skip_default = false;
100 let mut rename = None;
101
102 for attr in attrs {
103 if attr.path().is_ident("senax") {
104 let parsed = attr.parse_args_with(|input: syn::parse::ParseStream| {
106 let mut parsed_id = None;
107 let mut parsed_default = false;
108 let mut parsed_skip_encode = false;
109 let mut parsed_skip_decode = false;
110 let mut parsed_skip_default = false;
111 let mut parsed_rename = None;
112
113 while !input.is_empty() {
114 let ident = input.parse::<syn::Ident>()?;
115
116 if ident == "id" {
117 input.parse::<syn::Token![=]>()?;
118 let lit = input.parse::<syn::LitInt>()?;
119 if let Ok(id_val) = lit.base10_parse::<u64>() {
120 if id_val == 0 {
121 return Err(syn::Error::new(
122 lit.span(),
123 "Field ID 0 is reserved as a terminator",
124 ));
125 }
126 parsed_id = Some(id_val);
127 } else {
128 return Err(syn::Error::new(lit.span(), "Failed to parse ID value"));
129 }
130 } else if ident == "default" {
131 parsed_default = true;
132 } else if ident == "skip_encode" {
133 parsed_skip_encode = true;
134 } else if ident == "skip_decode" {
135 parsed_skip_decode = true;
136 } else if ident == "skip_default" {
137 parsed_skip_default = true;
138 } else if ident == "rename" {
139 input.parse::<syn::Token![=]>()?;
140 let lit_str = input.parse::<syn::LitStr>()?;
141 parsed_rename = Some(lit_str.value());
142 } else {
143 return Err(syn::Error::new(
144 ident.span(),
145 format!("Unknown attribute: {}", ident),
146 ));
147 }
148
149 if input.peek(syn::Token![,]) {
151 input.parse::<syn::Token![,]>()?;
152 }
153 }
154
155 Ok((
156 parsed_id,
157 parsed_default,
158 parsed_skip_encode,
159 parsed_skip_decode,
160 parsed_skip_default,
161 parsed_rename,
162 ))
163 });
164
165 if let Ok((
166 parsed_id,
167 parsed_default,
168 parsed_skip_encode,
169 parsed_skip_decode,
170 parsed_skip_default,
171 parsed_rename,
172 )) = parsed
173 {
174 if let Some(id_val) = parsed_id {
175 id = Some(id_val);
176 }
177 default = default || parsed_default;
178 skip_encode = skip_encode || parsed_skip_encode;
179 skip_decode = skip_decode || parsed_skip_decode;
180 skip_default = skip_default || parsed_skip_default;
181 if let Some(rename_val) = parsed_rename {
182 rename = Some(rename_val);
183 }
184 } else {
185 eprintln!(
186 "Warning: #[senax(...)] attribute for field '{}' is not in the correct format.",
187 field_name
188 );
189 }
190 }
191 }
192
193 let calculated_id = id.unwrap_or_else(|| {
195 let name_for_id = if let Some(ref rename_val) = rename {
196 rename_val.as_str()
197 } else {
198 field_name
199 };
200 calculate_id_from_name(name_for_id)
201 });
202
203 FieldAttributes {
204 id: calculated_id,
205 default,
206 skip_encode,
207 skip_decode,
208 skip_default,
209 rename,
210 }
211}
212
213fn is_option_type(ty: &Type) -> bool {
217 if let Type::Path(type_path) = ty {
218 type_path
219 .path
220 .segments
221 .last()
222 .map_or(false, |seg| seg.ident == "Option")
223 } else {
224 false
225 }
226}
227
228fn extract_inner_type_from_option(ty: &Type) -> Option<&Type> {
233 if let Type::Path(type_path) = ty {
234 if type_path
235 .path
236 .segments
237 .last()
238 .map_or(false, |seg| seg.ident == "Option")
239 {
240 if let PathArguments::AngleBracketed(args) =
241 &type_path.path.segments.last().unwrap().arguments
242 {
243 if let Some(GenericArgument::Type(inner_ty)) = args.args.first() {
244 return Some(inner_ty);
245 }
246 }
247 }
248 }
249 None
250}
251
252#[proc_macro_derive(Encode, attributes(senax))]
276pub fn derive_encode(input: TokenStream) -> TokenStream {
277 let input = parse_macro_input!(input as DeriveInput);
278 let name = &input.ident;
279 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
280
281 let mut default_variant_checks = Vec::new();
282
283 let encode_fields = match &input.data {
284 Data::Struct(s) => match &s.fields {
285 Fields::Named(fields) => {
286 let mut field_encode = Vec::new();
287 let mut used_ids_struct = HashSet::new();
288 for f in &fields.named {
289 let field_name_str = f.ident.as_ref().unwrap().to_string();
290 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
291
292 if field_attrs.skip_encode {
294 continue;
295 }
296
297 if !used_ids_struct.insert(field_attrs.id) {
298 panic!("Field ID (0x{:016X}) is duplicated for struct '{}'. Please specify a different ID for field '{}' using #[senax(id=...)].", field_attrs.id, name, field_name_str);
299 }
300
301 let field_ident = &f.ident;
302 let ty = &f.ty;
303 let is_option = is_option_type(ty);
304 let field_id = field_attrs.id;
305
306 if is_option {
307 field_encode.push(quote! {
308 if let Some(val) = &self.#field_ident {
309 senax_encoder::write_field_id_optimized(writer, #field_id)?;
310 senax_encoder::Encoder::encode(&val, writer)?;
311 }
312 });
313 } else if field_attrs.skip_default {
314 field_encode.push(quote! {
316 if senax_encoder::Encoder::is_default(&self.#field_ident) == false {
317 senax_encoder::write_field_id_optimized(writer, #field_id)?;
318 senax_encoder::Encoder::encode(&self.#field_ident, writer)?;
319 }
320 });
321 } else {
322 field_encode.push(quote! {
323 senax_encoder::write_field_id_optimized(writer, #field_id)?;
324 senax_encoder::Encoder::encode(&self.#field_ident, writer)?;
325 });
326 }
327 }
328 quote! {
329 writer.put_u8(senax_encoder::TAG_STRUCT_NAMED);
330 #(#field_encode)*
331 senax_encoder::write_field_id_optimized(writer, 0)?;
332 }
333 }
334 Fields::Unnamed(fields) => {
335 let field_count = fields.unnamed.len();
336 let field_encode = fields.unnamed.iter().enumerate().map(|(i, _)| {
337 let index = syn::Index::from(i);
338 quote! {
339 senax_encoder::Encoder::encode(&self.#index, writer)?;
340 }
341 });
342 quote! {
343 writer.put_u8(senax_encoder::TAG_STRUCT_UNNAMED);
344 let count: usize = #field_count;
345 senax_encoder::Encoder::encode(&count, writer)?;
346 #(#field_encode)*
347 }
348 }
349 Fields::Unit => quote! {
350 writer.put_u8(senax_encoder::TAG_STRUCT_UNIT);
351 },
352 },
353 Data::Enum(e) => {
354 let mut variant_encode = Vec::new();
355 let mut used_ids_enum = HashSet::new();
356
357 for v in &e.variants {
358 let variant_name_str = v.ident.to_string();
359 let variant_attrs = get_field_attributes(&v.attrs, &variant_name_str);
360 let variant_id = variant_attrs.id;
361 let is_default_variant = has_default_attribute(&v.attrs);
362
363 if !used_ids_enum.insert(variant_id) {
364 panic!("Variant ID (0x{:016X}) is duplicated for enum '{}'. Please specify a different ID for variant '{}' using #[senax(id=...)].", variant_id, name, variant_name_str);
365 }
366
367 let variant_ident = &v.ident;
368
369 if is_default_variant {
371 match &v.fields {
372 Fields::Named(fields) => {
373 let field_idents: Vec<_> = fields
374 .named
375 .iter()
376 .map(|f| f.ident.as_ref().unwrap())
377 .collect();
378 let field_default_checks: Vec<_> = field_idents
379 .iter()
380 .map(|ident| {
381 quote! { senax_encoder::Encoder::is_default(#ident) }
382 })
383 .collect();
384
385 if field_default_checks.is_empty() {
386 default_variant_checks.push(quote! {
387 #name::#variant_ident { .. } => true,
388 });
389 } else {
390 default_variant_checks.push(quote! {
391 #name::#variant_ident { #(#field_idents),* } => {
392 #(#field_default_checks)&&*
393 },
394 });
395 }
396 }
397 Fields::Unnamed(fields) => {
398 let field_count = fields.unnamed.len();
399 let field_bindings: Vec<_> = (0..field_count)
400 .map(|i| Ident::new(&format!("field{}", i), Span::call_site()))
401 .collect();
402 let field_default_checks: Vec<_> = field_bindings
403 .iter()
404 .map(|binding| {
405 quote! { senax_encoder::Encoder::is_default(#binding) }
406 })
407 .collect();
408
409 if field_default_checks.is_empty() {
410 default_variant_checks.push(quote! {
411 #name::#variant_ident(..) => true,
412 });
413 } else {
414 default_variant_checks.push(quote! {
415 #name::#variant_ident(#(#field_bindings),*) => {
416 #(#field_default_checks)&&*
417 },
418 });
419 }
420 }
421 Fields::Unit => {
422 default_variant_checks.push(quote! {
423 #name::#variant_ident => true,
424 });
425 }
426 }
427 }
428
429 match &v.fields {
430 Fields::Named(fields) => {
431 let field_idents: Vec<_> = fields
432 .named
433 .iter()
434 .map(|f| f.ident.as_ref().unwrap())
435 .collect();
436 let mut field_encode = Vec::new();
437 let mut used_ids_struct = HashSet::new();
438 for f in &fields.named {
439 let field_name_str = f.ident.as_ref().unwrap().to_string();
440 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
441
442 if field_attrs.skip_encode {
444 continue;
445 }
446
447 if !used_ids_struct.insert(field_attrs.id) {
448 panic!("Field ID (0x{:016X}) is duplicated for enum variant '{}'. Please specify a different ID for field '{}' using #[senax(id=...)].", field_attrs.id, variant_ident, field_name_str);
449 }
450 let field_ident = &f.ident;
451 let ty = &f.ty;
452 let is_option = is_option_type(ty);
453 let field_id = field_attrs.id;
454 if is_option {
455 field_encode.push(quote! {
456 if let Some(val) = #field_ident {
457 senax_encoder::write_field_id_optimized(writer, #field_id)?;
458 senax_encoder::Encoder::encode(&val, writer)?;
459 }
460 });
461 } else if field_attrs.skip_default {
462 field_encode.push(quote! {
464 if senax_encoder::Encoder::is_default(#field_ident) == false {
465 senax_encoder::write_field_id_optimized(writer, #field_id)?;
466 senax_encoder::Encoder::encode(&#field_ident, writer)?;
467 }
468 });
469 } else {
470 field_encode.push(quote! {
471 senax_encoder::write_field_id_optimized(writer, #field_id)?;
472 senax_encoder::Encoder::encode(&#field_ident, writer)?;
473 });
474 }
475 }
476 variant_encode.push(quote! {
477 #name::#variant_ident { #(#field_idents),* } => {
478 writer.put_u8(senax_encoder::TAG_ENUM_NAMED);
479 senax_encoder::write_field_id_optimized(writer, #variant_id)?;
480 #(#field_encode)*
481 senax_encoder::write_field_id_optimized(writer, 0)?;
482 }
483 });
484 }
485 Fields::Unnamed(fields) => {
486 let field_count = fields.unnamed.len();
487 let field_bindings: Vec<_> = (0..field_count)
488 .map(|i| Ident::new(&format!("field{}", i), Span::call_site()))
489 .collect();
490 let field_bindings_ref = &field_bindings;
491 variant_encode.push(quote! {
492 #name::#variant_ident( #(#field_bindings_ref),* ) => {
493 writer.put_u8(senax_encoder::TAG_ENUM_UNNAMED);
494 senax_encoder::write_field_id_optimized(writer, #variant_id)?;
495 let count: usize = #field_count;
496 senax_encoder::Encoder::encode(&count, writer)?;
497 #(
498 senax_encoder::Encoder::encode(&#field_bindings_ref, writer)?;
499 )*
500 }
501 });
502 }
503 Fields::Unit => {
504 variant_encode.push(quote! {
505 #name::#variant_ident => {
506 writer.put_u8(senax_encoder::TAG_ENUM);
507 senax_encoder::write_field_id_optimized(writer, #variant_id)?;
508 }
509 });
510 }
511 }
512 }
513 quote! {
514 match self {
515 #(#variant_encode)*
516 }
517 }
518 }
519 Data::Union(_) => unimplemented!("Unions are not supported"),
520 };
521
522 let is_default_impl = match &input.data {
523 Data::Enum(_) => {
524 if default_variant_checks.is_empty() {
525 quote! { false }
526 } else {
527 quote! {
528 match self {
529 #(#default_variant_checks)*
530 _ => false,
531 }
532 }
533 }
534 }
535 _ => quote! { false },
536 };
537
538 TokenStream::from(quote! {
539 impl #impl_generics senax_encoder::Encoder for #name #ty_generics #where_clause {
540 fn encode(&self, writer: &mut bytes::BytesMut) -> senax_encoder::Result<()> {
541 use bytes::{Buf, BufMut};
542 #encode_fields
543 Ok(())
544 }
545
546 fn is_default(&self) -> bool {
547 #is_default_impl
548 }
549 }
550 })
551}
552
553#[proc_macro_derive(Decode, attributes(senax))]
581pub fn derive_decode(input: TokenStream) -> TokenStream {
582 let input = parse_macro_input!(input as DeriveInput);
583 let name = &input.ident;
584 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
585
586 let decode_fields = match &input.data {
587 Data::Struct(s) => match &s.fields {
588 Fields::Named(fields) => {
589 let mut field_idents = Vec::new();
590 let mut field_original_types = Vec::new();
591 let mut field_ids_for_match = Vec::new();
592 let mut field_is_option_flags = Vec::new();
593 let mut field_attrs_list = Vec::new();
594 let mut used_ids_struct_decode = HashMap::new();
595
596 for f in &fields.named {
597 let field_name_str = f.ident.as_ref().unwrap().to_string();
598 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
599
600 if let Some(dup_field_name) =
601 used_ids_struct_decode.insert(field_attrs.id, field_name_str.clone())
602 {
603 panic!("Field ID (0x{:016X}) is duplicated for struct '{}'. Please specify a different ID for field '{}' and '{}' using #[senax(id=...)].",
604 field_attrs.id, name, dup_field_name, field_name_str);
605 }
606
607 field_idents.push(f.ident.as_ref().unwrap().clone());
608 field_original_types.push(f.ty.clone());
609 field_ids_for_match.push(field_attrs.id);
610 field_is_option_flags.push(is_option_type(&f.ty));
611 field_attrs_list.push(field_attrs);
612 }
613
614 let field_value_definitions = field_idents
615 .iter()
616 .zip(field_original_types.iter())
617 .zip(field_attrs_list.iter())
618 .filter_map(|((ident, original_ty), attrs)| {
619 if attrs.skip_decode {
620 None
622 } else if is_option_type(original_ty) {
623 Some(quote! { #ident: #original_ty, })
624 } else {
625 Some(quote! { #ident: Option<#original_ty>, })
626 }
627 });
628
629 let match_arms = field_idents
630 .iter()
631 .zip(field_original_types.iter())
632 .zip(field_ids_for_match.iter())
633 .zip(field_attrs_list.iter())
634 .filter_map(|(((ident, original_ty), id_val), attrs)| {
635 if attrs.skip_decode {
636 None
638 } else if is_option_type(original_ty) {
639 let inner_ty = extract_inner_type_from_option(original_ty)
640 .unwrap_or_else(|| {
641 panic!(
642 "Failed to extract inner type from Option for field {}",
643 ident
644 )
645 });
646 Some(quote! {
647 x if x == #id_val => {
648 field_values.#ident = Some(<#inner_ty as senax_encoder::Decoder>::decode(reader)?);
649 }
650 })
651 } else {
652 Some(quote! {
653 x if x == #id_val => {
654 field_values.#ident = Some(<#original_ty as senax_encoder::Decoder>::decode(reader)?);
655 }
656 })
657 }
658 });
659
660 let struct_assignments = field_idents.iter()
661 .zip(field_is_option_flags.iter())
662 .zip(field_attrs_list.iter())
663 .map(|((ident, is_opt_flag), attrs)| {
664 if attrs.skip_decode {
665 quote! {
667 #ident: Default::default(),
668 }
669 } else if *is_opt_flag {
670 quote! {
671 #ident: field_values.#ident,
672 }
673 } else if attrs.default || attrs.skip_default {
674 quote! {
676 #ident: field_values.#ident.unwrap_or_default(),
677 }
678 } else {
679 quote! {
680 #ident: field_values.#ident.ok_or_else(||
681 senax_encoder::EncoderError::Decode(format!("Required field '{}' not found for struct {}", stringify!(#ident), stringify!(#name)))
682 )?,
683 }
684 }
685 });
686
687 quote! {
688 if reader.remaining() == 0 {
689 return Err(senax_encoder::EncoderError::InsufficientData);
690 }
691 let tag = reader.get_u8();
692 if tag != senax_encoder::TAG_STRUCT_NAMED {
693 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct named tag ({}), got {}", senax_encoder::TAG_STRUCT_NAMED, tag)));
694 }
695
696 #[derive(Default)]
697 struct FieldValues {
698 #( #field_value_definitions )*
699 }
700
701 let mut field_values = FieldValues::default();
702
703 loop {
704 let field_id = senax_encoder::read_field_id_optimized(reader)?;
705 if field_id == 0 {
706 break;
707 }
708 match field_id {
709 #( #match_arms )*
710 _unknown_id => { senax_encoder::skip_value(reader)?; }
711 }
712 }
713
714 Ok(#name {
715 #( #struct_assignments )*
716 })
717 }
718 }
719 Fields::Unnamed(fields) => {
720 let field_count = fields.unnamed.len();
721 let field_deencode = fields.unnamed.iter().map(|f| {
722 let field_ty = &f.ty;
723 quote! {
724 <#field_ty as senax_encoder::Decoder>::decode(reader)?
725 }
726 });
727 quote! {
728 if reader.remaining() == 0 {
729 return Err(senax_encoder::EncoderError::InsufficientData);
730 }
731 let tag = reader.get_u8();
732 if tag != senax_encoder::TAG_STRUCT_UNNAMED {
733 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct unnamed tag ({}), got {}", senax_encoder::TAG_STRUCT_UNNAMED, tag)));
734 }
735 let count = <usize as senax_encoder::Decoder>::decode(reader)?;
736 if count != #field_count {
737 return Err(senax_encoder::EncoderError::Decode(format!("Field count mismatch for struct {}: expected {}, got {}", stringify!(#name), #field_count, count)));
738 }
739 Ok(#name(
740 #(#field_deencode),*
741 ))
742 }
743 }
744 Fields::Unit => quote! {
745 if reader.remaining() == 0 {
746 return Err(senax_encoder::EncoderError::InsufficientData);
747 }
748 let tag = reader.get_u8();
749 if tag != senax_encoder::TAG_STRUCT_UNIT {
750 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct unit tag ({}), got {}", senax_encoder::TAG_STRUCT_UNIT, tag)));
751 }
752 Ok(#name)
753 },
754 },
755 Data::Enum(e) => {
756 let mut unit_variant_arms = Vec::new();
757 let mut named_variant_arms = Vec::new();
758 let mut unnamed_variant_arms = Vec::new();
759 let mut used_ids_enum_decode = HashMap::new();
760
761 for v in &e.variants {
762 let variant_name_str = v.ident.to_string();
763 let variant_attrs = get_field_attributes(&v.attrs, &variant_name_str);
764 let variant_id = variant_attrs.id;
765
766 if let Some(dup_variant) =
767 used_ids_enum_decode.insert(variant_id, variant_name_str.clone())
768 {
769 panic!("Variant ID (0x{:016X}) is duplicated for enum '{}'. Please specify a different ID for variant '{}' and '{}' using #[senax(id=...)].",
770 variant_id, name, dup_variant, variant_name_str);
771 }
772
773 let variant_ident = &v.ident;
774 match &v.fields {
775 Fields::Named(fields) => {
776 let field_idents: Vec<_> = fields
777 .named
778 .iter()
779 .map(|f| f.ident.as_ref().unwrap().clone())
780 .collect();
781 let field_types: Vec<_> =
782 fields.named.iter().map(|f| f.ty.clone()).collect();
783 let field_attrs_list: Vec<_> = fields
784 .named
785 .iter()
786 .map(|f| {
787 get_field_attributes(
788 &f.attrs,
789 &f.ident.as_ref().unwrap().to_string(),
790 )
791 })
792 .collect();
793
794 let mut field_value_definitions_enum = Vec::new();
795 let mut match_arms_enum_named = Vec::new();
796 let mut struct_assignments_enum_named = Vec::new();
797
798 for (ident, ty, attrs) in izip!(
799 field_idents.iter(),
800 field_types.iter(),
801 field_attrs_list.iter()
802 ) {
803 if attrs.skip_decode {
804 } else if is_option_type(ty) {
806 field_value_definitions_enum.push(quote! { #ident: #ty, });
807 } else {
808 field_value_definitions_enum.push(quote! { #ident: Option<#ty>, });
809 }
810
811 if attrs.skip_decode {
812 } else if is_option_type(ty) {
814 let inner_ty = extract_inner_type_from_option(ty).unwrap();
815 let field_id = attrs.id;
816 match_arms_enum_named.push(quote! {
817 x if x == #field_id => { field_values.#ident = Some(<#inner_ty as senax_encoder::Decoder>::decode(reader)?); }
818 });
819 } else {
820 let field_id = attrs.id;
821 match_arms_enum_named.push(quote! {
822 x if x == #field_id => { field_values.#ident = Some(<#ty as senax_encoder::Decoder>::decode(reader)?); }
823 });
824 }
825
826 if attrs.skip_decode {
827 struct_assignments_enum_named
829 .push(quote! { #ident: Default::default(), });
830 } else if is_option_type(ty) {
831 struct_assignments_enum_named
832 .push(quote! { #ident: field_values.#ident, });
833 } else if attrs.default || attrs.skip_default {
834 struct_assignments_enum_named.push(quote! {
836 #ident: field_values.#ident.unwrap_or_default(),
837 });
838 } else {
839 struct_assignments_enum_named.push(quote! {
840 #ident: field_values.#ident.ok_or_else(|| senax_encoder::EncoderError::Decode(format!("Required field '{}' not found for variant {}::{}", stringify!(#ident), stringify!(#name), stringify!(#variant_ident))))?,
841 });
842 }
843 }
844
845 named_variant_arms.push(quote! {
846 x if x == #variant_id => {
847 #[derive(Default)]
848 struct FieldValues { #(#field_value_definitions_enum)* }
849 let mut field_values = FieldValues::default();
850 loop {
851 let field_id = {
852 if reader.remaining() == 0 { break; }
853 let id = senax_encoder::read_field_id_optimized(reader)?;
854 if id == 0 { break; }
855 id
856 };
857 match field_id {
858 #(#match_arms_enum_named)*
859 _unknown_id => { senax_encoder::skip_value(reader)?; }
860 }
861 }
862 Ok(#name::#variant_ident { #(#struct_assignments_enum_named)* })
863 }
864 });
865 }
866 Fields::Unnamed(fields) => {
867 let field_types: Vec<_> = fields.unnamed.iter().map(|f| &f.ty).collect();
868 let field_count = field_types.len();
869 unnamed_variant_arms.push(quote! {
870 x if x == #variant_id => {
871 let count = <usize as senax_encoder::Decoder>::decode(reader)?;
872 if count != #field_count {
873 return Err(senax_encoder::EncoderError::Decode(format!("Field count mismatch for variant {}::{}: expected {}, got {}", stringify!(#name), stringify!(#variant_ident), #field_count, count)));
874 }
875 Ok(#name::#variant_ident(
876 #(
877 <#field_types as senax_encoder::Decoder>::decode(reader)?,
878 )*
879 ))
880 }
881 });
882 }
883 Fields::Unit => {
884 unit_variant_arms.push(quote! {
885 x if x == #variant_id => {
886 Ok(#name::#variant_ident)
887 }
888 });
889 }
890 }
891 }
892 quote! {
893 if reader.remaining() == 0 {
894 return Err(senax_encoder::EncoderError::InsufficientData);
895 }
896 let tag = reader.get_u8();
897 match tag {
898 senax_encoder::TAG_ENUM => {
899 let variant_id = senax_encoder::read_field_id_optimized(reader)?;
900 match variant_id {
901 #(#unit_variant_arms)*
902 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown unit variant ID: 0x{:016X} for enum {}", variant_id, stringify!(#name))))
903 }
904 }
905 senax_encoder::TAG_ENUM_NAMED => {
906 let variant_id = senax_encoder::read_field_id_optimized(reader)?;
907 match variant_id {
908 #(#named_variant_arms)*
909 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown named variant ID: 0x{:016X} for enum {}", variant_id, stringify!(#name))))
910 }
911 }
912 senax_encoder::TAG_ENUM_UNNAMED => {
913 let variant_id = senax_encoder::read_field_id_optimized(reader)?;
914 match variant_id {
915 #(#unnamed_variant_arms)*
916 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown unnamed variant ID: 0x{:016X} for enum {}", variant_id, stringify!(#name))))
917 }
918 }
919 unknown_tag => Err(senax_encoder::EncoderError::Decode(format!("Unknown enum tag: {} for enum {}", unknown_tag, stringify!(#name))))
920 }
921 }
922 }
923 Data::Union(_) => unimplemented!("Unions are not supported"),
924 };
925
926 TokenStream::from(quote! {
927 impl #impl_generics senax_encoder::Decoder for #name #ty_generics #where_clause {
928 fn decode(reader: &mut bytes::Bytes) -> senax_encoder::Result<Self> {
929 use bytes::{Buf, BufMut};
930 #decode_fields
931 }
932 }
933 })
934}