senax_encoder_derive/
lib.rs

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
14/// CRC-64 hasher for field name to ID conversion
15const CRC64: Crc<u64> = Crc::<u64>::new(&CRC_64_ECMA_182);
16
17/// Calculate a unique field ID from a field name using CRC-64
18///
19/// This function generates a deterministic 64-bit ID from a field name by computing
20/// the CRC-64 hash. This ensures consistent field IDs across compilation runs
21/// while providing excellent distribution and minimizing collision probability.
22///
23/// # Arguments
24///
25/// * `name` - The field name to hash
26///
27/// # Returns
28///
29/// A 64-bit field ID (never 0, as 0 is reserved as a terminator)
30fn calculate_id_from_name(name: &str) -> u64 {
31    let crc64_hash = CRC64.checksum(name.as_bytes());
32    // Ensure it's not 0 (0 is reserved as terminator)
33    if crc64_hash == 0 {
34        u64::MAX
35    } else {
36        crc64_hash
37    }
38}
39
40/// Check if a variant has the #[default] attribute
41fn has_default_attribute(attrs: &[Attribute]) -> bool {
42    attrs.iter().any(|attr| attr.path().is_ident("default"))
43}
44
45/// Field attributes parsed from `#[senax(...)]` annotations
46///
47/// This struct represents the various attributes that can be applied to fields
48/// in structs and enum variants using the `#[senax(...)]` attribute macro.
49///
50/// # Fields
51///
52/// * `id` - The unique identifier for this field (computed from name or explicitly set)
53/// * `default` - Whether to use default values when the field is missing during decode
54/// * `skip_encode` - Whether to exclude this field from encoding
55/// * `skip_decode` - Whether to ignore this field during decoding
56/// * `skip_default` - Whether to use default value if field is missing
57/// * `rename` - Optional alternative name for ID calculation (maintains compatibility when renaming)
58#[derive(Debug, Clone)]
59#[allow(dead_code)] // The rename field is used indirectly in ID calculation
60struct 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
69/// Extract and parse `#[senax(...)]` attribute values from field attributes
70///
71/// This function parses the senax attributes applied to a field and returns
72/// a `FieldAttributes` struct containing all the parsed values.
73///
74/// # Arguments
75///
76/// * `attrs` - The attributes array from the field
77/// * `field_name` - The name of the field (used for ID calculation if no explicit ID is provided)
78///
79/// # Returns
80///
81/// A `FieldAttributes` struct with parsed values. If no explicit ID is provided,
82/// the ID is calculated using CRC64 hash of either the rename value or the field name.
83///
84/// # Supported Attributes
85///
86/// * `#[senax(id=1234)]` - Explicit field ID
87/// * `#[senax(default)]` - Use default value if field is missing during decode
88/// * `#[senax(skip_encode)]` - Skip this field during encoding
89/// * `#[senax(skip_decode)]` - Skip this field during decoding
90/// * `#[senax(skip_default)]` - Skip encoding if field value is default, use default if missing during decode
91/// * `#[senax(rename="name")]` - Alternative name for ID calculation
92///
93/// Multiple attributes can be combined: `#[senax(id=123, default, skip_encode)]`
94fn 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            // Try to parse #[senax(id=1234, default, skip_encode, skip_decode, skip_default, rename="name")]
105            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                    // Consume comma if present, otherwise end
150                    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    // ID calculation: Use explicit ID if provided, otherwise calculate CRC64 from rename or field name
194    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
213/// Check if a type is `Option<T>`
214///
215/// This helper function determines whether a given type is wrapped in an `Option`.
216fn 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
228/// Extract the inner type `T` from `Option<T>`
229///
230/// This helper function extracts the wrapped type from an `Option` type.
231/// Returns `None` if the type is not an `Option`.
232fn 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/// Derive macro for implementing the `Encode` trait
253///
254/// This procedural macro automatically generates an implementation of the `Encode` trait
255/// for structs and enums. It supports various field attributes for customizing the
256/// encoding behavior.
257///
258/// # Supported Attributes
259///
260/// * `#[senax(id=N)]` - Set explicit field/variant ID
261/// * `#[senax(skip_encode)]` - Skip field during encoding
262/// * `#[senax(rename="name")]` - Use alternative name for ID calculation
263///
264/// # Examples
265///
266/// ```rust
267/// #[derive(Encode)]
268/// struct MyStruct {
269///     #[senax(id=1)]
270///     field1: i32,
271///     #[senax(skip_encode)]
272///     field2: String,
273/// }
274/// ```
275#[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                    // Skip fields marked with skip_encode
293                    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                        // For skip_default fields, check if the value is default before encoding
315                        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                // Generate is_default check for this variant if it has #[default] attribute
370                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                            // Skip fields marked with skip_encode
443                            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                                // For skip_default fields, check if the value is default before encoding
463                                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/// Derive macro for implementing the `Decode` trait
554///
555/// This procedural macro automatically generates an implementation of the `Decode` trait
556/// for structs and enums. It supports various field attributes for customizing the
557/// decoding behavior and provides forward/backward compatibility.
558///
559/// # Supported Attributes
560///
561/// * `#[senax(id=N)]` - Set explicit field/variant ID
562/// * `#[senax(default)]` - Use default value if field is missing
563/// * `#[senax(skip_decode)]` - Skip field during decoding (use default value)
564/// * `#[senax(skip_default)]` - Use default value if field is missing (same as default for decode)
565/// * `#[senax(rename="name")]` - Use alternative name for ID calculation
566///
567/// # Examples
568///
569/// ```rust
570/// #[derive(Decode)]
571/// struct MyStruct {
572///     #[senax(id=1)]
573///     field1: i32,
574///     #[senax(default)]
575///     field2: String,
576///     #[senax(skip_decode)]
577///     field3: bool,
578/// }
579/// ```
580#[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                            // Fields marked with skip_decode don't store values
621                            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                            // Fields marked with skip_decode don't generate match arms (values are skipped)
637                            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                            // Fields marked with skip_decode use default values
666                            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                            // Fields marked with default or skip_default use default value if missing
675                            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                                // Fields marked with skip_decode don't store values
805                            } 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                                // Fields marked with skip_decode don't generate match arms
813                            } 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                                // Fields marked with skip_decode use default values
828                                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                                // Fields marked with default or skip_default use default value if missing
835                                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}