afastdata_macro/lib.rs
1//! # afastdata-macro
2//!
3//! afastdata 序列化框架的 derive 宏,为结构体和枚举自动生成
4//! [`AFastSerialize`] 和 [`AFastDeserialize`] trait 的实现。
5//!
6//! Derive macros for the afastdata serialization framework, automatically generating
7//! implementations of [`AFastSerialize`]` and [`AFastDeserialize`] traits for
8//! structs and enums.
9//!
10//! ## 支持的类型 / Supported Types
11//!
12//! - **命名字段结构体 (Named-field struct)**:逐字段序列化/反序列化
13//! / Field-by-field serialization/deserialization
14//! - **元组结构体 (Tuple struct)**:按索引逐字段序列化/反序列化
15//! / Index-based field serialization/deserialization
16//! - **单元结构体 (Unit struct)**:生成空实现(不产生任何字节)
17//! / Generates an empty implementation (no bytes produced)
18//! - **枚举 (Enum)**:写入 `u32` 变体索引 + 变体字段数据
19//! / Writes a `u32` variant index + variant field data
20//!
21//! ## 编码格式 / Encoding Format
22//!
23//! ### 结构体 / Struct
24//!
25//! 所有字段按声明顺序依次调用 `to_bytes()` / `from_bytes()`,无额外前缀。
26//!
27//! All fields call `to_bytes()` / `from_bytes()` in declaration order, with no
28//! additional prefix.
29//!
30//! ### 枚举 / Enum
31//!
32//! | 编码内容 / Content | 类型 / Type | 说明 / Description |
33//! |---|---|---|
34//! | 变体索引 / Variant index | `u32` little-endian | 从 0 开始递增 / Starts from 0, incrementing |
35//! | 变体字段 / Variant fields | 逐字段编码 / Field-wise encoding | 仅非 unit 变体 / Only for non-unit variants |
36//!
37//! ## 泛型支持 / Generic Support
38//!
39//! 泛型参数会自动添加 `AFastSerialize` 和(对于反序列化)`AFastDeserialize` trait 约束。
40//! 如果泛型参数仅用于某些字段,生成的约束可能过于严格,但这保证了实现的正确性。
41//!
42//! Generic parameters automatically receive `AFastSerialize` and (for deserialization)
43//! `AFastDeserialize` trait bounds. If a generic parameter is only used in certain fields,
44//! the generated bounds may be overly strict, but this ensures correctness.
45//!
46//! ## 示例 / Example
47//!
48//! ```ignore
49//! use afastdata::{AFastSerialize, AFastDeserialize};
50//!
51//! #[derive(AFastSerialize, AFastDeserialize, Debug, PartialEq)]
52//! struct Point {
53//! x: i32,
54//! y: i32,
55//! }
56//!
57//! #[derive(AFastSerialize, AFastDeserialize, Debug, PartialEq)]
58//! enum Shape {
59//! Circle(f64),
60//! Rectangle { width: f64, height: f64 },
61//! Empty,
62//! }
63//!
64//! // 序列化 / Serialize
65//! let point = Point { x: 10, y: 20 };
66//! let bytes = point.to_bytes();
67//!
68//! // 反序列化 / Deserialize
69//! let (decoded, _) = Point::from_bytes(&bytes).unwrap();
70//! assert_eq!(point, decoded);
71//! ```
72
73use proc_macro::TokenStream;
74use quote::quote;
75use syn::{
76 Attribute, Data, DeriveInput, Fields, Index, Lit, LitInt, LitStr, Meta, Path, Token, Type,
77 TypePath,
78 parse::{Parse, ParseStream},
79 parse_macro_input,
80 punctuated::Punctuated,
81};
82
83/// 为结构体或枚举生成 [`AFastSerialize`] trait 实现。
84///
85/// Generates an [`AFastSerialize`] trait implementation for a struct or enum.
86///
87/// # 生成的代码 / Generated Code
88///
89/// ## 结构体 / Struct
90///
91/// 为每个字段调用 `to_bytes()`,并将结果依次追加到字节缓冲区中。
92///
93/// Calls `to_bytes()` on each field, appending the results to a byte buffer
94/// sequentially.
95///
96/// ```ignore
97/// // 以下为生成代码的示意(非实际代码)
98/// // The following is an illustration of generated code (not actual code)
99/// impl AFastSerialize for MyStruct {
100/// fn to_bytes(&self) -> Vec<u8> {
101/// let mut bytes = Vec::new();
102/// bytes.extend(AFastSerialize::to_bytes(&self.field1));
103/// bytes.extend(AFastSerialize::to_bytes(&self.field2));
104/// // ...
105/// bytes
106/// }
107/// }
108/// ```
109///
110/// ## 枚举 / Enum
111///
112/// 先写入 `u32` 变体索引(从 0 开始),再写入变体的字段数据。
113/// Unit 变体只写入索引。
114///
115/// Writes a `u32` variant index (starting from 0), then the variant's field data.
116/// Unit variants only write the index.
117///
118/// ```ignore
119/// // 以下为生成代码的示意(非实际代码)
120/// // The following is an illustration of generated code (not actual code)
121/// impl AFastSerialize for MyEnum {
122/// fn to_bytes(&self) -> Vec<u8> {
123/// let mut bytes = Vec::new();
124/// match self {
125/// MyEnum::Variant1 => {
126/// bytes.extend(0u32.to_le_bytes());
127/// }
128/// MyEnum::Variant2(field) => {
129/// bytes.extend(1u32.to_le_bytes());
130/// bytes.extend(AFastSerialize::to_bytes(field));
131/// }
132/// // ...
133/// }
134/// bytes
135/// }
136/// }
137/// ```
138///
139/// # 泛型 / Generics
140///
141/// 如果目标类型包含泛型参数,生成的 `impl` 会自动为这些参数添加
142/// `AFastSerialize` 约束。
143///
144/// If the target type contains generic parameters, the generated `impl` automatically
145/// adds `AFastSerialize` bounds to those parameters.
146///
147/// # Panics
148///
149/// 对 union 类型使用此宏会触发编译 panic。
150///
151/// Using this macro on a union type will trigger a compile-time panic.
152#[proc_macro_derive(AFastSerialize, attributes(afast))]
153pub fn derive_serialize(input: TokenStream) -> TokenStream {
154 let input = parse_macro_input!(input as DeriveInput);
155 let name = &input.ident;
156 let generics = &input.generics;
157
158 // 为泛型参数添加 AFastSerialize trait 约束
159 // Add AFastSerialize trait bounds to generic parameters
160 let mut generics_with_bounds = generics.clone();
161 for param in &mut generics_with_bounds.params {
162 if let syn::GenericParam::Type(ref mut ty) = *param {
163 ty.bounds
164 .push(syn::parse_quote!(::afastdata::AFastSerialize));
165 }
166 }
167 let (impl_generics, _, _) = generics_with_bounds.split_for_impl();
168 let (_, ty_generics, _) = generics.split_for_impl();
169
170 let expanded = match &input.data {
171 Data::Struct(data) => {
172 let serialize_body = generate_serialize_fields(&data.fields, quote!(self));
173 quote! {
174 impl #impl_generics ::afastdata::AFastSerialize for #name #ty_generics {
175 fn to_bytes(&self) -> Vec<u8> {
176 let mut bytes = Vec::new();
177 #(#serialize_body)*
178 bytes
179 }
180 }
181 }
182 }
183 Data::Enum(data) => {
184 let mut arms = Vec::new();
185 for (i, variant) in data.variants.iter().enumerate() {
186 let variant_name = &variant.ident;
187 let tag = i as u32;
188
189 match &variant.fields {
190 Fields::Unit => {
191 // Unit 变体:只写入 u32 索引
192 // Unit variant: write only the u32 index
193 arms.push(quote! {
194 #name::#variant_name => {
195 bytes.extend(#tag.to_le_bytes());
196 }
197 });
198 }
199 Fields::Unnamed(fields) => {
200 // 元组变体:写入 u32 索引 + 逐字段序列化
201 // Tuple variant: write u32 index + field-by-field serialization
202 let field_names: Vec<_> = (0..fields.unnamed.len())
203 .map(|i| {
204 let ident =
205 syn::Ident::new(&format!("__f{}", i), variant_name.span());
206 ident
207 })
208 .collect();
209 let field_patterns = &field_names;
210 let mut serialize_fields = Vec::new();
211 for fname in &field_names {
212 serialize_fields.push(quote! {
213 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
214 });
215 }
216 arms.push(quote! {
217 #name::#variant_name(#(#field_patterns),*) => {
218 bytes.extend(#tag.to_le_bytes());
219 #(#serialize_fields)*
220 }
221 });
222 }
223 Fields::Named(fields) => {
224 // 命名字段变体:写入 u32 索引 + 逐字段序列化
225 // Named-field variant: write u32 index + field-by-field serialization
226 let field_names: Vec<_> = fields
227 .named
228 .iter()
229 .map(|f| f.ident.as_ref().unwrap())
230 .collect();
231 let mut serialize_fields = Vec::new();
232 for fname in &field_names {
233 serialize_fields.push(quote! {
234 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
235 });
236 }
237 arms.push(quote! {
238 #name::#variant_name { #(#field_names),* } => {
239 bytes.extend(#tag.to_le_bytes());
240 #(#serialize_fields)*
241 }
242 });
243 }
244 }
245 }
246
247 quote! {
248 impl #impl_generics ::afastdata::AFastSerialize for #name #ty_generics {
249 fn to_bytes(&self) -> Vec<u8> {
250 let mut bytes = Vec::new();
251 match self {
252 #(#arms)*
253 }
254 bytes
255 }
256 }
257 }
258 }
259 Data::Union(_) => panic!("AFastSerialize does not support unions"),
260 };
261
262 TokenStream::from(expanded)
263}
264
265/// 为结构体或枚举生成 [`AFastDeserialize`] trait 实现。
266///
267/// Generates an [`AFastDeserialize`] trait implementation for a struct or enum.
268///
269/// # 生成的代码 / Generated Code
270///
271/// ## 结构体 / Struct
272///
273/// 为每个字段依次调用 `from_bytes()`,并使用偏移量追踪已消耗的字节数,
274/// 最后构造结构体实例。
275///
276/// Calls `from_bytes()` on each field sequentially, using an offset to track
277/// consumed bytes, then constructs the struct instance.
278///
279/// ```ignore
280/// // 以下为生成代码的示意(非实际代码)
281/// // The following is an illustration of generated code (not actual code)
282/// impl AFastDeserialize for MyStruct {
283/// fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
284/// let mut offset: usize = 0;
285/// let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
286/// let field1 = __val;
287/// offset += __new_offset;
288/// // ... 更多字段 / more fields ...
289/// Ok((MyStruct { field1, ... }, offset))
290/// }
291/// }
292/// ```
293///
294/// ## 枚举 / Enum
295///
296/// 先读取 `u32` 变体索引,根据索引匹配对应变体,再反序列化该变体的字段。
297///
298/// First reads the `u32` variant index, matches the corresponding variant by index,
299/// then deserializes the variant's fields.
300///
301/// ```ignore
302/// // 以下为生成代码的示意(非实际代码)
303/// // The following is an illustration of generated code (not actual code)
304/// impl AFastDeserialize for MyEnum {
305/// fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
306/// let mut offset: usize = 0;
307/// let (__tag, __new_offset) = <u32 as AFastDeserialize>::from_bytes(&data[offset..])?;
308/// offset += __new_offset;
309/// match __tag {
310/// 0 => Ok((MyEnum::Variant1, offset)),
311/// 1 => {
312/// let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
313/// offset += __new_offset;
314/// Ok((MyEnum::Variant2(__val), offset))
315/// }
316/// v => Err(format!("Unknown variant tag: {} for MyEnum", v)),
317/// }
318/// }
319/// }
320/// ```
321///
322/// # 泛型 / Generics
323///
324/// 如果目标类型包含泛型参数,生成的 `impl` 会同时添加 `AFastSerialize` 和
325/// `AFastDeserialize` 约束。双重约束确保泛型类型在序列化和反序列化两个方向
326/// 上都可用。
327///
328/// If the target type contains generic parameters, the generated `impl` adds both
329/// `AFastSerialize` and `AFastDeserialize` bounds. The dual bounds ensure the generic
330/// type is available in both serialization and deserialization directions.
331///
332/// # Panics
333///
334/// 对 union 类型使用此宏会触发编译 panic。
335///
336/// Using this macro on a union type will trigger a compile-time panic.
337#[proc_macro_derive(AFastDeserialize, attributes(afast))]
338pub fn derive_deserialize(input: TokenStream) -> TokenStream {
339 let input = parse_macro_input!(input as DeriveInput);
340 let name = &input.ident;
341 let generics = &input.generics;
342
343 // 为泛型参数添加 AFastSerialize + AFastDeserialize trait 约束
344 // Add AFastSerialize + AFastDeserialize trait bounds to generic parameters
345 let mut generics_with_bounds = generics.clone();
346 for param in &mut generics_with_bounds.params {
347 if let syn::GenericParam::Type(ref mut ty) = *param {
348 ty.bounds
349 .push(syn::parse_quote!(::afastdata::AFastSerialize));
350 ty.bounds
351 .push(syn::parse_quote!(::afastdata::AFastDeserialize));
352 }
353 }
354 let (impl_generics, _, _) = generics_with_bounds.split_for_impl();
355 let (_, ty_generics, _) = generics.split_for_impl();
356
357 let expanded = match &input.data {
358 Data::Struct(data) => {
359 let (construct, field_desers) =
360 generate_deserialize_fields(&data.fields, &name, &ty_generics);
361 quote! {
362 impl #impl_generics ::afastdata::AFastDeserialize for #name #ty_generics {
363 fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::afastdata::Error> {
364 let mut offset: usize = 0;
365 #(#field_desers)*
366 Ok((#construct, offset))
367 }
368 }
369 }
370 }
371 Data::Enum(data) => {
372 let mut arms = Vec::new();
373 for (i, variant) in data.variants.iter().enumerate() {
374 let variant_name = &variant.ident;
375 let tag = i as u32;
376
377 match &variant.fields {
378 Fields::Unit => {
379 // Unit 变体:匹配索引后直接返回
380 // Unit variant: match index and return directly
381 arms.push(quote! {
382 #tag => {
383 Ok((#name::#variant_name, offset))
384 }
385 });
386 }
387 Fields::Unnamed(fields) => {
388 // 元组变体:匹配索引后逐字段反序列化
389 // Tuple variant: match index, then deserialize fields sequentially
390 let mut field_desers = Vec::new();
391 let mut field_names = Vec::new();
392 for (i, f) in fields.unnamed.iter().enumerate() {
393 let fname = syn::Ident::new(
394 &format!("__f{}", i),
395 variant_name.span(),
396 );
397 let ftype = &f.ty;
398 let validates = parse_validations(&fname, ftype, &f.attrs);
399 field_desers.push(quote! {
400 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
401 let #fname: #ftype = __val;
402 #(#validates)*
403 offset += __new_offset;
404 });
405 field_names.push(fname);
406 }
407 arms.push(quote! {
408 #tag => {
409 #(#field_desers)*
410 Ok((#name::#variant_name(#(#field_names),*), offset))
411 }
412 });
413 }
414 Fields::Named(fields) => {
415 // 命名字段变体:匹配索引后逐字段反序列化
416 // Named-field variant: match index, then deserialize fields sequentially
417 let mut field_desers = Vec::new();
418 let mut field_names = Vec::new();
419 for f in &fields.named {
420 let fname = f.ident.as_ref().unwrap();
421 let ftype = &f.ty;
422 let validates = parse_validations(fname, ftype, &f.attrs);
423 field_desers.push(quote! {
424 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
425 let #fname: #ftype = __val;
426 #(#validates)*
427 offset += __new_offset;
428 });
429 field_names.push(fname);
430 }
431 arms.push(quote! {
432 #tag => {
433 #(#field_desers)*
434 Ok((#name::#variant_name { #(#field_names),* }, offset))
435 }
436 });
437 }
438 }
439 }
440
441 quote! {
442 impl #impl_generics ::afastdata::AFastDeserialize for #name #ty_generics {
443 fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::afastdata::Error> {
444 let mut offset: usize = 0;
445 // 读取 u32 变体索引
446 // Read the u32 variant index
447 let (__tag_bytes, __new_offset) = <u32 as ::afastdata::AFastDeserialize>::from_bytes(&data[offset..])?;
448 offset += __new_offset;
449 match __tag_bytes {
450 #(#arms)*
451 v => Err(::afastdata::Error::deserialize(format!("Unknown variant tag: {} for {}", v, ::std::stringify!(#name)))),
452 }
453 }
454 }
455 }
456 }
457 Data::Union(_) => panic!("AFastDeserialize does not support unions"),
458 };
459
460 TokenStream::from(expanded)
461}
462
463/// 为结构体的字段生成序列化代码。内部辅助函数。
464///
465/// Generates serialization code for struct fields. Internal helper.
466///
467/// # 参数 / Parameters
468///
469/// - `fields`:结构体的字段定义 / The struct's field definitions
470/// - `self_prefix`:访问字段时使用的前缀(如 `self` 或变体解构变量)
471/// / The prefix used to access fields (e.g., `self` or a variant destructure variable)
472///
473/// # 返回值 / Returns
474///
475/// 返回一个 `TokenStream` 列表,每个元素对应一个字段的序列化语句。
476///
477/// Returns a list of `TokenStream`s, each corresponding to a serialization statement
478/// for one field.
479///
480/// # 生成格式 / Generated Format
481///
482/// - **命名字段 (Named)**:`bytes.extend(AFastSerialize::to_bytes(&self.field_name));`
483/// - **元组字段 (Unnamed)**:`bytes.extend(AFastSerialize::to_bytes(&self.0));`
484/// - **单元字段 (Unit)**:不生成任何代码 / Generates no code
485fn generate_serialize_fields(
486 fields: &Fields,
487 self_prefix: proc_macro2::TokenStream,
488) -> Vec<proc_macro2::TokenStream> {
489 match fields {
490 Fields::Named(named) => named
491 .named
492 .iter()
493 .filter(|f| !has_skip_attr(&f.attrs).0)
494 .map(|f| {
495 let fname = f.ident.as_ref().unwrap();
496 quote! {
497 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#fname));
498 }
499 })
500 .collect(),
501 Fields::Unnamed(unnamed) => unnamed
502 .unnamed
503 .iter()
504 .enumerate()
505 .map(|(i, _)| {
506 let idx = Index::from(i);
507 quote! {
508 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#idx));
509 }
510 })
511 .collect(),
512 Fields::Unit => vec![],
513 }
514}
515
516fn has_skip_attr(attrs: &[Attribute]) -> (bool, Option<String>) {
517 for attr in attrs {
518 if attr.path().is_ident("afast") {
519 // 尝试解析属性参数为逗号分隔的 Meta 列表
520 if let Ok(nested) =
521 attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
522 {
523 for meta in nested {
524 match meta {
525 // 无参数的 skip: #[afast(skip)]
526 Meta::Path(path) => {
527 if path.is_ident("skip") {
528 return (true, None);
529 }
530 }
531 // 有参数的 skip: #[afast(skip("v"))]
532 Meta::List(meta_list) => {
533 if meta_list.path.is_ident("skip") {
534 // 尝试解析 tokens 为字符串字面量
535 if let Ok(lit_str) = syn::parse2::<LitStr>(meta_list.tokens.clone())
536 {
537 return (true, Some(lit_str.value()));
538 } else {
539 // 如果解析失败(例如参数不是字符串),返回 true 但参数为 None
540 // 你可以根据需要添加错误处理或 panic
541 return (true, None);
542 }
543 }
544 }
545 _ => {}
546 }
547 }
548 }
549 }
550 }
551 (false, None)
552}
553
554struct Range {
555 int: LitInt,
556 _comma1: Token![,],
557 code: LitInt,
558 _comma2: Token![,],
559 msg: LitStr,
560}
561
562impl Parse for Range {
563 fn parse(input: ParseStream) -> syn::Result<Self> {
564 Ok(Range {
565 int: input.parse()?,
566 _comma1: input.parse()?,
567 code: input.parse()?,
568 _comma2: input.parse()?,
569 msg: input.parse()?,
570 })
571 }
572}
573
574struct Length {
575 min: LitInt,
576 _comma1: Token![,],
577 max: LitInt,
578 _comma2: Token![,],
579 code: LitInt,
580 _comma3: Token![,],
581 msg: LitStr,
582}
583
584impl Parse for Length {
585 fn parse(input: ParseStream) -> syn::Result<Self> {
586 Ok(Length {
587 min: input.parse()?,
588 _comma1: input.parse()?,
589 max: input.parse()?,
590 _comma2: input.parse()?,
591 code: input.parse()?,
592 _comma3: input.parse()?,
593 msg: input.parse()?,
594 })
595 }
596}
597
598#[derive(Clone)]
599enum ValidateValue {
600 Int(i64),
601 Float(f64),
602 Bool(bool),
603 Str(String),
604}
605
606impl ValidateValue {
607 /// 将值转换为代码生成中使用的 TokenStream
608 ///
609 /// 例如:
610 /// ValidateValue::Int(42) → quote! { 42 }
611 /// ValidateValue::Str("hello") → quote! { "hello" }
612 fn to_token_stream(&self) -> proc_macro2::TokenStream {
613 match self {
614 ValidateValue::Int(v) => quote! { #v },
615
616 ValidateValue::Float(v) => {
617 // 浮点数通过字符串解析来保持精度
618 let v_str = v.to_string();
619 v_str.parse().unwrap_or_else(|_| {
620 // 如果字符串解析失败,使用直接值
621 quote! { #v }
622 })
623 }
624
625 ValidateValue::Bool(v) => quote! { #v },
626 ValidateValue::Str(v) => quote! { #v },
627 }
628 }
629}
630
631struct OfValidator {
632 allowed_values: Vec<ValidateValue>,
633 code: syn::LitInt,
634 msg: syn::LitStr,
635}
636
637impl Parse for OfValidator {
638 fn parse(input: ParseStream) -> syn::Result<Self> {
639 let content;
640 syn::bracketed!(content in input);
641
642 let mut values = Vec::new();
643
644 if !content.is_empty() {
645 loop {
646 let lit = content.parse::<Lit>()?;
647
648 let value = match lit {
649 Lit::Int(lit_int) => {
650 let int_value: i64 = lit_int.base10_parse()?;
651 ValidateValue::Int(int_value)
652 }
653
654 Lit::Float(lit_float) => {
655 let float_value: f64 = lit_float.base10_parse()?;
656 ValidateValue::Float(float_value)
657 }
658
659 Lit::Bool(lit_bool) => ValidateValue::Bool(lit_bool.value),
660
661 Lit::Str(lit_str) => ValidateValue::Str(lit_str.value()),
662
663 _ => {
664 return Err(syn::Error::new_spanned(
665 &lit,
666 "unsupported literal type in 'of' validator; \
667 only int, float, bool, and str literals are supported",
668 ));
669 }
670 };
671
672 values.push(value);
673
674 if !content.peek(Token![,]) {
675 break;
676 }
677
678 content.parse::<Token![,]>()?;
679
680 if content.is_empty() {
681 break;
682 }
683 }
684 }
685
686 input.parse::<Token![,]>()?;
687
688 let code = input.parse::<syn::LitInt>()?;
689
690 input.parse::<Token![,]>()?;
691
692 let msg = input.parse::<syn::LitStr>()?;
693
694 Ok(OfValidator {
695 allowed_values: values,
696 code,
697 msg,
698 })
699 }
700}
701
702/// 解析字段上的 `#[afast(...)]` 校验属性,生成校验代码。
703///
704/// Parses `#[afast(...)]` validation attributes on a field and generates
705/// validation code blocks.
706///
707/// # 参数 / Parameters
708///
709/// - `field_name`:字段名 / Field name
710/// - `field_type`:字段类型 / Field type
711/// - `attrs`:字段的属性列表 / Field attributes
712///
713/// # 返回值 / Returns
714///
715/// 返回校验语句的 `TokenStream` 列表。
716///
717/// Returns a list of validation `TokenStream` blocks.
718fn parse_validations(
719 field_name: &syn::Ident,
720 field_type: &Type,
721 attrs: &[Attribute],
722) -> Vec<proc_macro2::TokenStream> {
723 let mut validates = Vec::new();
724 for attr in attrs {
725 if attr.path().is_ident("afast") {
726 let nested = attr
727 .parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
728 .unwrap();
729 for meta in nested {
730 match meta {
731 Meta::List(meta) => {
732 if meta.path.is_ident("gt") {
733 let inner = meta.parse_args::<Range>().unwrap();
734 let gt_value = inner.int.base10_parse::<i64>().unwrap();
735 let code = inner.code.base10_parse::<i64>().unwrap();
736 let err_msg = inner
737 .msg
738 .value()
739 .replace("${field}", &field_name.to_string());
740 validates.push(quote! {
741 if #field_name <= #gt_value {
742 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
743 }
744 });
745 } else if meta.path.is_ident("gte") {
746 let inner = meta.parse_args::<Range>().unwrap();
747 let gt_value = inner.int.base10_parse::<i64>().unwrap();
748 let code = inner.code.base10_parse::<i64>().unwrap();
749 let err_msg = inner
750 .msg
751 .value()
752 .replace("${field}", &field_name.to_string());
753 validates.push(quote! {
754 if #field_name < #gt_value {
755 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
756 }
757 });
758 } else if meta.path.is_ident("lt") {
759 let inner = meta.parse_args::<Range>().unwrap();
760 let lt_value = inner.int.base10_parse::<i64>().unwrap();
761 let code = inner.code.base10_parse::<i64>().unwrap();
762 let err_msg = inner
763 .msg
764 .value()
765 .replace("${field}", &field_name.to_string());
766 validates.push(quote! {
767 if #field_name >= #lt_value {
768 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
769 }
770 });
771 } else if meta.path.is_ident("lte") {
772 let inner = meta.parse_args::<Range>().unwrap();
773 let lt_value = inner.int.base10_parse::<i64>().unwrap();
774 let code = inner.code.base10_parse::<i64>().unwrap();
775 let err_msg = inner
776 .msg
777 .value()
778 .replace("${field}", &field_name.to_string());
779 validates.push(quote! {
780 if #field_name > #lt_value {
781 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
782 }
783 });
784 } else if meta.path.is_ident("len") {
785 let field_is_option = match field_type {
786 Type::Path(TypePath {
787 path: Path { segments, .. },
788 ..
789 }) => {
790 segments.len() == 1 && segments[0].ident == "Option"
791 }
792 _ => false,
793 };
794
795 let inner = meta.parse_args::<Length>().unwrap();
796 let min_value = inner.min.base10_parse::<i64>().unwrap();
797 let max_value = inner.max.base10_parse::<i64>().unwrap();
798 let code = inner.code.base10_parse::<i64>().unwrap();
799 let err_msg = inner
800 .msg
801 .value()
802 .replace("${field}", &field_name.to_string());
803 if min_value > max_value {
804 panic!(
805 "Invalid validation: min value {} is greater than max value {} for field {}",
806 min_value, max_value, field_name
807 );
808 }
809 if min_value < 0 && max_value < 0 {
810 panic!(
811 "Invalid validation: both min and max values are negative for field {}",
812 field_name
813 );
814 } else if min_value < 0 {
815 let max: usize = max_value.try_into().unwrap();
816 validates.push(quote! {
817 if #field_name.len() > #max {
818 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
819 }
820 });
821 } else if max_value < 0 {
822 let min: usize = min_value.try_into().unwrap();
823 validates.push(quote! {
824 if #field_name.len() < #min {
825 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
826 }
827 });
828 } else {
829 let min: usize = min_value.try_into().unwrap();
830 let max: usize = max_value.try_into().unwrap();
831 if field_is_option {
832 validates.push(quote! {
833 let length = match &#field_name {
834 Some(s) => {
835 let __length = s.len();
836 if __length < #min || __length > #max {
837 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
838 }
839 },
840 None => {},
841 };
842 });
843 } else {
844 validates.push(quote! {
845 if #field_name.len() < #min || #field_name.len() > #max {
846 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
847 }
848 });
849 }
850 }
851 } else if meta.path.is_ident("of") {
852 let inner = meta.parse_args::<OfValidator>().unwrap();
853 let allowed_values = inner.allowed_values.clone();
854 let code = inner.code.base10_parse::<i64>().unwrap();
855 let err_msg = inner
856 .msg
857 .value()
858 .replace("${field}", &field_name.to_string());
859 let values_tokens: Vec<_> = allowed_values
860 .iter()
861 .map(|v| v.to_token_stream())
862 .collect();
863 validates.push(quote! {
864 if !matches!(#field_name, #(#values_tokens)|*) {
865 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
866 }
867 });
868 } else if meta.path.is_ident("func") {
869 let inner = meta.parse_args::<LitStr>().unwrap();
870 let ident =
871 syn::parse_str::<syn::Ident>(&inner.value()).unwrap();
872 let field = field_name.to_string();
873 validates.push(quote! {
874 match #ident(&#field_name, #field) {
875 Ok(()) => {},
876 Err(e) => return Err(e.to_afastdata_error()),
877 }
878 });
879 }
880 }
881 _ => {}
882 }
883 }
884 }
885 }
886 validates
887}
888
889/// 为结构体的字段生成反序列化代码以及构造表达式。内部辅助函数。
890///
891/// Generates deserialization code for struct fields along with the construction
892/// expression. Internal helper.
893///
894/// # 参数 / Parameters
895///
896/// - `fields`:结构体的字段定义 / The struct's field definitions
897/// - `name`:结构体类型的标识符 / The struct type's identifier
898/// - `ty_generics`:类型的泛型参数(用于构造时的 turbofish 语法)
899/// / The type's generic parameters (used for turbofish syntax during construction)
900///
901/// # 返回值 / Returns
902///
903/// 返回 `(构造表达式, 反序列化语句列表)`:
904/// - 构造表达式:用于创建结构体实例的 `TokenStream`
905/// - 反序列化语句:每个字段的 `from_bytes()` 调用和偏移量更新
906///
907/// Returns `(construction_expression, deserialization_statements)`:
908/// - Construction expression: A `TokenStream` for creating the struct instance
909/// - Deserialization statements: `from_bytes()` calls and offset updates for each field
910///
911/// # 泛型构造 / Generic Construction
912///
913/// 使用 `as_turbofish()` 生成正确的泛型语法。例如 `MyStruct::<T>` 而非
914/// `MyStruct <T>`(后者会被解析为比较操作)。
915///
916/// Uses `as_turbofish()` to generate correct generic syntax. For example,
917/// `MyStruct::<T>` instead of `MyStruct <T>` (which would be parsed as a
918/// comparison operation).
919fn generate_deserialize_fields(
920 fields: &Fields,
921 name: &syn::Ident,
922 ty_generics: &syn::TypeGenerics,
923) -> (proc_macro2::TokenStream, Vec<proc_macro2::TokenStream>) {
924 // 在表达式上下文中使用 turbofish 语法:Name::<T>
925 // In expression context, use turbofish syntax: Name::<T>
926 let ty_params = ty_generics.as_turbofish();
927 match fields {
928 Fields::Named(named) => {
929 let mut desers = Vec::new();
930 let mut field_names = Vec::new();
931 for f in &named.named {
932 let fname = f.ident.as_ref().unwrap();
933 let ftype = &f.ty;
934 field_names.push(fname.clone());
935
936 let validates = parse_validations(fname, ftype, &f.attrs);
937 let (skip, default) = has_skip_attr(&f.attrs);
938 if skip {
939 if let Some(default) = default {
940 let ident = syn::parse_str::<syn::Ident>(&default).unwrap();
941 desers.push(quote! {
942 let #fname: #ftype = #ident();
943 });
944 } else {
945 desers.push(quote! {
946 let #fname: #ftype = #ftype::default();
947 });
948 }
949 } else {
950 desers.push(quote! {
951 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
952 let #fname: #ftype = __val;
953 #(#validates)*
954 offset += __new_offset;
955 });
956 }
957 }
958 let construct = quote! {
959 #name #ty_params { #(#field_names),* }
960 };
961 (construct, desers)
962 }
963 Fields::Unnamed(unnamed) => {
964 let mut desers = Vec::new();
965 let mut field_names = Vec::new();
966 for i in 0..unnamed.unnamed.len() {
967 let fname = syn::Ident::new(&format!("__f{}", i), name.span());
968 desers.push(quote! {
969 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
970 let #fname = __val;
971 offset += __new_offset;
972 });
973 field_names.push(fname);
974 }
975 let construct = quote! {
976 #name #ty_params ( #(#field_names),* )
977 };
978 (construct, desers)
979 }
980 Fields::Unit => {
981 let construct = quote! { #name #ty_params };
982 (construct, vec![])
983 }
984 }
985}