Skip to main content

afastdata_macro/
lib.rs

1//! # afastdata-macro
2//!
3//! afastdata 序列化框架的 derive 宏,为结构体和枚举自动生成
4//! [`AFastSerialize`] 和 [`AFastDeserialize`] trait 的实现。
5//!
6//! Derive macros for the afastdata serialization framework, automatically generating
7//! implementations of [`AFastSerialize`]` and [`AFastDeserialize`] traits for
8//! structs and enums.
9//!
10//! ## 支持的类型 / Supported Types
11//!
12//! - **命名字段结构体 (Named-field struct)**:逐字段序列化/反序列化
13//!   / Field-by-field serialization/deserialization
14//! - **元组结构体 (Tuple struct)**:按索引逐字段序列化/反序列化
15//!   / Index-based field serialization/deserialization
16//! - **单元结构体 (Unit struct)**:生成空实现(不产生任何字节)
17//!   / Generates an empty implementation (no bytes produced)
18//! - **枚举 (Enum)**:写入 `u32` 变体索引 + 变体字段数据
19//!   / Writes a `u32` variant index + variant field data
20//!
21//! ## 编码格式 / Encoding Format
22//!
23//! ### 结构体 / Struct
24//!
25//! 所有字段按声明顺序依次调用 `to_bytes()` / `from_bytes()`,无额外前缀。
26//!
27//! All fields call `to_bytes()` / `from_bytes()` in declaration order, with no
28//! additional prefix.
29//!
30//! ### 枚举 / Enum
31//!
32//! | 编码内容 / Content | 类型 / Type | 说明 / Description |
33//! |---|---|---|
34//! | 变体索引 / Variant index | `u32` little-endian | 从 0 开始递增 / Starts from 0, incrementing |
35//! | 变体字段 / Variant fields | 逐字段编码 / Field-wise encoding | 仅非 unit 变体 / Only for non-unit variants |
36//!
37//! ## 泛型支持 / Generic Support
38//!
39//! 泛型参数会自动添加 `AFastSerialize` 和(对于反序列化)`AFastDeserialize` trait 约束。
40//! 如果泛型参数仅用于某些字段,生成的约束可能过于严格,但这保证了实现的正确性。
41//!
42//! Generic parameters automatically receive `AFastSerialize` and (for deserialization)
43//! `AFastDeserialize` trait bounds. If a generic parameter is only used in certain fields,
44//! the generated bounds may be overly strict, but this ensures correctness.
45//!
46//! ## 示例 / Example
47//!
48//! ```ignore
49//! use afastdata::{AFastSerialize, AFastDeserialize};
50//!
51//! #[derive(AFastSerialize, AFastDeserialize, Debug, PartialEq)]
52//! struct Point {
53//!     x: i32,
54//!     y: i32,
55//! }
56//!
57//! #[derive(AFastSerialize, AFastDeserialize, Debug, PartialEq)]
58//! enum Shape {
59//!     Circle(f64),
60//!     Rectangle { width: f64, height: f64 },
61//!     Empty,
62//! }
63//!
64//! // 序列化 / Serialize
65//! let point = Point { x: 10, y: 20 };
66//! let bytes = point.to_bytes();
67//!
68//! // 反序列化 / Deserialize
69//! let (decoded, _) = Point::from_bytes(&bytes).unwrap();
70//! assert_eq!(point, decoded);
71//! ```
72
73use proc_macro::TokenStream;
74use quote::quote;
75use syn::{parse_macro_input, Data, DeriveInput, Fields, Index};
76
77/// 为结构体或枚举生成 [`AFastSerialize`] trait 实现。
78///
79/// Generates an [`AFastSerialize`] trait implementation for a struct or enum.
80///
81/// # 生成的代码 / Generated Code
82///
83/// ## 结构体 / Struct
84///
85/// 为每个字段调用 `to_bytes()`,并将结果依次追加到字节缓冲区中。
86///
87/// Calls `to_bytes()` on each field, appending the results to a byte buffer
88/// sequentially.
89///
90/// ```ignore
91/// // 以下为生成代码的示意(非实际代码)
92/// // The following is an illustration of generated code (not actual code)
93/// impl AFastSerialize for MyStruct {
94///     fn to_bytes(&self) -> Vec<u8> {
95///         let mut bytes = Vec::new();
96///         bytes.extend(AFastSerialize::to_bytes(&self.field1));
97///         bytes.extend(AFastSerialize::to_bytes(&self.field2));
98///         // ...
99///         bytes
100///     }
101/// }
102/// ```
103///
104/// ## 枚举 / Enum
105///
106/// 先写入 `u32` 变体索引(从 0 开始),再写入变体的字段数据。
107/// Unit 变体只写入索引。
108///
109/// Writes a `u32` variant index (starting from 0), then the variant's field data.
110/// Unit variants only write the index.
111///
112/// ```ignore
113/// // 以下为生成代码的示意(非实际代码)
114/// // The following is an illustration of generated code (not actual code)
115/// impl AFastSerialize for MyEnum {
116///     fn to_bytes(&self) -> Vec<u8> {
117///         let mut bytes = Vec::new();
118///         match self {
119///             MyEnum::Variant1 => {
120///                 bytes.extend(0u32.to_le_bytes());
121///             }
122///             MyEnum::Variant2(field) => {
123///                 bytes.extend(1u32.to_le_bytes());
124///                 bytes.extend(AFastSerialize::to_bytes(field));
125///             }
126///             // ...
127///         }
128///         bytes
129///     }
130/// }
131/// ```
132///
133/// # 泛型 / Generics
134///
135/// 如果目标类型包含泛型参数,生成的 `impl` 会自动为这些参数添加
136/// `AFastSerialize` 约束。
137///
138/// If the target type contains generic parameters, the generated `impl` automatically
139/// adds `AFastSerialize` bounds to those parameters.
140///
141/// # Panics
142///
143/// 对 union 类型使用此宏会触发编译 panic。
144///
145/// Using this macro on a union type will trigger a compile-time panic.
146#[proc_macro_derive(AFastSerialize)]
147pub fn derive_serialize(input: TokenStream) -> TokenStream {
148    let input = parse_macro_input!(input as DeriveInput);
149    let name = &input.ident;
150    let generics = &input.generics;
151
152    // 为泛型参数添加 AFastSerialize trait 约束
153    // Add AFastSerialize trait bounds to generic parameters
154    let mut generics_with_bounds = generics.clone();
155    for param in &mut generics_with_bounds.params {
156        if let syn::GenericParam::Type(ref mut ty) = *param {
157            ty.bounds.push(syn::parse_quote!(::afastdata_core::AFastSerialize));
158        }
159    }
160    let (impl_generics, _, _) = generics_with_bounds.split_for_impl();
161    let (_, ty_generics, _) = generics.split_for_impl();
162
163    let expanded = match &input.data {
164        Data::Struct(data) => {
165            let serialize_body = generate_serialize_fields(&data.fields, quote!(self));
166            quote! {
167                impl #impl_generics ::afastdata_core::AFastSerialize for #name #ty_generics {
168                    fn to_bytes(&self) -> Vec<u8> {
169                        let mut bytes = Vec::new();
170                        #(#serialize_body)*
171                        bytes
172                    }
173                }
174            }
175        }
176        Data::Enum(data) => {
177            let mut arms = Vec::new();
178            for (i, variant) in data.variants.iter().enumerate() {
179                let variant_name = &variant.ident;
180                let tag = i as u32;
181
182                match &variant.fields {
183                    Fields::Unit => {
184                        // Unit 变体:只写入 u32 索引
185                        // Unit variant: write only the u32 index
186                        arms.push(quote! {
187                            #name::#variant_name => {
188                                bytes.extend(#tag.to_le_bytes());
189                            }
190                        });
191                    }
192                    Fields::Unnamed(fields) => {
193                        // 元组变体:写入 u32 索引 + 逐字段序列化
194                        // Tuple variant: write u32 index + field-by-field serialization
195                        let field_names: Vec<_> = (0..fields.unnamed.len())
196                            .map(|i| {
197                                let ident = syn::Ident::new(&format!("__f{}", i), variant_name.span());
198                                ident
199                            })
200                            .collect();
201                        let field_patterns = &field_names;
202                        let mut serialize_fields = Vec::new();
203                        for fname in &field_names {
204                            serialize_fields.push(quote! {
205                                bytes.extend(::afastdata_core::AFastSerialize::to_bytes(#fname));
206                            });
207                        }
208                        arms.push(quote! {
209                            #name::#variant_name(#(#field_patterns),*) => {
210                                bytes.extend(#tag.to_le_bytes());
211                                #(#serialize_fields)*
212                            }
213                        });
214                    }
215                    Fields::Named(fields) => {
216                        // 命名字段变体:写入 u32 索引 + 逐字段序列化
217                        // Named-field variant: write u32 index + field-by-field serialization
218                        let field_names: Vec<_> =
219                            fields.named.iter().map(|f| f.ident.as_ref().unwrap()).collect();
220                        let mut serialize_fields = Vec::new();
221                        for fname in &field_names {
222                            serialize_fields.push(quote! {
223                                bytes.extend(::afastdata_core::AFastSerialize::to_bytes(#fname));
224                            });
225                        }
226                        arms.push(quote! {
227                            #name::#variant_name { #(#field_names),* } => {
228                                bytes.extend(#tag.to_le_bytes());
229                                #(#serialize_fields)*
230                            }
231                        });
232                    }
233                }
234            }
235
236            quote! {
237                impl #impl_generics ::afastdata_core::AFastSerialize for #name #ty_generics {
238                    fn to_bytes(&self) -> Vec<u8> {
239                        let mut bytes = Vec::new();
240                        match self {
241                            #(#arms)*
242                        }
243                        bytes
244                    }
245                }
246            }
247        }
248        Data::Union(_) => panic!("AFastSerialize does not support unions"),
249    };
250
251    TokenStream::from(expanded)
252}
253
254/// 为结构体或枚举生成 [`AFastDeserialize`] trait 实现。
255///
256/// Generates an [`AFastDeserialize`] trait implementation for a struct or enum.
257///
258/// # 生成的代码 / Generated Code
259///
260/// ## 结构体 / Struct
261///
262/// 为每个字段依次调用 `from_bytes()`,并使用偏移量追踪已消耗的字节数,
263/// 最后构造结构体实例。
264///
265/// Calls `from_bytes()` on each field sequentially, using an offset to track
266/// consumed bytes, then constructs the struct instance.
267///
268/// ```ignore
269/// // 以下为生成代码的示意(非实际代码)
270/// // The following is an illustration of generated code (not actual code)
271/// impl AFastDeserialize for MyStruct {
272///     fn from_bytes(data: &[u8]) -> Result<(Self, usize), String> {
273///         let mut offset: usize = 0;
274///         let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
275///         let field1 = __val;
276///         offset += __new_offset;
277///         // ... 更多字段 / more fields ...
278///         Ok((MyStruct { field1, ... }, offset))
279///     }
280/// }
281/// ```
282///
283/// ## 枚举 / Enum
284///
285/// 先读取 `u32` 变体索引,根据索引匹配对应变体,再反序列化该变体的字段。
286///
287/// First reads the `u32` variant index, matches the corresponding variant by index,
288/// then deserializes the variant's fields.
289///
290/// ```ignore
291/// // 以下为生成代码的示意(非实际代码)
292/// // The following is an illustration of generated code (not actual code)
293/// impl AFastDeserialize for MyEnum {
294///     fn from_bytes(data: &[u8]) -> Result<(Self, usize), String> {
295///         let mut offset: usize = 0;
296///         let (__tag, __new_offset) = <u32 as AFastDeserialize>::from_bytes(&data[offset..])?;
297///         offset += __new_offset;
298///         match __tag {
299///             0 => Ok((MyEnum::Variant1, offset)),
300///             1 => {
301///                 let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
302///                 offset += __new_offset;
303///                 Ok((MyEnum::Variant2(__val), offset))
304///             }
305///             v => Err(format!("Unknown variant tag: {} for MyEnum", v)),
306///         }
307///     }
308/// }
309/// ```
310///
311/// # 泛型 / Generics
312///
313/// 如果目标类型包含泛型参数,生成的 `impl` 会同时添加 `AFastSerialize` 和
314/// `AFastDeserialize` 约束。双重约束确保泛型类型在序列化和反序列化两个方向
315/// 上都可用。
316///
317/// If the target type contains generic parameters, the generated `impl` adds both
318/// `AFastSerialize` and `AFastDeserialize` bounds. The dual bounds ensure the generic
319/// type is available in both serialization and deserialization directions.
320///
321/// # Panics
322///
323/// 对 union 类型使用此宏会触发编译 panic。
324///
325/// Using this macro on a union type will trigger a compile-time panic.
326#[proc_macro_derive(AFastDeserialize)]
327pub fn derive_deserialize(input: TokenStream) -> TokenStream {
328    let input = parse_macro_input!(input as DeriveInput);
329    let name = &input.ident;
330    let generics = &input.generics;
331
332    // 为泛型参数添加 AFastSerialize + AFastDeserialize trait 约束
333    // Add AFastSerialize + AFastDeserialize trait bounds to generic parameters
334    let mut generics_with_bounds = generics.clone();
335    for param in &mut generics_with_bounds.params {
336        if let syn::GenericParam::Type(ref mut ty) = *param {
337            ty.bounds.push(syn::parse_quote!(::afastdata_core::AFastSerialize));
338            ty.bounds.push(syn::parse_quote!(::afastdata_core::AFastDeserialize));
339        }
340    }
341    let (impl_generics, _, _) = generics_with_bounds.split_for_impl();
342    let (_, ty_generics, _) = generics.split_for_impl();
343
344    let expanded = match &input.data {
345        Data::Struct(data) => {
346            let (construct, field_desers) =
347                generate_deserialize_fields(&data.fields, &name, &ty_generics);
348            quote! {
349                impl #impl_generics ::afastdata_core::AFastDeserialize for #name #ty_generics {
350                    fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::std::string::String> {
351                        let mut offset: usize = 0;
352                        #(#field_desers)*
353                        Ok((#construct, offset))
354                    }
355                }
356            }
357        }
358        Data::Enum(data) => {
359            let mut arms = Vec::new();
360            for (i, variant) in data.variants.iter().enumerate() {
361                let variant_name = &variant.ident;
362                let tag = i as u32;
363
364                match &variant.fields {
365                    Fields::Unit => {
366                        // Unit 变体:匹配索引后直接返回
367                        // Unit variant: match index and return directly
368                        arms.push(quote! {
369                            #tag => {
370                                Ok((#name::#variant_name, offset))
371                            }
372                        });
373                    }
374                    Fields::Unnamed(fields) => {
375                        // 元组变体:匹配索引后逐字段反序列化
376                        // Tuple variant: match index, then deserialize fields sequentially
377                        let mut field_desers = Vec::new();
378                        let mut field_names = Vec::new();
379                        for _ in &fields.unnamed {
380                            let fname = syn::Ident::new(
381                                &format!("__f{}", field_names.len()),
382                                variant_name.span(),
383                            );
384                            field_desers.push(quote! {
385                                let (__val, __new_offset) = ::afastdata_core::AFastDeserialize::from_bytes(&data[offset..])?;
386                                let #fname = __val;
387                                offset += __new_offset;
388                            });
389                            field_names.push(fname);
390                        }
391                        arms.push(quote! {
392                            #tag => {
393                                #(#field_desers)*
394                                Ok((#name::#variant_name(#(#field_names),*), offset))
395                            }
396                        });
397                    }
398                    Fields::Named(fields) => {
399                        // 命名字段变体:匹配索引后逐字段反序列化
400                        // Named-field variant: match index, then deserialize fields sequentially
401                        let mut field_desers = Vec::new();
402                        let mut field_names = Vec::new();
403                        for f in &fields.named {
404                            let fname = f.ident.as_ref().unwrap();
405                            field_desers.push(quote! {
406                                let (__val, __new_offset) = ::afastdata_core::AFastDeserialize::from_bytes(&data[offset..])?;
407                                let #fname = __val;
408                                offset += __new_offset;
409                            });
410                            field_names.push(fname);
411                        }
412                        arms.push(quote! {
413                            #tag => {
414                                #(#field_desers)*
415                                Ok((#name::#variant_name { #(#field_names),* }, offset))
416                            }
417                        });
418                    }
419                }
420            }
421
422            quote! {
423                impl #impl_generics ::afastdata_core::AFastDeserialize for #name #ty_generics {
424                    fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::std::string::String> {
425                        let mut offset: usize = 0;
426                        // 读取 u32 变体索引
427                        // Read the u32 variant index
428                        let (__tag_bytes, __new_offset) = <u32 as ::afastdata_core::AFastDeserialize>::from_bytes(&data[offset..])?;
429                        offset += __new_offset;
430                        match __tag_bytes {
431                            #(#arms)*
432                            v => Err(::std::format!("Unknown variant tag: {} for {}", v, ::std::stringify!(#name))),
433                        }
434                    }
435                }
436            }
437        }
438        Data::Union(_) => panic!("AFastDeserialize does not support unions"),
439    };
440
441    TokenStream::from(expanded)
442}
443
444/// 为结构体的字段生成序列化代码。内部辅助函数。
445///
446/// Generates serialization code for struct fields. Internal helper.
447///
448/// # 参数 / Parameters
449///
450/// - `fields`:结构体的字段定义 / The struct's field definitions
451/// - `self_prefix`:访问字段时使用的前缀(如 `self` 或变体解构变量)
452///   / The prefix used to access fields (e.g., `self` or a variant destructure variable)
453///
454/// # 返回值 / Returns
455///
456/// 返回一个 `TokenStream` 列表,每个元素对应一个字段的序列化语句。
457///
458/// Returns a list of `TokenStream`s, each corresponding to a serialization statement
459/// for one field.
460///
461/// # 生成格式 / Generated Format
462///
463/// - **命名字段 (Named)**:`bytes.extend(AFastSerialize::to_bytes(&self.field_name));`
464/// - **元组字段 (Unnamed)**:`bytes.extend(AFastSerialize::to_bytes(&self.0));`
465/// - **单元字段 (Unit)**:不生成任何代码 / Generates no code
466fn generate_serialize_fields(
467    fields: &Fields,
468    self_prefix: proc_macro2::TokenStream,
469) -> Vec<proc_macro2::TokenStream> {
470    match fields {
471        Fields::Named(named) => named
472            .named
473            .iter()
474            .map(|f| {
475                let fname = f.ident.as_ref().unwrap();
476                quote! {
477                    bytes.extend(::afastdata_core::AFastSerialize::to_bytes(&#self_prefix.#fname));
478                }
479            })
480            .collect(),
481        Fields::Unnamed(unnamed) => unnamed
482            .unnamed
483            .iter()
484            .enumerate()
485            .map(|(i, _)| {
486                let idx = Index::from(i);
487                quote! {
488                    bytes.extend(::afastdata_core::AFastSerialize::to_bytes(&#self_prefix.#idx));
489                }
490            })
491            .collect(),
492        Fields::Unit => vec![],
493    }
494}
495
496/// 为结构体的字段生成反序列化代码以及构造表达式。内部辅助函数。
497///
498/// Generates deserialization code for struct fields along with the construction
499/// expression. Internal helper.
500///
501/// # 参数 / Parameters
502///
503/// - `fields`:结构体的字段定义 / The struct's field definitions
504/// - `name`:结构体类型的标识符 / The struct type's identifier
505/// - `ty_generics`:类型的泛型参数(用于构造时的 turbofish 语法)
506///   / The type's generic parameters (used for turbofish syntax during construction)
507///
508/// # 返回值 / Returns
509///
510/// 返回 `(构造表达式, 反序列化语句列表)`:
511/// - 构造表达式:用于创建结构体实例的 `TokenStream`
512/// - 反序列化语句:每个字段的 `from_bytes()` 调用和偏移量更新
513///
514/// Returns `(construction_expression, deserialization_statements)`:
515/// - Construction expression: A `TokenStream` for creating the struct instance
516/// - Deserialization statements: `from_bytes()` calls and offset updates for each field
517///
518/// # 泛型构造 / Generic Construction
519///
520/// 使用 `as_turbofish()` 生成正确的泛型语法。例如 `MyStruct::<T>` 而非
521/// `MyStruct <T>`(后者会被解析为比较操作)。
522///
523/// Uses `as_turbofish()` to generate correct generic syntax. For example,
524/// `MyStruct::<T>` instead of `MyStruct <T>` (which would be parsed as a
525/// comparison operation).
526fn generate_deserialize_fields(
527    fields: &Fields,
528    name: &syn::Ident,
529    ty_generics: &syn::TypeGenerics,
530) -> (proc_macro2::TokenStream, Vec<proc_macro2::TokenStream>) {
531    // 在表达式上下文中使用 turbofish 语法:Name::<T>
532    // In expression context, use turbofish syntax: Name::<T>
533    let ty_params = ty_generics.as_turbofish();
534    match fields {
535        Fields::Named(named) => {
536            let mut desers = Vec::new();
537            let mut field_names = Vec::new();
538            for f in &named.named {
539                let fname = f.ident.as_ref().unwrap();
540                field_names.push(fname.clone());
541                desers.push(quote! {
542                    let (__val, __new_offset) = ::afastdata_core::AFastDeserialize::from_bytes(&data[offset..])?;
543                    let #fname = __val;
544                    offset += __new_offset;
545                });
546            }
547            let construct = quote! {
548                #name #ty_params { #(#field_names),* }
549            };
550            (construct, desers)
551        }
552        Fields::Unnamed(unnamed) => {
553            let mut desers = Vec::new();
554            let mut field_names = Vec::new();
555            for i in 0..unnamed.unnamed.len() {
556                let fname = syn::Ident::new(&format!("__f{}", i), name.span());
557                desers.push(quote! {
558                    let (__val, __new_offset) = ::afastdata_core::AFastDeserialize::from_bytes(&data[offset..])?;
559                    let #fname = __val;
560                    offset += __new_offset;
561                });
562                field_names.push(fname);
563            }
564            let construct = quote! {
565                #name #ty_params ( #(#field_names),* )
566            };
567            (construct, desers)
568        }
569        Fields::Unit => {
570            let construct = quote! { #name #ty_params };
571            (construct, vec![])
572        }
573    }
574}