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//! ```
49//! extern crate afastdata;
50//! use afastdata::{AFastSerialize, AFastDeserialize};
51//!
52//! #[derive(AFastSerialize, AFastDeserialize, Debug, PartialEq)]
53//! struct Point {
54//!     x: i32,
55//!     y: i32,
56//! }
57//!
58//! #[derive(AFastSerialize, AFastDeserialize, Debug, PartialEq)]
59//! enum Shape {
60//!     Circle(f64),
61//!     Rectangle { width: f64, height: f64 },
62//!     Empty,
63//! }
64//!
65//! // 序列化 / Serialize
66//! let point = Point { x: 10, y: 20 };
67//! let bytes = point.to_bytes();
68//!
69//! // 反序列化 / Deserialize
70//! let (decoded, _) = Point::from_bytes(&bytes).unwrap();
71//! assert_eq!(point, decoded);
72//! ```
73
74use proc_macro::TokenStream;
75use quote::quote;
76use syn::{
77    Attribute, Data, DeriveInput, Fields, Index, Lit, LitFloat, LitInt, LitStr, Meta, Path, Token, Type,
78    TypePath,
79    parse::{Parse, ParseStream},
80    parse_macro_input,
81    punctuated::Punctuated,
82};
83
84/// 返回枚举变体标签的类型和字节大小,基于编译时 feature 配置。
85///
86/// Returns the enum variant tag type and byte size based on compile-time feature config.
87fn tag_type() -> (proc_macro2::TokenStream, usize) {
88    if cfg!(feature = "tag-u16") {
89        (quote! { u16 }, 2)
90    } else if cfg!(feature = "tag-u32") {
91        (quote! { u32 }, 4)
92    } else {
93        (quote! { u8 }, 1)
94    }
95}
96
97/// 为结构体或枚举生成 [`AFastSerialize`] trait 实现。
98///
99/// Generates an [`AFastSerialize`] trait implementation for a struct or enum.
100///
101/// # 生成的代码 / Generated Code
102///
103/// ## 结构体 / Struct
104///
105/// 为每个字段调用 `to_bytes()`,并将结果依次追加到字节缓冲区中。
106///
107/// Calls `to_bytes()` on each field, appending the results to a byte buffer
108/// sequentially.
109///
110/// ```text
111/// // 以下为生成代码的示意(非实际代码)
112/// // The following is an illustration of generated code (not actual code)
113/// impl AFastSerialize for MyStruct {
114///     fn to_bytes(&self) -> Vec<u8> {
115///         let mut bytes = Vec::new();
116///         bytes.extend(AFastSerialize::to_bytes(&self.field1));
117///         bytes.extend(AFastSerialize::to_bytes(&self.field2));
118///         // ... 依次处理每个字段 / remaining fields processed similarly
119///         bytes
120///     }
121/// }
122/// ```
123///
124/// ## 枚举 / Enum
125///
126/// 先写入 `u8` 变体索引(从 0 开始),再写入变体的字段数据。
127/// Unit 变体只写入索引。可通过 feature 切换为 `u16` 或 `u32`。
128///
129/// Writes a `u8` variant index (starting from 0), then the variant's field data.
130/// Unit variants only write the index. Switchable to `u16` or `u32` via features.
131///
132/// ```text
133/// // 以下为生成代码的示意(非实际代码)
134/// // The following is an illustration of generated code (not actual code)
135/// impl AFastSerialize for MyEnum {
136///     fn to_bytes(&self) -> Vec<u8> {
137///         let mut bytes = Vec::new();
138///         match self {
139///             MyEnum::Variant1 => {
140///                 bytes.extend(0u8.to_le_bytes());
141///             }
142///             MyEnum::Variant2(field) => {
143///                 bytes.extend(1u8.to_le_bytes());
144///                 bytes.extend(AFastSerialize::to_bytes(field));
145///             }
146///             // ...
147///         }
148///         bytes
149///     }
150/// }
151/// ```
152///
153/// # 泛型 / Generics
154///
155/// 如果目标类型包含泛型参数,生成的 `impl` 会自动为这些参数添加
156/// `AFastSerialize` 约束。
157///
158/// If the target type contains generic parameters, the generated `impl` automatically
159/// adds `AFastSerialize` bounds to those parameters.
160///
161/// # Panics
162///
163/// 对 union 类型使用此宏会触发编译 panic。
164///
165/// Using this macro on a union type will trigger a compile-time panic.
166#[proc_macro_derive(AFastSerialize, attributes(afast))]
167pub fn derive_serialize(input: TokenStream) -> TokenStream {
168    let input = parse_macro_input!(input as DeriveInput);
169    let name = &input.ident;
170    let generics = &input.generics;
171
172    // 为泛型参数添加 AFastSerialize trait 约束
173    // Add AFastSerialize trait bounds to generic parameters
174    let mut generics_with_bounds = generics.clone();
175    for param in &mut generics_with_bounds.params {
176        if let syn::GenericParam::Type(ref mut ty) = *param {
177            ty.bounds
178                .push(syn::parse_quote!(::afastdata::AFastSerialize));
179        }
180    }
181    let (impl_generics, _, _) = generics_with_bounds.split_for_impl();
182    let (_, ty_generics, _) = generics.split_for_impl();
183
184    let expanded = match &input.data {
185        Data::Struct(data) => {
186            let serialize_body = generate_serialize_fields(&data.fields, quote!(self));
187            quote! {
188                impl #impl_generics ::afastdata::AFastSerialize for #name #ty_generics {
189                    fn to_bytes(&self) -> Vec<u8> {
190                        let mut bytes = Vec::new();
191                        #(#serialize_body)*
192                        bytes
193                    }
194                }
195            }
196        }
197        Data::Enum(data) => {
198            let (tag_ty, _) = tag_type();
199            let mut arms = Vec::new();
200            for (i, variant) in data.variants.iter().enumerate() {
201                let variant_name = &variant.ident;
202
203                match &variant.fields {
204                    Fields::Unit => {
205                        arms.push(quote! {
206                            #name::#variant_name => {
207                                bytes.extend((#i as #tag_ty).to_le_bytes());
208                            }
209                        });
210                    }
211                    Fields::Unnamed(fields) => {
212                        let field_names: Vec<_> = (0..fields.unnamed.len())
213                            .map(|i| {
214                                syn::Ident::new(&format!("__f{}", i), variant_name.span())
215                            })
216                            .collect();
217                        let field_patterns = &field_names;
218                        let mut serialize_fields = Vec::new();
219                        for (i, f) in fields.unnamed.iter().enumerate() {
220                            if !has_skip_attr(&f.attrs).0 {
221                                let fname = &field_names[i];
222                                serialize_fields.push(quote! {
223                                    bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
224                                });
225                            }
226                        }
227                        arms.push(quote! {
228                            #name::#variant_name(#(#field_patterns),*) => {
229                                bytes.extend((#i as #tag_ty).to_le_bytes());
230                                #(#serialize_fields)*
231                            }
232                        });
233                    }
234                    Fields::Named(fields) => {
235                        let all_field_names: Vec<_> = fields
236                            .named
237                            .iter()
238                            .map(|f| f.ident.as_ref().unwrap())
239                            .collect();
240                        let non_skip_names: Vec<_> = fields
241                            .named
242                            .iter()
243                            .filter(|f| !has_skip_attr(&f.attrs).0)
244                            .map(|f| f.ident.as_ref().unwrap())
245                            .collect();
246                        let has_skip = non_skip_names.len() < all_field_names.len();
247                        let mut serialize_fields = Vec::new();
248                        for fname in &non_skip_names {
249                            serialize_fields.push(quote! {
250                                bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
251                            });
252                        }
253                        if has_skip {
254                            arms.push(quote! {
255                                #name::#variant_name { #(#non_skip_names),*, .. } => {
256                                    bytes.extend((#i as #tag_ty).to_le_bytes());
257                                    #(#serialize_fields)*
258                                }
259                            });
260                        } else {
261                            arms.push(quote! {
262                                #name::#variant_name { #(#non_skip_names),* } => {
263                                    bytes.extend((#i as #tag_ty).to_le_bytes());
264                                    #(#serialize_fields)*
265                                }
266                            });
267                        }
268                    }
269                }
270            }
271
272            quote! {
273                impl #impl_generics ::afastdata::AFastSerialize for #name #ty_generics {
274                    fn to_bytes(&self) -> Vec<u8> {
275                        let mut bytes = Vec::new();
276                        match self {
277                            #(#arms)*
278                        }
279                        bytes
280                    }
281                }
282            }
283        }
284        Data::Union(_) => panic!("AFastSerialize does not support unions"),
285    };
286
287    TokenStream::from(expanded)
288}
289
290/// 为结构体或枚举生成 [`AFastDeserialize`] trait 实现。
291///
292/// Generates an [`AFastDeserialize`] trait implementation for a struct or enum.
293///
294/// # 生成的代码 / Generated Code
295///
296/// ## 结构体 / Struct
297///
298/// 为每个字段依次调用 `from_bytes()`,并使用偏移量追踪已消耗的字节数,
299/// 最后构造结构体实例。
300///
301/// Calls `from_bytes()` on each field sequentially, using an offset to track
302/// consumed bytes, then constructs the struct instance.
303///
304/// ```text
305/// // 以下为生成代码的示意(非实际代码)
306/// // The following is an illustration of generated code (not actual code)
307/// impl AFastDeserialize for MyStruct {
308///     fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
309///         let mut offset: usize = 0;
310///         let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
311///         let field1 = __val;
312///         offset += __new_offset;
313///         // ... 更多字段 / more fields ...
314///         Ok((MyStruct { field1, ... }, offset))
315///     }
316/// }
317/// ```
318///
319/// ## 枚举 / Enum
320///
321/// 先读取 `u8` 变体索引,根据索引匹配对应变体,再反序列化该变体的字段。
322/// 可通过 feature 切换为 `u16` 或 `u32`。
323///
324/// First reads the `u8` variant index, matches the corresponding variant by index,
325/// then deserializes the variant's fields.
326/// Switchable to `u16` or `u32` via features.
327///
328/// ```text
329/// // 以下为生成代码的示意(非实际代码)
330/// // The following is an illustration of generated code (not actual code)
331/// impl AFastDeserialize for MyEnum {
332///     fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
333///         let mut offset: usize = 0;
334///         let (__tag, __new_offset) = <u8 as AFastDeserialize>::from_bytes(&data[offset..])?;
335///         offset += __new_offset;
336///         match __tag as usize {
337///             0 => Ok((MyEnum::Variant1, offset)),
338///             1 => {
339///                 let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
340///                 offset += __new_offset;
341///                 Ok((MyEnum::Variant2(__val), offset))
342///             }
343///             v => Err(format!("Unknown variant tag: {} for MyEnum", v)),
344///         }
345///     }
346/// }
347/// ```
348///
349/// # 泛型 / Generics
350///
351/// 如果目标类型包含泛型参数,生成的 `impl` 会同时添加 `AFastSerialize` 和
352/// `AFastDeserialize` 约束。双重约束确保泛型类型在序列化和反序列化两个方向
353/// 上都可用。
354///
355/// If the target type contains generic parameters, the generated `impl` adds both
356/// `AFastSerialize` and `AFastDeserialize` bounds. The dual bounds ensure the generic
357/// type is available in both serialization and deserialization directions.
358///
359/// # Panics
360///
361/// 对 union 类型使用此宏会触发编译 panic。
362///
363/// Using this macro on a union type will trigger a compile-time panic.
364#[proc_macro_derive(AFastDeserialize, attributes(afast))]
365pub fn derive_deserialize(input: TokenStream) -> TokenStream {
366    let input = parse_macro_input!(input as DeriveInput);
367    let name = &input.ident;
368    let generics = &input.generics;
369
370    // 为泛型参数添加 AFastSerialize + AFastDeserialize trait 约束
371    // Add AFastSerialize + AFastDeserialize trait bounds to generic parameters
372    let mut generics_with_bounds = generics.clone();
373    for param in &mut generics_with_bounds.params {
374        if let syn::GenericParam::Type(ref mut ty) = *param {
375            ty.bounds
376                .push(syn::parse_quote!(::afastdata::AFastSerialize));
377            ty.bounds
378                .push(syn::parse_quote!(::afastdata::AFastDeserialize));
379        }
380    }
381    let (impl_generics, _, _) = generics_with_bounds.split_for_impl();
382    let (_, ty_generics, _) = generics.split_for_impl();
383
384    let expanded = match &input.data {
385        Data::Struct(data) => {
386            let (construct, field_desers) =
387                generate_deserialize_fields(&data.fields, name, &ty_generics);
388            quote! {
389                impl #impl_generics ::afastdata::AFastDeserialize for #name #ty_generics {
390                    fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::afastdata::Error> {
391                        let mut offset: usize = 0;
392                        #(#field_desers)*
393                        Ok((#construct, offset))
394                    }
395                }
396            }
397        }
398        Data::Enum(data) => {
399            let (tag_ty, _) = tag_type();
400            let mut arms = Vec::new();
401            for (i, variant) in data.variants.iter().enumerate() {
402                let variant_name = &variant.ident;
403
404                match &variant.fields {
405                    Fields::Unit => {
406                        arms.push(quote! {
407                            #i => {
408                                Ok((#name::#variant_name, offset))
409                            }
410                        });
411                    }
412                    Fields::Unnamed(fields) => {
413                        let mut field_desers = Vec::new();
414                        let mut field_names = Vec::new();
415                        for (i, f) in fields.unnamed.iter().enumerate() {
416                            let fname = syn::Ident::new(
417                                &format!("__f{}", i),
418                                variant_name.span(),
419                            );
420                            let ftype = &f.ty;
421                            let (skip, default_fn) = has_skip_attr(&f.attrs);
422                            if skip {
423                                if let Some(func_name) = default_fn {
424                                    match syn::parse_str::<syn::Ident>(&func_name) {
425                                        Ok(ident) => {
426                                            field_desers.push(quote! {
427                                                let #fname: #ftype = #ident();
428                                            });
429                                        }
430                                        Err(_) => {
431                                            field_desers.push(quote! {
432                                                compile_error!(concat!("invalid function name in skip: ", #func_name));
433                                            });
434                                        }
435                                    }
436                                } else {
437                                    field_desers.push(quote! {
438                                        let #fname: #ftype = <#ftype as ::std::default::Default>::default();
439                                    });
440                                }
441                            } else {
442                                let validates = parse_validations(&fname, ftype, &f.attrs);
443                                field_desers.push(quote! {
444                                    let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
445                                    let #fname: #ftype = __val;
446                                    #(#validates)*
447                                    offset += __new_offset;
448                                });
449                            }
450                            field_names.push(fname);
451                        }
452                        arms.push(quote! {
453                            #i => {
454                                #(#field_desers)*
455                                Ok((#name::#variant_name(#(#field_names),*), offset))
456                            }
457                        });
458                    }
459                    Fields::Named(fields) => {
460                        let mut field_desers = Vec::new();
461                        let mut field_names = Vec::new();
462                        for f in &fields.named {
463                            let fname = f.ident.as_ref().unwrap();
464                            let ftype = &f.ty;
465                            let (skip, default_fn) = has_skip_attr(&f.attrs);
466                            if skip {
467                                if let Some(func_name) = default_fn {
468                                    match syn::parse_str::<syn::Ident>(&func_name) {
469                                        Ok(ident) => {
470                                            field_desers.push(quote! {
471                                                let #fname: #ftype = #ident();
472                                            });
473                                        }
474                                        Err(_) => {
475                                            field_desers.push(quote! {
476                                                compile_error!(concat!("invalid function name in skip: ", #func_name));
477                                            });
478                                        }
479                                    }
480                                } else {
481                                    field_desers.push(quote! {
482                                        let #fname: #ftype = <#ftype as ::std::default::Default>::default();
483                                    });
484                                }
485                            } else {
486                                let validates = parse_validations(fname, ftype, &f.attrs);
487                                field_desers.push(quote! {
488                                    let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
489                                    let #fname: #ftype = __val;
490                                    #(#validates)*
491                                    offset += __new_offset;
492                                });
493                            }
494                            field_names.push(fname);
495                        }
496                        arms.push(quote! {
497                            #i => {
498                                #(#field_desers)*
499                                Ok((#name::#variant_name { #(#field_names),* }, offset))
500                            }
501                        });
502                    }
503                }
504            }
505
506            quote! {
507                impl #impl_generics ::afastdata::AFastDeserialize for #name #ty_generics {
508                    fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::afastdata::Error> {
509                        let mut offset: usize = 0;
510                        let (__tag_bytes, __new_offset) = <#tag_ty as ::afastdata::AFastDeserialize>::from_bytes(&data[offset..])?;
511                        offset += __new_offset;
512                        match __tag_bytes as usize {
513                            #(#arms)*
514                            v => Err(::afastdata::Error::deserialize(format!("Unknown variant tag: {} for {}", v, ::std::stringify!(#name)))),
515                        }
516                    }
517                }
518            }
519        }
520        Data::Union(_) => panic!("AFastDeserialize does not support unions"),
521    };
522
523    TokenStream::from(expanded)
524}
525
526/// 为结构体的字段生成序列化代码。内部辅助函数。
527///
528/// Generates serialization code for struct fields. Internal helper.
529///
530/// # 参数 / Parameters
531///
532/// - `fields`:结构体的字段定义 / The struct's field definitions
533/// - `self_prefix`:访问字段时使用的前缀(如 `self` 或变体解构变量)
534///   / The prefix used to access fields (e.g., `self` or a variant destructure variable)
535///
536/// # 返回值 / Returns
537///
538/// 返回一个 `TokenStream` 列表,每个元素对应一个字段的序列化语句。
539///
540/// Returns a list of `TokenStream`s, each corresponding to a serialization statement
541/// for one field.
542///
543/// # 生成格式 / Generated Format
544///
545/// - **命名字段 (Named)**:`bytes.extend(AFastSerialize::to_bytes(&self.field_name));`
546/// - **元组字段 (Unnamed)**:`bytes.extend(AFastSerialize::to_bytes(&self.0));`
547/// - **单元字段 (Unit)**:不生成任何代码 / Generates no code
548fn generate_serialize_fields(
549    fields: &Fields,
550    self_prefix: proc_macro2::TokenStream,
551) -> Vec<proc_macro2::TokenStream> {
552    match fields {
553        Fields::Named(named) => named
554            .named
555            .iter()
556            .filter(|f| !has_skip_attr(&f.attrs).0)
557            .map(|f| {
558                let fname = f.ident.as_ref().unwrap();
559                quote! {
560                    bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#fname));
561                }
562            })
563            .collect(),
564        Fields::Unnamed(unnamed) => unnamed
565            .unnamed
566            .iter()
567            .enumerate()
568            .filter(|(_, f)| !has_skip_attr(&f.attrs).0)
569            .map(|(i, _)| {
570                let idx = Index::from(i);
571                quote! {
572                    bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#idx));
573                }
574            })
575            .collect(),
576        Fields::Unit => vec![],
577    }
578}
579
580fn has_skip_attr(attrs: &[Attribute]) -> (bool, Option<String>) {
581    for attr in attrs {
582        if attr.path().is_ident("afast")
583            && let Ok(nested) =
584                attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
585        {
586            for meta in nested {
587                match meta {
588                    Meta::Path(path) if path.is_ident("skip") => {
589                        return (true, None);
590                    }
591                    Meta::List(meta_list) if meta_list.path.is_ident("skip") => {
592                        if let Ok(lit_str) = syn::parse2::<LitStr>(meta_list.tokens.clone()) {
593                            return (true, Some(lit_str.value()));
594                        } else {
595                            return (true, None);
596                        }
597                    }
598                    _ => {}
599                }
600            }
601        }
602    }
603    (false, None)
604}
605
606enum RangeValue {
607    Int(LitInt),
608    Float(LitFloat),
609}
610
611impl RangeValue {
612    fn to_token_stream(&self) -> proc_macro2::TokenStream {
613        match self {
614            RangeValue::Int(v) => quote! { #v },
615            RangeValue::Float(v) => quote! { #v },
616        }
617    }
618}
619
620struct Range {
621    value: RangeValue,
622    _comma1: Token![,],
623    code: LitInt,
624    _comma2: Token![,],
625    msg: LitStr,
626}
627
628impl Parse for Range {
629    fn parse(input: ParseStream) -> syn::Result<Self> {
630        // Try to parse as float first, then as int
631        let value = if input.peek(LitFloat) {
632            RangeValue::Float(input.parse()?)
633        } else {
634            RangeValue::Int(input.parse()?)
635        };
636        Ok(Range {
637            value,
638            _comma1: input.parse()?,
639            code: input.parse()?,
640            _comma2: input.parse()?,
641            msg: input.parse()?,
642        })
643    }
644}
645
646struct Length {
647    min: LitInt,
648    _comma1: Token![,],
649    max: LitInt,
650    _comma2: Token![,],
651    code: LitInt,
652    _comma3: Token![,],
653    msg: LitStr,
654}
655
656impl Parse for Length {
657    fn parse(input: ParseStream) -> syn::Result<Self> {
658        Ok(Length {
659            min: input.parse()?,
660            _comma1: input.parse()?,
661            max: input.parse()?,
662            _comma2: input.parse()?,
663            code: input.parse()?,
664            _comma3: input.parse()?,
665            msg: input.parse()?,
666        })
667    }
668}
669
670#[derive(Clone)]
671enum ValidateValue {
672    Int(i64),
673    Float(f64),
674    Bool(bool),
675    Str(String),
676}
677
678impl ValidateValue {
679    /// 将值转换为代码生成中使用的 TokenStream
680    ///
681    /// 例如:
682    /// ValidateValue::Int(42) → quote! { 42 }
683    /// ValidateValue::Str("hello") → quote! { "hello" }
684    fn to_token_stream(&self) -> proc_macro2::TokenStream {
685        match self {
686            ValidateValue::Int(v) => quote! { #v },
687
688            ValidateValue::Float(v) => {
689                // 浮点数通过字符串解析来保持精度
690                let v_str = v.to_string();
691                v_str.parse().unwrap_or_else(|_| {
692                    // 如果字符串解析失败,使用直接值
693                    quote! { #v }
694                })
695            }
696
697            ValidateValue::Bool(v) => quote! { #v },
698            ValidateValue::Str(v) => quote! { #v },
699        }
700    }
701}
702
703struct OfValidator {
704    allowed_values: Vec<ValidateValue>,
705    code: syn::LitInt,
706    msg: syn::LitStr,
707}
708
709impl Parse for OfValidator {
710    fn parse(input: ParseStream) -> syn::Result<Self> {
711        let content;
712        syn::bracketed!(content in input);
713
714        let mut values = Vec::new();
715
716        if !content.is_empty() {
717            loop {
718                let lit = content.parse::<Lit>()?;
719
720                let value = match lit {
721                    Lit::Int(lit_int) => {
722                        let int_value: i64 = lit_int.base10_parse()?;
723                        ValidateValue::Int(int_value)
724                    }
725
726                    Lit::Float(lit_float) => {
727                        let float_value: f64 = lit_float.base10_parse()?;
728                        ValidateValue::Float(float_value)
729                    }
730
731                    Lit::Bool(lit_bool) => ValidateValue::Bool(lit_bool.value),
732
733                    Lit::Str(lit_str) => ValidateValue::Str(lit_str.value()),
734
735                    _ => {
736                        return Err(syn::Error::new_spanned(
737                            &lit,
738                            "unsupported literal type in 'of' validator; \
739                             only int, float, bool, and str literals are supported",
740                        ));
741                    }
742                };
743
744                values.push(value);
745
746                if !content.peek(Token![,]) {
747                    break;
748                }
749
750                content.parse::<Token![,]>()?;
751
752                if content.is_empty() {
753                    break;
754                }
755            }
756        }
757
758        input.parse::<Token![,]>()?;
759
760        let code = input.parse::<syn::LitInt>()?;
761
762        input.parse::<Token![,]>()?;
763
764        let msg = input.parse::<syn::LitStr>()?;
765
766        Ok(OfValidator {
767            allowed_values: values,
768            code,
769            msg,
770        })
771    }
772}
773
774/// 检测字段类型是否为数值类型(i8..i128, u8..u128, f32, f64)。
775///
776/// Checks whether the field type is a numeric type.
777fn is_numeric_type(ty: &Type) -> bool {
778    if let Type::Path(TypePath { path, .. }) = ty {
779        if let Some(segment) = path.segments.last() {
780            let name = segment.ident.to_string();
781            return matches!(
782                name.as_str(),
783                "i8" | "i16"
784                    | "i32"
785                    | "i64"
786                    | "i128"
787                    | "u8"
788                    | "u16"
789                    | "u32"
790                    | "u64"
791                    | "u128"
792                    | "f32"
793                    | "f64"
794            );
795        }
796    }
797    false
798}
799
800/// 检测字段类型是否为 Option<T>。
801///
802/// Checks whether the field type is `Option<T>`.
803fn is_option_type(ty: &Type) -> bool {
804    if let Type::Path(TypePath {
805        path: Path { segments, .. },
806        ..
807    }) = ty
808    {
809        segments.len() == 1 && segments[0].ident == "Option"
810    } else {
811        false
812    }
813}
814
815/// 检测字段类型是否为字符串或集合类型(String, &str, Vec<T>, [T; N])。
816///
817/// Checks whether the field type is a string or collection type.
818fn is_collection_type(ty: &Type) -> bool {
819    if let Type::Path(TypePath { path, .. }) = ty {
820        if let Some(segment) = path.segments.last() {
821            let name = segment.ident.to_string();
822            return matches!(name.as_str(), "String" | "Vec" | "BTreeSet" | "BTreeMap" | "HashSet" | "HashMap");
823        }
824    }
825    // [T; N] arrays
826    if let Type::Array(_) = ty {
827        return true;
828    }
829    // &str
830    if let Type::Reference(r) = ty {
831        if let Type::Path(TypePath { path, .. }) = &*r.elem {
832            if let Some(segment) = path.segments.last() {
833                return segment.ident == "str";
834            }
835        }
836    }
837    false
838}
839
840/// 解析字段上的 `#[afast(...)]` 校验属性,生成校验代码。
841///
842/// Parses `#[afast(...)]` validation attributes on a field and generates
843/// validation code blocks.
844///
845/// # 参数 / Parameters
846///
847/// - `field_name`:字段名 / Field name
848/// - `field_type`:字段类型 / Field type
849/// - `attrs`:字段的属性列表 / Field attributes
850///
851/// # 返回值 / Returns
852///
853/// 返回校验语句的 `TokenStream` 列表。
854///
855/// Returns a list of validation `TokenStream` blocks.
856fn parse_validations(
857    field_name: &syn::Ident,
858    field_type: &Type,
859    attrs: &[Attribute],
860) -> Vec<proc_macro2::TokenStream> {
861    let mut validates = Vec::new();
862    for attr in attrs {
863        if attr.path().is_ident("afast") {
864            let nested = match attr
865                .parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
866            {
867                Ok(n) => n,
868                Err(e) => {
869                    validates.push(e.to_compile_error());
870                    continue;
871                }
872            };
873            for meta in nested {
874                if let Meta::List(meta) = meta {
875                        if meta.path.is_ident("gt") {
876                            if !is_numeric_type(field_type) {
877                                validates.push(
878                                    syn::Error::new_spanned(
879                                        &meta.path,
880                                        format!(
881                                            "validation `gt` is only supported on numeric types, but field `{}` is not",
882                                            field_name
883                                        ),
884                                    )
885                                    .to_compile_error(),
886                                );
887                                continue;
888                            }
889                            let inner = match meta.parse_args::<Range>() {
890                                Ok(v) => v,
891                                Err(e) => {
892                                    validates.push(e.to_compile_error());
893                                    continue;
894                                }
895                            };
896                            let cmp_value = inner.value.to_token_stream();
897                            let code = match inner.code.base10_parse::<i64>() {
898                                Ok(v) => v,
899                                Err(e) => {
900                                    validates.push(
901                                        syn::Error::new_spanned(&inner.code, format!("invalid error code: {}", e))
902                                            .to_compile_error(),
903                                    );
904                                    continue;
905                                }
906                            };
907                            let err_msg = inner
908                                .msg
909                                .value()
910                                .replace("${field}", &field_name.to_string());
911                            validates.push(quote! {
912                                if #field_name <= #cmp_value {
913                                    return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
914                                }
915                            });
916                        } else if meta.path.is_ident("gte") {
917                            if !is_numeric_type(field_type) {
918                                validates.push(
919                                    syn::Error::new_spanned(
920                                        &meta.path,
921                                        format!(
922                                            "validation `gte` is only supported on numeric types, but field `{}` is not",
923                                            field_name
924                                        ),
925                                    )
926                                    .to_compile_error(),
927                                );
928                                continue;
929                            }
930                            let inner = match meta.parse_args::<Range>() {
931                                Ok(v) => v,
932                                Err(e) => {
933                                    validates.push(e.to_compile_error());
934                                    continue;
935                                }
936                            };
937                            let cmp_value = inner.value.to_token_stream();
938                            let code = match inner.code.base10_parse::<i64>() {
939                                Ok(v) => v,
940                                Err(e) => {
941                                    validates.push(
942                                        syn::Error::new_spanned(&inner.code, format!("invalid error code: {}", e))
943                                            .to_compile_error(),
944                                    );
945                                    continue;
946                                }
947                            };
948                            let err_msg = inner
949                                .msg
950                                .value()
951                                .replace("${field}", &field_name.to_string());
952                            validates.push(quote! {
953                                if #field_name < #cmp_value {
954                                    return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
955                                }
956                            });
957                        } else if meta.path.is_ident("lt") {
958                            if !is_numeric_type(field_type) {
959                                validates.push(
960                                    syn::Error::new_spanned(
961                                        &meta.path,
962                                        format!(
963                                            "validation `lt` is only supported on numeric types, but field `{}` is not",
964                                            field_name
965                                        ),
966                                    )
967                                    .to_compile_error(),
968                                );
969                                continue;
970                            }
971                            let inner = match meta.parse_args::<Range>() {
972                                Ok(v) => v,
973                                Err(e) => {
974                                    validates.push(e.to_compile_error());
975                                    continue;
976                                }
977                            };
978                            let cmp_value = inner.value.to_token_stream();
979                            let code = match inner.code.base10_parse::<i64>() {
980                                Ok(v) => v,
981                                Err(e) => {
982                                    validates.push(
983                                        syn::Error::new_spanned(&inner.code, format!("invalid error code: {}", e))
984                                            .to_compile_error(),
985                                    );
986                                    continue;
987                                }
988                            };
989                            let err_msg = inner
990                                .msg
991                                .value()
992                                .replace("${field}", &field_name.to_string());
993                            validates.push(quote! {
994                                if #field_name >= #cmp_value {
995                                    return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
996                                }
997                            });
998                        } else if meta.path.is_ident("lte") {
999                            if !is_numeric_type(field_type) {
1000                                validates.push(
1001                                    syn::Error::new_spanned(
1002                                        &meta.path,
1003                                        format!(
1004                                            "validation `lte` is only supported on numeric types, but field `{}` is not",
1005                                            field_name
1006                                        ),
1007                                    )
1008                                    .to_compile_error(),
1009                                );
1010                                continue;
1011                            }
1012                            let inner = match meta.parse_args::<Range>() {
1013                                Ok(v) => v,
1014                                Err(e) => {
1015                                    validates.push(e.to_compile_error());
1016                                    continue;
1017                                }
1018                            };
1019                            let cmp_value = inner.value.to_token_stream();
1020                            let code = match inner.code.base10_parse::<i64>() {
1021                                Ok(v) => v,
1022                                Err(e) => {
1023                                    validates.push(
1024                                        syn::Error::new_spanned(&inner.code, format!("invalid error code: {}", e))
1025                                            .to_compile_error(),
1026                                    );
1027                                    continue;
1028                                }
1029                            };
1030                            let err_msg = inner
1031                                .msg
1032                                .value()
1033                                .replace("${field}", &field_name.to_string());
1034                            validates.push(quote! {
1035                                if #field_name > #cmp_value {
1036                                    return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1037                                }
1038                            });
1039                        } else if meta.path.is_ident("len") {
1040                            let field_is_option = is_option_type(field_type);
1041                            // For Option<T>, check if inner type is a collection
1042                            // For non-Option, check directly
1043                            if field_is_option {
1044                                // Option<T> is allowed - inner type check is deferred to runtime
1045                            } else if !is_collection_type(field_type) {
1046                                validates.push(
1047                                    syn::Error::new_spanned(
1048                                        &meta.path,
1049                                        format!(
1050                                            "validation `len` is only supported on String, &[u8], Vec<T>, [T; N], or Option<T> wrapping these types, but field `{}` is not",
1051                                            field_name
1052                                        ),
1053                                    )
1054                                    .to_compile_error(),
1055                                );
1056                                continue;
1057                            }
1058
1059                            let inner = match meta.parse_args::<Length>() {
1060                                Ok(v) => v,
1061                                Err(e) => {
1062                                    validates.push(e.to_compile_error());
1063                                    continue;
1064                                }
1065                            };
1066                            let min_value = match inner.min.base10_parse::<i64>() {
1067                                Ok(v) => v,
1068                                Err(e) => {
1069                                    validates.push(
1070                                        syn::Error::new_spanned(&inner.min, format!("invalid min value: {}", e))
1071                                            .to_compile_error(),
1072                                    );
1073                                    continue;
1074                                }
1075                            };
1076                            let max_value = match inner.max.base10_parse::<i64>() {
1077                                Ok(v) => v,
1078                                Err(e) => {
1079                                    validates.push(
1080                                        syn::Error::new_spanned(&inner.max, format!("invalid max value: {}", e))
1081                                            .to_compile_error(),
1082                                    );
1083                                    continue;
1084                                }
1085                            };
1086                            let code = match inner.code.base10_parse::<i64>() {
1087                                Ok(v) => v,
1088                                Err(e) => {
1089                                    validates.push(
1090                                        syn::Error::new_spanned(&inner.code, format!("invalid error code: {}", e))
1091                                            .to_compile_error(),
1092                                    );
1093                                    continue;
1094                                }
1095                            };
1096                            let err_msg = inner
1097                                .msg
1098                                .value()
1099                                .replace("${field}", &field_name.to_string());
1100                            if min_value > max_value {
1101                                validates.push(
1102                                    syn::Error::new_spanned(
1103                                        &meta.path,
1104                                        format!(
1105                                            "invalid len validation: min ({}) > max ({}) for field `{}`",
1106                                            min_value, max_value, field_name
1107                                        ),
1108                                    )
1109                                    .to_compile_error(),
1110                                );
1111                                continue;
1112                            }
1113                            if min_value < 0 && max_value < 0 {
1114                                validates.push(
1115                                    syn::Error::new_spanned(
1116                                        &meta.path,
1117                                        format!(
1118                                            "invalid len validation: both min and max are negative for field `{}`",
1119                                            field_name
1120                                        ),
1121                                    )
1122                                    .to_compile_error(),
1123                                );
1124                                continue;
1125                            } else if min_value < 0 {
1126                                let max: usize = match max_value.try_into() {
1127                                    Ok(v) => v,
1128                                    Err(_) => {
1129                                        validates.push(
1130                                            syn::Error::new_spanned(&inner.max, "value too large for usize")
1131                                                .to_compile_error(),
1132                                        );
1133                                        continue;
1134                                    }
1135                                };
1136                                validates.push(quote! {
1137                                    if #field_name.len() > #max {
1138                                        return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1139                                    }
1140                                });
1141                            } else if max_value < 0 {
1142                                let min: usize = match min_value.try_into() {
1143                                    Ok(v) => v,
1144                                    Err(_) => {
1145                                        validates.push(
1146                                            syn::Error::new_spanned(&inner.min, "value too large for usize")
1147                                                .to_compile_error(),
1148                                        );
1149                                        continue;
1150                                    }
1151                                };
1152                                validates.push(quote! {
1153                                    if #field_name.len() < #min {
1154                                        return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1155                                    }
1156                                });
1157                            } else {
1158                                let min: usize = match min_value.try_into() {
1159                                    Ok(v) => v,
1160                                    Err(_) => {
1161                                        validates.push(
1162                                            syn::Error::new_spanned(&inner.min, "value too large for usize")
1163                                                .to_compile_error(),
1164                                        );
1165                                        continue;
1166                                    }
1167                                };
1168                                let max: usize = match max_value.try_into() {
1169                                    Ok(v) => v,
1170                                    Err(_) => {
1171                                        validates.push(
1172                                            syn::Error::new_spanned(&inner.max, "value too large for usize")
1173                                                .to_compile_error(),
1174                                        );
1175                                        continue;
1176                                    }
1177                                };
1178                                if field_is_option {
1179                                    validates.push(quote! {
1180                                        let length = match &#field_name {
1181                                            Some(s) => {
1182                                                let __length = s.len();
1183                                                if __length < #min || __length > #max {
1184                                                    return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1185                                                }
1186                                            },
1187                                            None => {},
1188                                        };
1189                                    });
1190                                } else {
1191                                    validates.push(quote! {
1192                                        if #field_name.len() < #min || #field_name.len() > #max {
1193                                            return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1194                                        }
1195                                    });
1196                                }
1197                            }
1198                        } else if meta.path.is_ident("of") {
1199                            let inner = match meta.parse_args::<OfValidator>() {
1200                                Ok(v) => v,
1201                                Err(e) => {
1202                                    validates.push(e.to_compile_error());
1203                                    continue;
1204                                }
1205                            };
1206                            let allowed_values = inner.allowed_values.clone();
1207                            let code = match inner.code.base10_parse::<i64>() {
1208                                Ok(v) => v,
1209                                Err(e) => {
1210                                    validates.push(
1211                                        syn::Error::new_spanned(&inner.code, format!("invalid error code: {}", e))
1212                                            .to_compile_error(),
1213                                    );
1214                                    continue;
1215                                }
1216                            };
1217                            let err_msg = inner
1218                                .msg
1219                                .value()
1220                                .replace("${field}", &field_name.to_string());
1221                            let values_tokens: Vec<_> = allowed_values
1222                                .iter()
1223                                .map(|v| v.to_token_stream())
1224                                .collect();
1225                            validates.push(quote! {
1226                                if !matches!(#field_name, #(#values_tokens)|*) {
1227                                    return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1228                                }
1229                            });
1230                        } else if meta.path.is_ident("func") {
1231                            let inner = match meta.parse_args::<LitStr>() {
1232                                Ok(v) => v,
1233                                Err(e) => {
1234                                    validates.push(e.to_compile_error());
1235                                    continue;
1236                                }
1237                            };
1238                            let ident = match syn::parse_str::<syn::Ident>(&inner.value()) {
1239                                Ok(v) => v,
1240                                Err(e) => {
1241                                    validates.push(
1242                                        syn::Error::new_spanned(
1243                                            &inner,
1244                                            format!("invalid function name `{}`: {}", inner.value(), e),
1245                                        )
1246                                        .to_compile_error(),
1247                                    );
1248                                    continue;
1249                                }
1250                            };
1251                            let field = field_name.to_string();
1252                            validates.push(quote! {
1253                                match #ident(&#field_name, #field) {
1254                                    Ok(()) => {},
1255                                    Err(e) => return Err(e.to_afastdata_error()),
1256                                }
1257                            });
1258                        }
1259                }
1260            }
1261        }
1262    }
1263    validates
1264}
1265
1266/// 为结构体的字段生成反序列化代码以及构造表达式。内部辅助函数。
1267///
1268/// Generates deserialization code for struct fields along with the construction
1269/// expression. Internal helper.
1270///
1271/// # 参数 / Parameters
1272///
1273/// - `fields`:结构体的字段定义 / The struct's field definitions
1274/// - `name`:结构体类型的标识符 / The struct type's identifier
1275/// - `ty_generics`:类型的泛型参数(用于构造时的 turbofish 语法)
1276///   / The type's generic parameters (used for turbofish syntax during construction)
1277///
1278/// # 返回值 / Returns
1279///
1280/// 返回 `(构造表达式, 反序列化语句列表)`:
1281/// - 构造表达式:用于创建结构体实例的 `TokenStream`
1282/// - 反序列化语句:每个字段的 `from_bytes()` 调用和偏移量更新
1283///
1284/// Returns `(construction_expression, deserialization_statements)`:
1285/// - Construction expression: A `TokenStream` for creating the struct instance
1286/// - Deserialization statements: `from_bytes()` calls and offset updates for each field
1287///
1288/// # 泛型构造 / Generic Construction
1289///
1290/// 使用 `as_turbofish()` 生成正确的泛型语法。例如 `MyStruct::<T>` 而非
1291/// `MyStruct <T>`(后者会被解析为比较操作)。
1292///
1293/// Uses `as_turbofish()` to generate correct generic syntax. For example,
1294/// `MyStruct::<T>` instead of `MyStruct <T>` (which would be parsed as a
1295/// comparison operation).
1296fn generate_deserialize_fields(
1297    fields: &Fields,
1298    name: &syn::Ident,
1299    ty_generics: &syn::TypeGenerics,
1300) -> (proc_macro2::TokenStream, Vec<proc_macro2::TokenStream>) {
1301    // 在表达式上下文中使用 turbofish 语法:Name::<T>
1302    // In expression context, use turbofish syntax: Name::<T>
1303    let ty_params = ty_generics.as_turbofish();
1304    match fields {
1305        Fields::Named(named) => {
1306            let mut desers = Vec::new();
1307            let mut field_names = Vec::new();
1308            for f in &named.named {
1309                let fname = f.ident.as_ref().unwrap();
1310                let ftype = &f.ty;
1311                field_names.push(fname.clone());
1312
1313                let validates = parse_validations(fname, ftype, &f.attrs);
1314                let (skip, default) = has_skip_attr(&f.attrs);
1315                if skip {
1316                    if let Some(default) = default {
1317                        match syn::parse_str::<syn::Ident>(&default) {
1318                            Ok(ident) => {
1319                                desers.push(quote! {
1320                                    let #fname: #ftype = #ident();
1321                                });
1322                            }
1323                            Err(_) => {
1324                                desers.push(quote! {
1325                                    compile_error!(concat!("invalid function name in skip: ", #default));
1326                                });
1327                            }
1328                        }
1329                    } else {
1330                        desers.push(quote! {
1331                            let #fname: #ftype = #ftype::default();
1332                        });
1333                    }
1334                } else {
1335                    desers.push(quote! {
1336                        let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1337                        let #fname: #ftype = __val;
1338                        #(#validates)*
1339                        offset += __new_offset;
1340                    });
1341                }
1342            }
1343            let construct = quote! {
1344                #name #ty_params { #(#field_names),* }
1345            };
1346            (construct, desers)
1347        }
1348        Fields::Unnamed(unnamed) => {
1349            let mut desers = Vec::new();
1350            let mut field_names = Vec::new();
1351            for (i, f) in unnamed.unnamed.iter().enumerate() {
1352                let fname = syn::Ident::new(&format!("__f{}", i), name.span());
1353                let ftype = &f.ty;
1354                let (skip, default_fn) = has_skip_attr(&f.attrs);
1355                if skip {
1356                    if let Some(func_name) = default_fn {
1357                        match syn::parse_str::<syn::Ident>(&func_name) {
1358                            Ok(ident) => {
1359                                desers.push(quote! {
1360                                    let #fname: #ftype = #ident();
1361                                });
1362                            }
1363                            Err(_) => {
1364                                desers.push(quote! {
1365                                    compile_error!(concat!("invalid function name in skip: ", #func_name));
1366                                });
1367                            }
1368                        }
1369                    } else {
1370                        desers.push(quote! {
1371                            let #fname: #ftype = <#ftype as ::std::default::Default>::default();
1372                        });
1373                    }
1374                } else {
1375                    let validates = parse_validations(&fname, ftype, &f.attrs);
1376                    desers.push(quote! {
1377                        let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1378                        let #fname: #ftype = __val;
1379                        #(#validates)*
1380                        offset += __new_offset;
1381                    });
1382                }
1383                field_names.push(fname);
1384            }
1385            let construct = quote! {
1386                #name #ty_params ( #(#field_names),* )
1387            };
1388            (construct, desers)
1389        }
1390        Fields::Unit => {
1391            let construct = quote! { #name #ty_params };
1392            (construct, vec![])
1393        }
1394    }
1395}