1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, DeriveInput, Data, Fields, Ident, Type, PathArguments, GenericArgument, Attribute};
6use proc_macro2::Span;
7use crc32fast::Hasher;
8use std::collections::{HashSet, HashMap};
9use itertools::izip;
10
11fn calculate_id_from_name(name: &str) -> u32 {
16 let mut hasher = Hasher::new();
17 hasher.update(name.as_bytes());
18 let id = hasher.finalize();
19 if id == 0 { 1 } else { id }
21}
22
23#[derive(Debug, Clone)]
36#[allow(dead_code)] struct FieldAttributes {
38 id: u32,
39 default: bool,
40 skip_encode: bool,
41 skip_decode: bool,
42 rename: Option<String>,
43}
44
45fn get_field_attributes(attrs: &[Attribute], field_name: &str) -> FieldAttributes {
70 let mut id = None;
71 let mut default = false;
72 let mut skip_encode = false;
73 let mut skip_decode = false;
74 let mut rename = None;
75
76 for attr in attrs {
77 if attr.path().is_ident("senax") {
78 let parsed = attr.parse_args_with(|input: syn::parse::ParseStream| {
80 let mut parsed_id = None;
81 let mut parsed_default = false;
82 let mut parsed_skip_encode = false;
83 let mut parsed_skip_decode = false;
84 let mut parsed_rename = None;
85
86 while !input.is_empty() {
87 let ident = input.parse::<syn::Ident>()?;
88
89 if ident == "id" {
90 input.parse::<syn::Token![=]>()?;
91 let lit = input.parse::<syn::LitInt>()?;
92 if let Ok(id_val) = lit.base10_parse::<u32>() {
93 if id_val == 0 {
94 return Err(syn::Error::new(lit.span(), "Field ID 0 is reserved as a terminator"));
95 }
96 parsed_id = Some(id_val);
97 } else {
98 return Err(syn::Error::new(lit.span(), "Failed to parse ID value"));
99 }
100 } else if ident == "default" {
101 parsed_default = true;
102 } else if ident == "skip_encode" {
103 parsed_skip_encode = true;
104 } else if ident == "skip_decode" {
105 parsed_skip_decode = true;
106 } else if ident == "rename" {
107 input.parse::<syn::Token![=]>()?;
108 let lit_str = input.parse::<syn::LitStr>()?;
109 parsed_rename = Some(lit_str.value());
110 } else {
111 return Err(syn::Error::new(ident.span(), format!("Unknown attribute: {}", ident)));
112 }
113
114 if input.peek(syn::Token![,]) {
116 input.parse::<syn::Token![,]>()?;
117 }
118 }
119
120 Ok((parsed_id, parsed_default, parsed_skip_encode, parsed_skip_decode, parsed_rename))
121 });
122
123 if let Ok((parsed_id, parsed_default, parsed_skip_encode, parsed_skip_decode, parsed_rename)) = parsed {
124 if let Some(id_val) = parsed_id {
125 id = Some(id_val);
126 }
127 default = default || parsed_default;
128 skip_encode = skip_encode || parsed_skip_encode;
129 skip_decode = skip_decode || parsed_skip_decode;
130 if let Some(rename_val) = parsed_rename {
131 rename = Some(rename_val);
132 }
133 } else {
134 eprintln!("Warning: #[senax(...)] attribute for field '{}' is not in the correct format.", field_name);
135 }
136 }
137 }
138
139 let calculated_id = id.unwrap_or_else(|| {
141 let name_for_id = if let Some(ref rename_val) = rename {
142 rename_val.as_str()
143 } else {
144 field_name
145 };
146 calculate_id_from_name(name_for_id)
147 });
148
149 FieldAttributes {
150 id: calculated_id,
151 default,
152 skip_encode,
153 skip_decode,
154 rename,
155 }
156}
157
158fn is_option_type(ty: &Type) -> bool {
162 if let Type::Path(type_path) = ty {
163 type_path.path.segments.last().map_or(false, |seg| seg.ident == "Option")
164 } else {
165 false
166 }
167}
168
169fn extract_inner_type_from_option(ty: &Type) -> Option<&Type> {
174 if let Type::Path(type_path) = ty {
175 if type_path.path.segments.last().map_or(false, |seg| seg.ident == "Option") {
176 if let PathArguments::AngleBracketed(args) = &type_path.path.segments.last().unwrap().arguments {
177 if let Some(GenericArgument::Type(inner_ty)) = args.args.first() {
178 return Some(inner_ty);
179 }
180 }
181 }
182 }
183 None
184}
185
186fn get_container_attributes(attrs: &[Attribute]) -> bool {
188 for attr in attrs {
189 if attr.path().is_ident("senax") {
190 let parsed = attr.parse_args_with(|input: syn::parse::ParseStream| {
191 let mut id_u8 = false;
192 while !input.is_empty() {
193 let ident = input.parse::<syn::Ident>()?;
194 if ident == "u8" {
195 id_u8 = true;
196 }
197 if input.peek(syn::Token![,]) {
198 input.parse::<syn::Token![,]>()?;
199 }
200 }
201 Ok(id_u8)
202 });
203 if let Ok(id_u8) = parsed {
204 if id_u8 {
205 return true;
206 }
207 }
208 }
209 }
210 false
211}
212
213#[proc_macro_derive(Encode, attributes(senax))]
237pub fn derive_encode(input: TokenStream) -> TokenStream {
238 let input = parse_macro_input!(input as DeriveInput);
239 let name = &input.ident;
240 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
241 let container_id_u8 = get_container_attributes(&input.attrs);
242
243 let encode_fields = match &input.data {
244 Data::Struct(s) => match &s.fields {
245 Fields::Named(fields) => {
246 let mut field_encode = Vec::new();
247 let mut used_ids_struct = HashSet::new();
248 for f in &fields.named {
249 let field_name_str = f.ident.as_ref().unwrap().to_string();
250 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
251
252 if field_attrs.skip_encode {
254 continue;
255 }
256
257 if !used_ids_struct.insert(field_attrs.id) {
258 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);
259 }
260
261 let field_ident = &f.ident;
262 let ty = &f.ty;
263 let is_option = is_option_type(ty);
264 let field_id = field_attrs.id;
265
266 if is_option {
267 if container_id_u8 {
268 field_encode.push(quote! {
269 if let Some(val) = &self.#field_ident {
270 let field_id_val: u8 = #field_id as u8;
271 writer.put_u8(field_id_val);
272 val.encode(writer)?;
273 }
274 });
275 } else {
276 field_encode.push(quote! {
277 if let Some(val) = &self.#field_ident {
278 let field_id_val: u32 = #field_id;
279 if #container_id_u8 {
280 writer.put_u8(field_id_val as u8);
281 } else {
282 senax_encoder::write_u32_le(writer, field_id_val)?;
283 }
284 val.encode(writer)?;
285 }
286 });
287 }
288 } else {
289 if container_id_u8 {
290 field_encode.push(quote! {
291 let field_id_val: u8 = #field_id as u8;
292 writer.put_u8(field_id_val);
293 self.#field_ident.encode(writer)?;
294 });
295 } else {
296 field_encode.push(quote! {
297 let field_id_val: u32 = #field_id;
298 if #container_id_u8 {
299 writer.put_u8(field_id_val as u8);
300 } else {
301 senax_encoder::write_u32_le(writer, field_id_val)?;
302 }
303 self.#field_ident.encode(writer)?;
304 });
305 }
306 }
307 }
308 if container_id_u8 {
309 quote! {
310 writer.put_u8(senax_encoder::TAG_STRUCT_NAMED);
311 #(#field_encode)*
312 writer.put_u8(0);
313 }
314 } else {
315 quote! {
316 writer.put_u8(senax_encoder::TAG_STRUCT_NAMED);
317 #(#field_encode)*
318 senax_encoder::write_u32_le(writer, 0)?;
319 }
320 }
321 }
322 Fields::Unnamed(fields) => {
323 let field_count = fields.unnamed.len();
324 let field_encode = fields.unnamed.iter().enumerate().map(|(i, _)| {
325 let index = syn::Index::from(i);
326 quote! {
327 self.#index.encode(writer)?;
328 }
329 });
330 quote! {
331 writer.put_u8(senax_encoder::TAG_STRUCT_UNNAMED);
332 let count: usize = #field_count;
333 count.encode(writer)?;
334 #(#field_encode)*
335 }
336 }
337 Fields::Unit => quote! {
338 writer.put_u8(senax_encoder::TAG_STRUCT_UNIT);
339 },
340 },
341 Data::Enum(e) => {
342 let mut variant_encode = Vec::new();
343 let mut used_ids_enum = HashSet::new();
344
345 for v in &e.variants {
346 let variant_name_str = v.ident.to_string();
347 let variant_attrs = get_field_attributes(&v.attrs, &variant_name_str);
348 let variant_id = variant_attrs.id;
349
350 if !used_ids_enum.insert(variant_id) {
351 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);
352 }
353
354 let variant_ident = &v.ident;
355 match &v.fields {
356 Fields::Named(fields) => {
357 let field_idents: Vec<_> = fields.named.iter().map(|f| f.ident.as_ref().unwrap()).collect();
358 let mut field_encode = Vec::new();
359 let mut used_ids_struct = HashSet::new();
360 for f in &fields.named {
361 let field_name_str = f.ident.as_ref().unwrap().to_string();
362 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
363
364 if field_attrs.skip_encode {
366 continue;
367 }
368
369 if !used_ids_struct.insert(field_attrs.id) {
370 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);
371 }
372 let field_ident = &f.ident;
373 let ty = &f.ty;
374 let is_option = is_option_type(ty);
375 let field_id = field_attrs.id;
376 if is_option {
377 field_encode.push(quote! {
378 if let Some(val) = #field_ident {
379 let field_id_val: u32 = #field_id;
380 if #container_id_u8 {
381 writer.put_u8(field_id_val as u8);
382 } else {
383 senax_encoder::write_u32_le(writer, field_id_val)?;
384 }
385 val.encode(writer)?;
386 }
387 });
388 } else {
389 field_encode.push(quote! {
390 let field_id_val: u32 = #field_id;
391 if #container_id_u8 {
392 writer.put_u8(field_id_val as u8);
393 } else {
394 senax_encoder::write_u32_le(writer, field_id_val)?;
395 }
396 #field_ident.encode(writer)?;
397 });
398 }
399 }
400 if container_id_u8 {
401 variant_encode.push(quote! {
402 #name::#variant_ident { #(#field_idents),* } => {
403 writer.put_u8(senax_encoder::TAG_ENUM_NAMED);
404 let variant_id_val: u8 = #variant_id as u8;
405 writer.put_u8(variant_id_val);
406 #(#field_encode)*
407 writer.put_u8(0);
408 }
409 });
410 } else {
411 variant_encode.push(quote! {
412 #name::#variant_ident { #(#field_idents),* } => {
413 writer.put_u8(senax_encoder::TAG_ENUM_NAMED);
414 let variant_id_val: u32 = #variant_id;
415 if #container_id_u8 {
416 writer.put_u8(variant_id_val as u8);
417 } else {
418 senax_encoder::write_u32_le(writer, variant_id_val)?;
419 }
420 #(#field_encode)*
421 senax_encoder::write_u32_le(writer, 0)?;
422 }
423 });
424 }
425 }
426 Fields::Unnamed(fields) => {
427 let field_count = fields.unnamed.len();
428 let field_bindings: Vec<_> = (0..field_count)
429 .map(|i| Ident::new(&format!("field{}", i), Span::call_site()))
430 .collect();
431 let field_bindings_ref = &field_bindings;
432 variant_encode.push(quote! {
433 #name::#variant_ident( #(#field_bindings_ref),* ) => {
434 writer.put_u8(senax_encoder::TAG_ENUM_UNNAMED);
435 let variant_id_val: u32 = #variant_id;
436 if #container_id_u8 {
437 writer.put_u8(variant_id_val as u8);
438 } else {
439 senax_encoder::write_u32_le(writer, variant_id_val)?;
440 }
441 let count: usize = #field_count;
442 count.encode(writer)?;
443 #(
444 #field_bindings_ref.encode(writer)?;
445 )*
446 }
447 });
448 }
449 Fields::Unit => {
450 variant_encode.push(quote! {
451 #name::#variant_ident => {
452 writer.put_u8(senax_encoder::TAG_ENUM);
453 let variant_id_val: u32 = #variant_id;
454 if #container_id_u8 {
455 writer.put_u8(variant_id_val as u8);
456 } else {
457 senax_encoder::write_u32_le(writer, variant_id_val)?;
458 }
459 }
460 });
461 }
462 }
463 }
464 quote! {
465 match self {
466 #(#variant_encode)*
467 }
468 }
469 }
470 Data::Union(_) => unimplemented!("Unions are not supported"),
471 };
472
473 TokenStream::from(quote! {
474 impl #impl_generics senax_encoder::Encoder for #name #ty_generics #where_clause {
475 fn encode(&self, writer: &mut bytes::BytesMut) -> senax_encoder::Result<()> {
476 use bytes::{Buf, BufMut};
477 #encode_fields
478 Ok(())
479 }
480 }
481 })
482}
483
484#[proc_macro_derive(Decode, attributes(senax))]
511pub fn derive_decode(input: TokenStream) -> TokenStream {
512 let input = parse_macro_input!(input as DeriveInput);
513 let name = &input.ident;
514 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
515 let container_id_u8 = get_container_attributes(&input.attrs);
516
517 let decode_fields = match &input.data {
518 Data::Struct(s) => match &s.fields {
519 Fields::Named(fields) => {
520 let mut field_idents = Vec::new();
521 let mut field_original_types = Vec::new();
522 let mut field_ids_for_match = Vec::new();
523 let mut field_is_option_flags = Vec::new();
524 let mut field_attrs_list = Vec::new();
525 let mut used_ids_struct_decode = HashMap::new();
526
527 for f in &fields.named {
528 let field_name_str = f.ident.as_ref().unwrap().to_string();
529 let field_attrs = get_field_attributes(&f.attrs, &field_name_str);
530
531 if let Some(dup_field_name) = used_ids_struct_decode.insert(field_attrs.id, field_name_str.clone()) {
532 panic!("Field ID (0x{:08X}) is duplicated for struct '{}'. Please specify a different ID for field '{}' and '{}' using #[senax(id=...)].",
533 field_attrs.id, name, dup_field_name, field_name_str);
534 }
535
536 field_idents.push(f.ident.as_ref().unwrap().clone());
537 field_original_types.push(f.ty.clone());
538 field_ids_for_match.push(field_attrs.id);
539 field_is_option_flags.push(is_option_type(&f.ty));
540 field_attrs_list.push(field_attrs);
541 }
542
543 let field_value_definitions = field_idents.iter()
544 .zip(field_original_types.iter())
545 .zip(field_attrs_list.iter())
546 .filter_map(|((ident, original_ty), attrs)| {
547 if attrs.skip_decode {
548 None
550 } else if is_option_type(original_ty) {
551 Some(quote! { #ident: #original_ty, })
552 } else {
553 Some(quote! { #ident: Option<#original_ty>, })
554 }
555 });
556
557 let match_arms = field_idents.iter()
558 .zip(field_original_types.iter())
559 .zip(field_ids_for_match.iter())
560 .zip(field_attrs_list.iter())
561 .filter_map(|(((ident, original_ty), id_val), attrs)| {
562 if attrs.skip_decode {
563 None
565 } else if is_option_type(original_ty) {
566 let inner_ty = extract_inner_type_from_option(original_ty)
567 .expect(&format!("Failed to extract inner type from Option for field {}", ident));
568 Some(quote! {
569 x if x == #id_val => {
570 field_values.#ident = Some(<#inner_ty>::decode(reader)?);
571 }
572 })
573 } else {
574 Some(quote! {
575 x if x == #id_val => {
576 field_values.#ident = Some(<#original_ty>::decode(reader)?);
577 }
578 })
579 }
580 });
581
582 let struct_assignments = field_idents.iter()
583 .zip(field_is_option_flags.iter())
584 .zip(field_attrs_list.iter())
585 .map(|((ident, is_opt_flag), attrs)| {
586 if attrs.skip_decode {
587 quote! {
589 #ident: Default::default(),
590 }
591 } else if *is_opt_flag {
592 quote! {
593 #ident: field_values.#ident,
594 }
595 } else if attrs.default {
596 quote! {
598 #ident: field_values.#ident.unwrap_or_default(),
599 }
600 } else {
601 quote! {
602 #ident: field_values.#ident.ok_or_else(||
603 senax_encoder::EncoderError::Decode(format!("Required field '{}' not found for struct {}", stringify!(#ident), stringify!(#name)))
604 )?,
605 }
606 }
607 });
608
609 quote! {
610 if reader.remaining() == 0 {
611 return Err(senax_encoder::EncoderError::InsufficientData);
612 }
613 let tag = reader.get_u8();
614 if tag != senax_encoder::TAG_STRUCT_NAMED {
615 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct named tag ({}), got {}", senax_encoder::TAG_STRUCT_NAMED, tag)));
616 }
617
618 #[derive(Default)]
619 struct FieldValues {
620 #( #field_value_definitions )*
621 }
622
623 let mut field_values = FieldValues::default();
624
625 loop {
626 let field_id = if #container_id_u8 {
627 if reader.remaining() == 0 { break; }
628 let id = reader.get_u8() as u32;
629 if id == 0 { break; }
630 id
631 } else {
632 let id = senax_encoder::read_u32_le(reader)?;
633 if id == 0 { break; }
634 id
635 };
636 match field_id {
637 #( #match_arms )*
638 _unknown_id => { senax_encoder::skip_value(reader)?; }
639 }
640 }
641
642 Ok(#name {
643 #( #struct_assignments )*
644 })
645 }
646 }
647 Fields::Unnamed(fields) => {
648 let field_count = fields.unnamed.len();
649 let field_deencode = fields.unnamed.iter().map(|f| {
650 let field_ty = &f.ty;
651 quote! {
652 <#field_ty>::decode(reader)?
653 }
654 });
655 quote! {
656 if reader.remaining() == 0 {
657 return Err(senax_encoder::EncoderError::InsufficientData);
658 }
659 let tag = reader.get_u8();
660 if tag != senax_encoder::TAG_STRUCT_UNNAMED {
661 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct unnamed tag ({}), got {}", senax_encoder::TAG_STRUCT_UNNAMED, tag)));
662 }
663 let count = <usize>::decode(reader)?;
664 if count != #field_count {
665 return Err(senax_encoder::EncoderError::Decode(format!("Field count mismatch for struct {}: expected {}, got {}", stringify!(#name), #field_count, count)));
666 }
667 Ok(#name(
668 #(#field_deencode),*
669 ))
670 }
671 }
672 Fields::Unit => quote! {
673 if reader.remaining() == 0 {
674 return Err(senax_encoder::EncoderError::InsufficientData);
675 }
676 let tag = reader.get_u8();
677 if tag != senax_encoder::TAG_STRUCT_UNIT {
678 return Err(senax_encoder::EncoderError::Decode(format!("Expected struct unit tag ({}), got {}", senax_encoder::TAG_STRUCT_UNIT, tag)));
679 }
680 Ok(#name)
681 },
682 },
683 Data::Enum(e) => {
684 let mut unit_variant_arms = Vec::new();
685 let mut named_variant_arms = Vec::new();
686 let mut unnamed_variant_arms = Vec::new();
687 let mut used_ids_enum_decode = HashMap::new();
688
689 for v in &e.variants {
690 let variant_name_str = v.ident.to_string();
691 let variant_attrs = get_field_attributes(&v.attrs, &variant_name_str);
692 let variant_id = variant_attrs.id;
693
694 if let Some(dup_variant) = used_ids_enum_decode.insert(variant_id, variant_name_str.clone()) {
695 panic!("Variant ID (0x{:08X}) is duplicated for enum '{}'. Please specify a different ID for variant '{}' and '{}' using #[senax(id=...)].",
696 variant_id, name, dup_variant, variant_name_str);
697 }
698
699 let variant_ident = &v.ident;
700 match &v.fields {
701 Fields::Named(fields) => {
702 let field_idents: Vec<_> = fields.named.iter().map(|f| f.ident.as_ref().unwrap().clone()).collect();
703 let field_types: Vec<_> = fields.named.iter().map(|f| f.ty.clone()).collect();
704 let field_attrs_list: Vec<_> = fields.named.iter().map(|f| get_field_attributes(&f.attrs, &f.ident.as_ref().unwrap().to_string())).collect();
705
706 let mut field_value_definitions_enum = Vec::new();
707 let mut match_arms_enum_named = Vec::new();
708 let mut struct_assignments_enum_named = Vec::new();
709
710 for (ident, ty, attrs) in izip!(field_idents.iter(), field_types.iter(), field_attrs_list.iter()) {
711 if attrs.skip_decode {
712 } else if is_option_type(ty) {
714 field_value_definitions_enum.push(quote! { #ident: #ty, });
715 } else {
716 field_value_definitions_enum.push(quote! { #ident: Option<#ty>, });
717 }
718
719 if attrs.skip_decode {
720 } else if is_option_type(ty) {
722 let inner_ty = extract_inner_type_from_option(ty).unwrap();
723 let field_id = attrs.id;
724 match_arms_enum_named.push(quote! {
725 x if x == #field_id => { field_values.#ident = Some(<#inner_ty>::decode(reader)?); }
726 });
727 } else {
728 let field_id = attrs.id;
729 match_arms_enum_named.push(quote! {
730 x if x == #field_id => { field_values.#ident = Some(<#ty>::decode(reader)?); }
731 });
732 }
733
734 if attrs.skip_decode {
735 struct_assignments_enum_named.push(quote! { #ident: Default::default(), });
737 } else if is_option_type(ty) {
738 struct_assignments_enum_named.push(quote! { #ident: field_values.#ident, });
739 } else if attrs.default {
740 struct_assignments_enum_named.push(quote! {
742 #ident: field_values.#ident.unwrap_or_default(),
743 });
744 } else {
745 struct_assignments_enum_named.push(quote! {
746 #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))))?,
747 });
748 }
749 }
750
751 named_variant_arms.push(quote! {
752 x if x == #variant_id => {
753 #[derive(Default)]
754 struct FieldValues { #(#field_value_definitions_enum)* }
755 let mut field_values = FieldValues::default();
756 loop {
757 let field_id = if #container_id_u8 {
758 if reader.remaining() == 0 { break; }
759 let id = reader.get_u8() as u32;
760 if id == 0 { break; }
761 id
762 } else {
763 let id = senax_encoder::read_u32_le(reader)?;
764 if id == 0 { break; }
765 id
766 };
767 match field_id {
768 #(#match_arms_enum_named)*
769 _unknown_id => { senax_encoder::skip_value(reader)?; }
770 }
771 }
772 Ok(#name::#variant_ident { #(#struct_assignments_enum_named)* })
773 }
774 });
775 }
776 Fields::Unnamed(fields) => {
777 let field_types: Vec<_> = fields.unnamed.iter().map(|f| &f.ty).collect();
778 let field_count = field_types.len();
779 unnamed_variant_arms.push(quote! {
780 x if x == #variant_id => {
781 let count = <usize>::decode(reader)?;
782 if count != #field_count {
783 return Err(senax_encoder::EncoderError::Decode(format!("Field count mismatch for variant {}::{}: expected {}, got {}", stringify!(#name), stringify!(#variant_ident), #field_count, count)));
784 }
785 Ok(#name::#variant_ident(
786 #(
787 <#field_types>::decode(reader)?,
788 )*
789 ))
790 }
791 });
792 }
793 Fields::Unit => {
794 unit_variant_arms.push(quote! {
795 x if x == #variant_id => {
796 Ok(#name::#variant_ident)
797 }
798 });
799 }
800 }
801 }
802 quote! {
803 if reader.remaining() == 0 {
804 return Err(senax_encoder::EncoderError::InsufficientData);
805 }
806 let tag = reader.get_u8();
807 match tag {
808 senax_encoder::TAG_ENUM => {
809 let variant_id = if #container_id_u8 {
810 reader.get_u8() as u32
811 } else {
812 senax_encoder::read_u32_le(reader)?
813 };
814 match variant_id {
815 #(#unit_variant_arms)*
816 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown unit variant ID: 0x{:08X} for enum {}", variant_id, stringify!(#name))))
817 }
818 }
819 senax_encoder::TAG_ENUM_NAMED => {
820 let variant_id = if #container_id_u8 {
821 reader.get_u8() as u32
822 } else {
823 senax_encoder::read_u32_le(reader)?
824 };
825 match variant_id {
826 #(#named_variant_arms)*
827 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown named variant ID: 0x{:08X} for enum {}", variant_id, stringify!(#name))))
828 }
829 }
830 senax_encoder::TAG_ENUM_UNNAMED => {
831 let variant_id = if #container_id_u8 {
832 reader.get_u8() as u32
833 } else {
834 senax_encoder::read_u32_le(reader)?
835 };
836 match variant_id {
837 #(#unnamed_variant_arms)*
838 _ => Err(senax_encoder::EncoderError::Decode(format!("Unknown unnamed variant ID: 0x{:08X} for enum {}", variant_id, stringify!(#name))))
839 }
840 }
841 unknown_tag => Err(senax_encoder::EncoderError::Decode(format!("Unknown enum tag: {} for enum {}", unknown_tag, stringify!(#name))))
842 }
843 }
844 }
845 Data::Union(_) => unimplemented!("Unions are not supported"),
846 };
847
848 TokenStream::from(quote! {
849 impl #impl_generics senax_encoder::Decoder for #name #ty_generics #where_clause {
850 fn decode(reader: &mut bytes::Bytes) -> senax_encoder::Result<Self> {
851 use bytes::{Buf, BufMut};
852 #decode_fields
853 }
854 }
855 })
856}
857
858