1extern crate proc_macro;
2
3use crc32fast::Hasher;
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
14fn calculate_id_from_name(name: &str) -> u32 {
19 let mut hasher = Hasher::new();
20 hasher.update(name.as_bytes());
21 let id = hasher.finalize();
22 if id == 0 {
24 1
25 } else {
26 id
27 }
28}
29
30#[derive(Debug, Clone)]
44#[allow(dead_code)] struct FieldAttributes {
46 id: u32,
47 default: bool,
48 skip_encode: bool,
49 skip_decode: bool,
50 skip_default: bool,
51 rename: Option<String>,
52}
53
54fn get_field_attributes(attrs: &[Attribute], field_name: &str) -> FieldAttributes {
80 let mut id = None;
81 let mut default = false;
82 let mut skip_encode = false;
83 let mut skip_decode = false;
84 let mut skip_default = false;
85 let mut rename = None;
86
87 for attr in attrs {
88 if attr.path().is_ident("senax") {
89 let parsed = attr.parse_args_with(|input: syn::parse::ParseStream| {
91 let mut parsed_id = None;
92 let mut parsed_default = false;
93 let mut parsed_skip_encode = false;
94 let mut parsed_skip_decode = false;
95 let mut parsed_skip_default = false;
96 let mut parsed_rename = None;
97
98 while !input.is_empty() {
99 let ident = input.parse::<syn::Ident>()?;
100
101 if ident == "id" {
102 input.parse::<syn::Token![=]>()?;
103 let lit = input.parse::<syn::LitInt>()?;
104 if let Ok(id_val) = lit.base10_parse::<u32>() {
105 if id_val == 0 {
106 return Err(syn::Error::new(
107 lit.span(),
108 "Field ID 0 is reserved as a terminator",
109 ));
110 }
111 parsed_id = Some(id_val);
112 } else {
113 return Err(syn::Error::new(lit.span(), "Failed to parse ID value"));
114 }
115 } else if ident == "default" {
116 parsed_default = true;
117 } else if ident == "skip_encode" {
118 parsed_skip_encode = true;
119 } else if ident == "skip_decode" {
120 parsed_skip_decode = true;
121 } else if ident == "skip_default" {
122 parsed_skip_default = true;
123 } else if ident == "rename" {
124 input.parse::<syn::Token![=]>()?;
125 let lit_str = input.parse::<syn::LitStr>()?;
126 parsed_rename = Some(lit_str.value());
127 } else {
128 return Err(syn::Error::new(
129 ident.span(),
130 format!("Unknown attribute: {}", ident),
131 ));
132 }
133
134 if input.peek(syn::Token![,]) {
136 input.parse::<syn::Token![,]>()?;
137 }
138 }
139
140 Ok((
141 parsed_id,
142 parsed_default,
143 parsed_skip_encode,
144 parsed_skip_decode,
145 parsed_skip_default,
146 parsed_rename,
147 ))
148 });
149
150 if let Ok((
151 parsed_id,
152 parsed_default,
153 parsed_skip_encode,
154 parsed_skip_decode,
155 parsed_skip_default,
156 parsed_rename,
157 )) = parsed
158 {
159 if let Some(id_val) = parsed_id {
160 id = Some(id_val);
161 }
162 default = default || parsed_default;
163 skip_encode = skip_encode || parsed_skip_encode;
164 skip_decode = skip_decode || parsed_skip_decode;
165 skip_default = skip_default || parsed_skip_default;
166 if let Some(rename_val) = parsed_rename {
167 rename = Some(rename_val);
168 }
169 } else {
170 eprintln!(
171 "Warning: #[senax(...)] attribute for field '{}' is not in the correct format.",
172 field_name
173 );
174 }
175 }
176 }
177
178 let calculated_id = id.unwrap_or_else(|| {
180 let name_for_id = if let Some(ref rename_val) = rename {
181 rename_val.as_str()
182 } else {
183 field_name
184 };
185 calculate_id_from_name(name_for_id)
186 });
187
188 FieldAttributes {
189 id: calculated_id,
190 default,
191 skip_encode,
192 skip_decode,
193 skip_default,
194 rename,
195 }
196}
197
198fn is_option_type(ty: &Type) -> bool {
202 if let Type::Path(type_path) = ty {
203 type_path
204 .path
205 .segments
206 .last()
207 .map_or(false, |seg| seg.ident == "Option")
208 } else {
209 false
210 }
211}
212
213fn extract_inner_type_from_option(ty: &Type) -> Option<&Type> {
218 if let Type::Path(type_path) = ty {
219 if type_path
220 .path
221 .segments
222 .last()
223 .map_or(false, |seg| seg.ident == "Option")
224 {
225 if let PathArguments::AngleBracketed(args) =
226 &type_path.path.segments.last().unwrap().arguments
227 {
228 if let Some(GenericArgument::Type(inner_ty)) = args.args.first() {
229 return Some(inner_ty);
230 }
231 }
232 }
233 }
234 None
235}
236
237fn get_container_attributes(attrs: &[Attribute]) -> bool {
239 for attr in attrs {
240 if attr.path().is_ident("senax") {
241 let parsed = attr.parse_args_with(|input: syn::parse::ParseStream| {
242 let mut id_u8 = false;
243 while !input.is_empty() {
244 let ident = input.parse::<syn::Ident>()?;
245 if ident == "u8" {
246 id_u8 = true;
247 }
248 if input.peek(syn::Token![,]) {
249 input.parse::<syn::Token![,]>()?;
250 }
251 }
252 Ok(id_u8)
253 });
254 if let Ok(id_u8) = parsed {
255 if id_u8 {
256 return true;
257 }
258 }
259 }
260 }
261 false
262}
263
264#[proc_macro_derive(Encode, attributes(senax))]
288pub fn derive_encode(input: TokenStream) -> TokenStream {
289 let input = parse_macro_input!(input as DeriveInput);
290 let name = &input.ident;
291 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
292 let container_id_u8 = get_container_attributes(&input.attrs);
293
294 let encode_fields = match &input.data {
295 Data::Struct(s) => match &s.fields {
296 Fields::Named(fields) => {
297 let mut field_encode = Vec::new();
298 let mut used_ids_struct = HashSet::new();
299 for f in &fields.named {
300 let field_name_str = f.ident.as_ref().unwrap().to_string();
301 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
302
303 if field_attrs.skip_encode {
305 continue;
306 }
307
308 if !used_ids_struct.insert(field_attrs.id) {
309 panic!("Field ID (0x{:08X}) is duplicated for struct '{}'. Please specify a different ID for field '{}' using #[senax(id=...)].", field_attrs.id, name, field_name_str);
310 }
311
312 let field_ident = &f.ident;
313 let ty = &f.ty;
314 let is_option = is_option_type(ty);
315 let field_id = field_attrs.id;
316
317 if is_option {
318 if container_id_u8 {
319 field_encode.push(quote! {
320 if let Some(val) = &self.#field_ident {
321 let field_id_val: u8 = #field_id as u8;
322 writer.put_u8(field_id_val);
323 val.encode(writer)?;
324 }
325 });
326 } else {
327 field_encode.push(quote! {
328 if let Some(val) = &self.#field_ident {
329 let field_id_val: u32 = #field_id;
330 if #container_id_u8 {
331 writer.put_u8(field_id_val as u8);
332 } else {
333 senax_encoder::write_u32_le(writer, field_id_val)?;
334 }
335 val.encode(writer)?;
336 }
337 });
338 }
339 } else if field_attrs.skip_default {
340 if container_id_u8 {
342 field_encode.push(quote! {
343 if !self.#field_ident.is_default() {
344 let field_id_val: u8 = #field_id as u8;
345 writer.put_u8(field_id_val);
346 self.#field_ident.encode(writer)?;
347 }
348 });
349 } else {
350 field_encode.push(quote! {
351 if !self.#field_ident.is_default() {
352 let field_id_val: u32 = #field_id;
353 if #container_id_u8 {
354 writer.put_u8(field_id_val as u8);
355 } else {
356 senax_encoder::write_u32_le(writer, field_id_val)?;
357 }
358 self.#field_ident.encode(writer)?;
359 }
360 });
361 }
362 } else if container_id_u8 {
363 field_encode.push(quote! {
364 let field_id_val: u8 = #field_id as u8;
365 writer.put_u8(field_id_val);
366 self.#field_ident.encode(writer)?;
367 });
368 } else {
369 field_encode.push(quote! {
370 let field_id_val: u32 = #field_id;
371 if #container_id_u8 {
372 writer.put_u8(field_id_val as u8);
373 } else {
374 senax_encoder::write_u32_le(writer, field_id_val)?;
375 }
376 self.#field_ident.encode(writer)?;
377 });
378 }
379 }
380 if container_id_u8 {
381 quote! {
382 writer.put_u8(senax_encoder::TAG_STRUCT_NAMED);
383 #(#field_encode)*
384 writer.put_u8(0);
385 }
386 } else {
387 quote! {
388 writer.put_u8(senax_encoder::TAG_STRUCT_NAMED);
389 #(#field_encode)*
390 senax_encoder::write_u32_le(writer, 0)?;
391 }
392 }
393 }
394 Fields::Unnamed(fields) => {
395 let field_count = fields.unnamed.len();
396 let field_encode = fields.unnamed.iter().enumerate().map(|(i, _)| {
397 let index = syn::Index::from(i);
398 quote! {
399 self.#index.encode(writer)?;
400 }
401 });
402 quote! {
403 writer.put_u8(senax_encoder::TAG_STRUCT_UNNAMED);
404 let count: usize = #field_count;
405 count.encode(writer)?;
406 #(#field_encode)*
407 }
408 }
409 Fields::Unit => quote! {
410 writer.put_u8(senax_encoder::TAG_STRUCT_UNIT);
411 },
412 },
413 Data::Enum(e) => {
414 let mut variant_encode = Vec::new();
415 let mut used_ids_enum = HashSet::new();
416
417 for v in &e.variants {
418 let variant_name_str = v.ident.to_string();
419 let variant_attrs = get_field_attributes(&v.attrs, &variant_name_str);
420 let variant_id = variant_attrs.id;
421
422 if !used_ids_enum.insert(variant_id) {
423 panic!("Variant ID (0x{:08X}) is duplicated for enum '{}'. Please specify a different ID for variant '{}' using #[senax(id=...)].", variant_id, name, variant_name_str);
424 }
425
426 let variant_ident = &v.ident;
427 match &v.fields {
428 Fields::Named(fields) => {
429 let field_idents: Vec<_> = fields
430 .named
431 .iter()
432 .map(|f| f.ident.as_ref().unwrap())
433 .collect();
434 let mut field_encode = Vec::new();
435 let mut used_ids_struct = HashSet::new();
436 for f in &fields.named {
437 let field_name_str = f.ident.as_ref().unwrap().to_string();
438 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
439
440 if field_attrs.skip_encode {
442 continue;
443 }
444
445 if !used_ids_struct.insert(field_attrs.id) {
446 panic!("Field ID (0x{:08X}) is duplicated for enum variant '{}'. Please specify a different ID for field '{}' using #[senax(id=...)].", field_attrs.id, variant_ident, field_name_str);
447 }
448 let field_ident = &f.ident;
449 let ty = &f.ty;
450 let is_option = is_option_type(ty);
451 let field_id = field_attrs.id;
452 if is_option {
453 field_encode.push(quote! {
454 if let Some(val) = #field_ident {
455 let field_id_val: u32 = #field_id;
456 if #container_id_u8 {
457 writer.put_u8(field_id_val as u8);
458 } else {
459 senax_encoder::write_u32_le(writer, field_id_val)?;
460 }
461 val.encode(writer)?;
462 }
463 });
464 } else if field_attrs.skip_default {
465 field_encode.push(quote! {
467 if !#field_ident.is_default() {
468 let field_id_val: u32 = #field_id;
469 if #container_id_u8 {
470 writer.put_u8(field_id_val as u8);
471 } else {
472 senax_encoder::write_u32_le(writer, field_id_val)?;
473 }
474 #field_ident.encode(writer)?;
475 }
476 });
477 } else {
478 field_encode.push(quote! {
479 let field_id_val: u32 = #field_id;
480 if #container_id_u8 {
481 writer.put_u8(field_id_val as u8);
482 } else {
483 senax_encoder::write_u32_le(writer, field_id_val)?;
484 }
485 #field_ident.encode(writer)?;
486 });
487 }
488 }
489 if container_id_u8 {
490 variant_encode.push(quote! {
491 #name::#variant_ident { #(#field_idents),* } => {
492 writer.put_u8(senax_encoder::TAG_ENUM_NAMED);
493 let variant_id_val: u8 = #variant_id as u8;
494 writer.put_u8(variant_id_val);
495 #(#field_encode)*
496 writer.put_u8(0);
497 }
498 });
499 } else {
500 variant_encode.push(quote! {
501 #name::#variant_ident { #(#field_idents),* } => {
502 writer.put_u8(senax_encoder::TAG_ENUM_NAMED);
503 let variant_id_val: u32 = #variant_id;
504 if #container_id_u8 {
505 writer.put_u8(variant_id_val as u8);
506 } else {
507 senax_encoder::write_u32_le(writer, variant_id_val)?;
508 }
509 #(#field_encode)*
510 senax_encoder::write_u32_le(writer, 0)?;
511 }
512 });
513 }
514 }
515 Fields::Unnamed(fields) => {
516 let field_count = fields.unnamed.len();
517 let field_bindings: Vec<_> = (0..field_count)
518 .map(|i| Ident::new(&format!("field{}", i), Span::call_site()))
519 .collect();
520 let field_bindings_ref = &field_bindings;
521 variant_encode.push(quote! {
522 #name::#variant_ident( #(#field_bindings_ref),* ) => {
523 writer.put_u8(senax_encoder::TAG_ENUM_UNNAMED);
524 let variant_id_val: u32 = #variant_id;
525 if #container_id_u8 {
526 writer.put_u8(variant_id_val as u8);
527 } else {
528 senax_encoder::write_u32_le(writer, variant_id_val)?;
529 }
530 let count: usize = #field_count;
531 count.encode(writer)?;
532 #(
533 #field_bindings_ref.encode(writer)?;
534 )*
535 }
536 });
537 }
538 Fields::Unit => {
539 variant_encode.push(quote! {
540 #name::#variant_ident => {
541 writer.put_u8(senax_encoder::TAG_ENUM);
542 let variant_id_val: u32 = #variant_id;
543 if #container_id_u8 {
544 writer.put_u8(variant_id_val as u8);
545 } else {
546 senax_encoder::write_u32_le(writer, variant_id_val)?;
547 }
548 }
549 });
550 }
551 }
552 }
553 quote! {
554 match self {
555 #(#variant_encode)*
556 }
557 }
558 }
559 Data::Union(_) => unimplemented!("Unions are not supported"),
560 };
561
562 TokenStream::from(quote! {
563 impl #impl_generics senax_encoder::Encoder for #name #ty_generics #where_clause {
564 fn encode(&self, writer: &mut bytes::BytesMut) -> senax_encoder::Result<()> {
565 use bytes::{Buf, BufMut};
566 #encode_fields
567 Ok(())
568 }
569
570 fn is_default(&self) -> bool {
571 false }
573 }
574 })
575}
576
577#[proc_macro_derive(Decode, attributes(senax))]
605pub fn derive_decode(input: TokenStream) -> TokenStream {
606 let input = parse_macro_input!(input as DeriveInput);
607 let name = &input.ident;
608 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
609 let container_id_u8 = get_container_attributes(&input.attrs);
610
611 let decode_fields = match &input.data {
612 Data::Struct(s) => match &s.fields {
613 Fields::Named(fields) => {
614 let mut field_idents = Vec::new();
615 let mut field_original_types = Vec::new();
616 let mut field_ids_for_match = Vec::new();
617 let mut field_is_option_flags = Vec::new();
618 let mut field_attrs_list = Vec::new();
619 let mut used_ids_struct_decode = HashMap::new();
620
621 for f in &fields.named {
622 let field_name_str = f.ident.as_ref().unwrap().to_string();
623 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
624
625 if let Some(dup_field_name) =
626 used_ids_struct_decode.insert(field_attrs.id, field_name_str.clone())
627 {
628 panic!("Field ID (0x{:08X}) is duplicated for struct '{}'. Please specify a different ID for field '{}' and '{}' using #[senax(id=...)].",
629 field_attrs.id, name, dup_field_name, field_name_str);
630 }
631
632 field_idents.push(f.ident.as_ref().unwrap().clone());
633 field_original_types.push(f.ty.clone());
634 field_ids_for_match.push(field_attrs.id);
635 field_is_option_flags.push(is_option_type(&f.ty));
636 field_attrs_list.push(field_attrs);
637 }
638
639 let field_value_definitions = field_idents
640 .iter()
641 .zip(field_original_types.iter())
642 .zip(field_attrs_list.iter())
643 .filter_map(|((ident, original_ty), attrs)| {
644 if attrs.skip_decode {
645 None
647 } else if is_option_type(original_ty) {
648 Some(quote! { #ident: #original_ty, })
649 } else {
650 Some(quote! { #ident: Option<#original_ty>, })
651 }
652 });
653
654 let match_arms = field_idents
655 .iter()
656 .zip(field_original_types.iter())
657 .zip(field_ids_for_match.iter())
658 .zip(field_attrs_list.iter())
659 .filter_map(|(((ident, original_ty), id_val), attrs)| {
660 if attrs.skip_decode {
661 None
663 } else if is_option_type(original_ty) {
664 let inner_ty = extract_inner_type_from_option(original_ty)
665 .unwrap_or_else(|| {
666 panic!(
667 "Failed to extract inner type from Option for field {}",
668 ident
669 )
670 });
671 Some(quote! {
672 x if x == #id_val => {
673 field_values.#ident = Some(<#inner_ty>::decode(reader)?);
674 }
675 })
676 } else {
677 Some(quote! {
678 x if x == #id_val => {
679 field_values.#ident = Some(<#original_ty>::decode(reader)?);
680 }
681 })
682 }
683 });
684
685 let struct_assignments = field_idents.iter()
686 .zip(field_is_option_flags.iter())
687 .zip(field_attrs_list.iter())
688 .map(|((ident, is_opt_flag), attrs)| {
689 if attrs.skip_decode {
690 quote! {
692 #ident: Default::default(),
693 }
694 } else if *is_opt_flag {
695 quote! {
696 #ident: field_values.#ident,
697 }
698 } else if attrs.default || attrs.skip_default {
699 quote! {
701 #ident: field_values.#ident.unwrap_or_default(),
702 }
703 } else {
704 quote! {
705 #ident: field_values.#ident.ok_or_else(||
706 senax_encoder::EncoderError::Decode(format!("Required field '{}' not found for struct {}", stringify!(#ident), stringify!(#name)))
707 )?,
708 }
709 }
710 });
711
712 quote! {
713 if reader.remaining() == 0 {
714 return Err(senax_encoder::EncoderError::InsufficientData);
715 }
716 let tag = reader.get_u8();
717 if tag != senax_encoder::TAG_STRUCT_NAMED {
718 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct named tag ({}), got {}", senax_encoder::TAG_STRUCT_NAMED, tag)));
719 }
720
721 #[derive(Default)]
722 struct FieldValues {
723 #( #field_value_definitions )*
724 }
725
726 let mut field_values = FieldValues::default();
727
728 loop {
729 let field_id = if #container_id_u8 {
730 if reader.remaining() == 0 { break; }
731 let id = reader.get_u8() as u32;
732 if id == 0 { break; }
733 id
734 } else {
735 let id = senax_encoder::read_u32_le(reader)?;
736 if id == 0 { break; }
737 id
738 };
739 match field_id {
740 #( #match_arms )*
741 _unknown_id => { senax_encoder::skip_value(reader)?; }
742 }
743 }
744
745 Ok(#name {
746 #( #struct_assignments )*
747 })
748 }
749 }
750 Fields::Unnamed(fields) => {
751 let field_count = fields.unnamed.len();
752 let field_deencode = fields.unnamed.iter().map(|f| {
753 let field_ty = &f.ty;
754 quote! {
755 <#field_ty>::decode(reader)?
756 }
757 });
758 quote! {
759 if reader.remaining() == 0 {
760 return Err(senax_encoder::EncoderError::InsufficientData);
761 }
762 let tag = reader.get_u8();
763 if tag != senax_encoder::TAG_STRUCT_UNNAMED {
764 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct unnamed tag ({}), got {}", senax_encoder::TAG_STRUCT_UNNAMED, tag)));
765 }
766 let count = <usize>::decode(reader)?;
767 if count != #field_count {
768 return Err(senax_encoder::EncoderError::Decode(format!("Field count mismatch for struct {}: expected {}, got {}", stringify!(#name), #field_count, count)));
769 }
770 Ok(#name(
771 #(#field_deencode),*
772 ))
773 }
774 }
775 Fields::Unit => quote! {
776 if reader.remaining() == 0 {
777 return Err(senax_encoder::EncoderError::InsufficientData);
778 }
779 let tag = reader.get_u8();
780 if tag != senax_encoder::TAG_STRUCT_UNIT {
781 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct unit tag ({}), got {}", senax_encoder::TAG_STRUCT_UNIT, tag)));
782 }
783 Ok(#name)
784 },
785 },
786 Data::Enum(e) => {
787 let mut unit_variant_arms = Vec::new();
788 let mut named_variant_arms = Vec::new();
789 let mut unnamed_variant_arms = Vec::new();
790 let mut used_ids_enum_decode = HashMap::new();
791
792 for v in &e.variants {
793 let variant_name_str = v.ident.to_string();
794 let variant_attrs = get_field_attributes(&v.attrs, &variant_name_str);
795 let variant_id = variant_attrs.id;
796
797 if let Some(dup_variant) =
798 used_ids_enum_decode.insert(variant_id, variant_name_str.clone())
799 {
800 panic!("Variant ID (0x{:08X}) is duplicated for enum '{}'. Please specify a different ID for variant '{}' and '{}' using #[senax(id=...)].",
801 variant_id, name, dup_variant, variant_name_str);
802 }
803
804 let variant_ident = &v.ident;
805 match &v.fields {
806 Fields::Named(fields) => {
807 let field_idents: Vec<_> = fields
808 .named
809 .iter()
810 .map(|f| f.ident.as_ref().unwrap().clone())
811 .collect();
812 let field_types: Vec<_> =
813 fields.named.iter().map(|f| f.ty.clone()).collect();
814 let field_attrs_list: Vec<_> = fields
815 .named
816 .iter()
817 .map(|f| {
818 get_field_attributes(
819 &f.attrs,
820 &f.ident.as_ref().unwrap().to_string(),
821 )
822 })
823 .collect();
824
825 let mut field_value_definitions_enum = Vec::new();
826 let mut match_arms_enum_named = Vec::new();
827 let mut struct_assignments_enum_named = Vec::new();
828
829 for (ident, ty, attrs) in izip!(
830 field_idents.iter(),
831 field_types.iter(),
832 field_attrs_list.iter()
833 ) {
834 if attrs.skip_decode {
835 } else if is_option_type(ty) {
837 field_value_definitions_enum.push(quote! { #ident: #ty, });
838 } else {
839 field_value_definitions_enum.push(quote! { #ident: Option<#ty>, });
840 }
841
842 if attrs.skip_decode {
843 } else if is_option_type(ty) {
845 let inner_ty = extract_inner_type_from_option(ty).unwrap();
846 let field_id = attrs.id;
847 match_arms_enum_named.push(quote! {
848 x if x == #field_id => { field_values.#ident = Some(<#inner_ty>::decode(reader)?); }
849 });
850 } else {
851 let field_id = attrs.id;
852 match_arms_enum_named.push(quote! {
853 x if x == #field_id => { field_values.#ident = Some(<#ty>::decode(reader)?); }
854 });
855 }
856
857 if attrs.skip_decode {
858 struct_assignments_enum_named
860 .push(quote! { #ident: Default::default(), });
861 } else if is_option_type(ty) {
862 struct_assignments_enum_named
863 .push(quote! { #ident: field_values.#ident, });
864 } else if attrs.default || attrs.skip_default {
865 struct_assignments_enum_named.push(quote! {
867 #ident: field_values.#ident.unwrap_or_default(),
868 });
869 } else {
870 struct_assignments_enum_named.push(quote! {
871 #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))))?,
872 });
873 }
874 }
875
876 named_variant_arms.push(quote! {
877 x if x == #variant_id => {
878 #[derive(Default)]
879 struct FieldValues { #(#field_value_definitions_enum)* }
880 let mut field_values = FieldValues::default();
881 loop {
882 let field_id = if #container_id_u8 {
883 if reader.remaining() == 0 { break; }
884 let id = reader.get_u8() as u32;
885 if id == 0 { break; }
886 id
887 } else {
888 let id = senax_encoder::read_u32_le(reader)?;
889 if id == 0 { break; }
890 id
891 };
892 match field_id {
893 #(#match_arms_enum_named)*
894 _unknown_id => { senax_encoder::skip_value(reader)?; }
895 }
896 }
897 Ok(#name::#variant_ident { #(#struct_assignments_enum_named)* })
898 }
899 });
900 }
901 Fields::Unnamed(fields) => {
902 let field_types: Vec<_> = fields.unnamed.iter().map(|f| &f.ty).collect();
903 let field_count = field_types.len();
904 unnamed_variant_arms.push(quote! {
905 x if x == #variant_id => {
906 let count = <usize>::decode(reader)?;
907 if count != #field_count {
908 return Err(senax_encoder::EncoderError::Decode(format!("Field count mismatch for variant {}::{}: expected {}, got {}", stringify!(#name), stringify!(#variant_ident), #field_count, count)));
909 }
910 Ok(#name::#variant_ident(
911 #(
912 <#field_types>::decode(reader)?,
913 )*
914 ))
915 }
916 });
917 }
918 Fields::Unit => {
919 unit_variant_arms.push(quote! {
920 x if x == #variant_id => {
921 Ok(#name::#variant_ident)
922 }
923 });
924 }
925 }
926 }
927 quote! {
928 if reader.remaining() == 0 {
929 return Err(senax_encoder::EncoderError::InsufficientData);
930 }
931 let tag = reader.get_u8();
932 match tag {
933 senax_encoder::TAG_ENUM => {
934 let variant_id = if #container_id_u8 {
935 reader.get_u8() as u32
936 } else {
937 senax_encoder::read_u32_le(reader)?
938 };
939 match variant_id {
940 #(#unit_variant_arms)*
941 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown unit variant ID: 0x{:08X} for enum {}", variant_id, stringify!(#name))))
942 }
943 }
944 senax_encoder::TAG_ENUM_NAMED => {
945 let variant_id = if #container_id_u8 {
946 reader.get_u8() as u32
947 } else {
948 senax_encoder::read_u32_le(reader)?
949 };
950 match variant_id {
951 #(#named_variant_arms)*
952 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown named variant ID: 0x{:08X} for enum {}", variant_id, stringify!(#name))))
953 }
954 }
955 senax_encoder::TAG_ENUM_UNNAMED => {
956 let variant_id = if #container_id_u8 {
957 reader.get_u8() as u32
958 } else {
959 senax_encoder::read_u32_le(reader)?
960 };
961 match variant_id {
962 #(#unnamed_variant_arms)*
963 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown unnamed variant ID: 0x{:08X} for enum {}", variant_id, stringify!(#name))))
964 }
965 }
966 unknown_tag => Err(senax_encoder::EncoderError::Decode(format!("Unknown enum tag: {} for enum {}", unknown_tag, stringify!(#name))))
967 }
968 }
969 }
970 Data::Union(_) => unimplemented!("Unions are not supported"),
971 };
972
973 TokenStream::from(quote! {
974 impl #impl_generics senax_encoder::Decoder for #name #ty_generics #where_clause {
975 fn decode(reader: &mut bytes::Bytes) -> senax_encoder::Result<Self> {
976 use bytes::{Buf, BufMut};
977 #decode_fields
978 }
979 }
980 })
981}