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}