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,
78 Type, 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 let marker_ident = syn::Ident::new("__afast_marker__", proc_macro2::Span::call_site());
188 let serialize_body_with =
189 generate_serialize_fields_with(&data.fields, quote!(self), &marker_ident);
190 quote! {
191 impl #impl_generics ::afastdata::AFastSerialize for #name #ty_generics {
192 fn to_bytes(&self) -> Vec<u8> {
193 let mut bytes = Vec::new();
194 #(#serialize_body)*
195 bytes
196 }
197 fn to_bytes_with(&self, __afast_marker__: &str) -> Vec<u8> {
198 let mut bytes = Vec::new();
199 #(#serialize_body_with)*
200 bytes
201 }
202 }
203 }
204 }
205 Data::Enum(data) => {
206 let (tag_ty, _) = tag_type();
207 let mut arms = Vec::new();
208 let mut arms_with = Vec::new();
209 for (i, variant) in data.variants.iter().enumerate() {
210 let variant_name = &variant.ident;
211
212 match &variant.fields {
213 Fields::Unit => {
214 arms.push(quote! {
215 #name::#variant_name => {
216 bytes.extend((#i as #tag_ty).to_le_bytes());
217 }
218 });
219 arms_with.push(quote! {
220 #name::#variant_name => {
221 bytes.extend((#i as #tag_ty).to_le_bytes());
222 }
223 });
224 }
225 Fields::Unnamed(fields) => {
226 let field_names: Vec<_> = (0..fields.unnamed.len())
227 .map(|i| syn::Ident::new(&format!("__f{}", i), variant_name.span()))
228 .collect();
229 let field_patterns = &field_names;
230 let mut serialize_fields = Vec::new();
231 for (i, f) in fields.unnamed.iter().enumerate() {
232 if !has_skip_attr(&f.attrs).0 {
233 let fname = &field_names[i];
234 serialize_fields.push(quote! {
235 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
236 });
237 }
238 }
239 let mut serialize_fields_with = Vec::new();
240 for (i, f) in fields.unnamed.iter().enumerate() {
241 if has_skip_attr(&f.attrs).0 {
242 continue;
243 }
244 let skip_with = has_skip_with_attr(&f.attrs);
245 let fname = &field_names[i];
246 if let Some((m, _)) = skip_with {
247 serialize_fields_with.push(quote! {
248 if #m != __afast_marker__ {
249 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
250 }
251 });
252 } else {
253 serialize_fields_with.push(quote! {
254 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
255 });
256 }
257 }
258 arms.push(quote! {
259 #name::#variant_name(#(#field_patterns),*) => {
260 bytes.extend((#i as #tag_ty).to_le_bytes());
261 #(#serialize_fields)*
262 }
263 });
264 arms_with.push(quote! {
265 #name::#variant_name(#(#field_patterns),*) => {
266 bytes.extend((#i as #tag_ty).to_le_bytes());
267 #(#serialize_fields_with)*
268 }
269 });
270 }
271 Fields::Named(fields) => {
272 let all_field_names: Vec<_> = fields
273 .named
274 .iter()
275 .map(|f| f.ident.as_ref().unwrap())
276 .collect();
277 let non_skip_names: Vec<_> = fields
278 .named
279 .iter()
280 .filter(|f| !has_skip_attr(&f.attrs).0)
281 .map(|f| f.ident.as_ref().unwrap())
282 .collect();
283 let has_skip = non_skip_names.len() < all_field_names.len();
284 let mut serialize_fields = Vec::new();
285 for fname in &non_skip_names {
286 serialize_fields.push(quote! {
287 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
288 });
289 }
290 // _with: include all non-skip fields, skip_with matched ones use runtime check
291 let non_skip_fields_with: Vec<_> = fields
292 .named
293 .iter()
294 .filter(|f| !has_skip_attr(&f.attrs).0)
295 .collect();
296 let has_any_skip_with = non_skip_fields_with.len() < all_field_names.len();
297 let non_skip_names_with: Vec<_> = non_skip_fields_with
298 .iter()
299 .map(|f| f.ident.as_ref().unwrap())
300 .collect();
301 let mut serialize_fields_with = Vec::new();
302 for f in &non_skip_fields_with {
303 let fname = f.ident.as_ref().unwrap();
304 let skip_with = has_skip_with_attr(&f.attrs);
305 if let Some((m, _)) = skip_with {
306 serialize_fields_with.push(quote! {
307 if #m != __afast_marker__ {
308 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
309 }
310 });
311 } else {
312 serialize_fields_with.push(quote! {
313 bytes.extend(::afastdata::AFastSerialize::to_bytes(#fname));
314 });
315 }
316 }
317 if has_skip {
318 arms.push(quote! {
319 #name::#variant_name { #(#non_skip_names),*, .. } => {
320 bytes.extend((#i as #tag_ty).to_le_bytes());
321 #(#serialize_fields)*
322 }
323 });
324 } else {
325 arms.push(quote! {
326 #name::#variant_name { #(#non_skip_names),* } => {
327 bytes.extend((#i as #tag_ty).to_le_bytes());
328 #(#serialize_fields)*
329 }
330 });
331 }
332 if has_any_skip_with {
333 arms_with.push(quote! {
334 #name::#variant_name { #(#non_skip_names_with),*, .. } => {
335 bytes.extend((#i as #tag_ty).to_le_bytes());
336 #(#serialize_fields_with)*
337 }
338 });
339 } else {
340 arms_with.push(quote! {
341 #name::#variant_name { #(#non_skip_names_with),* } => {
342 bytes.extend((#i as #tag_ty).to_le_bytes());
343 #(#serialize_fields_with)*
344 }
345 });
346 }
347 }
348 }
349 }
350
351 quote! {
352 impl #impl_generics ::afastdata::AFastSerialize for #name #ty_generics {
353 fn to_bytes(&self) -> Vec<u8> {
354 let mut bytes = Vec::new();
355 match self {
356 #(#arms)*
357 }
358 bytes
359 }
360 fn to_bytes_with(&self, __afast_marker__: &str) -> Vec<u8> {
361 let mut bytes = Vec::new();
362 match self {
363 #(#arms_with)*
364 }
365 bytes
366 }
367 }
368 }
369 }
370 Data::Union(_) => panic!("AFastSerialize does not support unions"),
371 };
372
373 TokenStream::from(expanded)
374}
375
376/// 为结构体或枚举生成 [`AFastDeserialize`] trait 实现。
377///
378/// Generates an [`AFastDeserialize`] trait implementation for a struct or enum.
379///
380/// # 生成的代码 / Generated Code
381///
382/// ## 结构体 / Struct
383///
384/// 为每个字段依次调用 `from_bytes()`,并使用偏移量追踪已消耗的字节数,
385/// 最后构造结构体实例。
386///
387/// Calls `from_bytes()` on each field sequentially, using an offset to track
388/// consumed bytes, then constructs the struct instance.
389///
390/// ```text
391/// // 以下为生成代码的示意(非实际代码)
392/// // The following is an illustration of generated code (not actual code)
393/// impl AFastDeserialize for MyStruct {
394/// fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
395/// let mut offset: usize = 0;
396/// let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
397/// let field1 = __val;
398/// offset += __new_offset;
399/// // ... 更多字段 / more fields ...
400/// Ok((MyStruct { field1, ... }, offset))
401/// }
402/// }
403/// ```
404///
405/// ## 枚举 / Enum
406///
407/// 先读取 `u8` 变体索引,根据索引匹配对应变体,再反序列化该变体的字段。
408/// 可通过 feature 切换为 `u16` 或 `u32`。
409///
410/// First reads the `u8` variant index, matches the corresponding variant by index,
411/// then deserializes the variant's fields.
412/// Switchable to `u16` or `u32` via features.
413///
414/// ```text
415/// // 以下为生成代码的示意(非实际代码)
416/// // The following is an illustration of generated code (not actual code)
417/// impl AFastDeserialize for MyEnum {
418/// fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
419/// let mut offset: usize = 0;
420/// let (__tag, __new_offset) = <u8 as AFastDeserialize>::from_bytes(&data[offset..])?;
421/// offset += __new_offset;
422/// match __tag as usize {
423/// 0 => Ok((MyEnum::Variant1, offset)),
424/// 1 => {
425/// let (__val, __new_offset) = AFastDeserialize::from_bytes(&data[offset..])?;
426/// offset += __new_offset;
427/// Ok((MyEnum::Variant2(__val), offset))
428/// }
429/// v => Err(format!("Unknown variant tag: {} for MyEnum", v)),
430/// }
431/// }
432/// }
433/// ```
434///
435/// # 泛型 / Generics
436///
437/// 如果目标类型包含泛型参数,生成的 `impl` 会同时添加 `AFastSerialize` 和
438/// `AFastDeserialize` 约束。双重约束确保泛型类型在序列化和反序列化两个方向
439/// 上都可用。
440///
441/// If the target type contains generic parameters, the generated `impl` adds both
442/// `AFastSerialize` and `AFastDeserialize` bounds. The dual bounds ensure the generic
443/// type is available in both serialization and deserialization directions.
444///
445/// # Panics
446///
447/// 对 union 类型使用此宏会触发编译 panic。
448///
449/// Using this macro on a union type will trigger a compile-time panic.
450#[proc_macro_derive(AFastDeserialize, attributes(afast))]
451pub fn derive_deserialize(input: TokenStream) -> TokenStream {
452 let input = parse_macro_input!(input as DeriveInput);
453 let name = &input.ident;
454 let generics = &input.generics;
455
456 // 为泛型参数添加 AFastSerialize + AFastDeserialize trait 约束
457 // Add AFastSerialize + AFastDeserialize trait bounds to generic parameters
458 let mut generics_with_bounds = generics.clone();
459 for param in &mut generics_with_bounds.params {
460 if let syn::GenericParam::Type(ref mut ty) = *param {
461 ty.bounds
462 .push(syn::parse_quote!(::afastdata::AFastSerialize));
463 ty.bounds
464 .push(syn::parse_quote!(::afastdata::AFastDeserialize));
465 }
466 }
467 let (impl_generics, _, _) = generics_with_bounds.split_for_impl();
468 let (_, ty_generics, _) = generics.split_for_impl();
469
470 let expanded = match &input.data {
471 Data::Struct(data) => {
472 let (construct, field_desers) =
473 generate_deserialize_fields(&data.fields, name, &ty_generics);
474 let (construct_with, field_desers_with) = generate_deserialize_fields_with(
475 &data.fields,
476 name,
477 &ty_generics,
478 "__afast_marker__",
479 );
480 quote! {
481 impl #impl_generics ::afastdata::AFastDeserialize for #name #ty_generics {
482 fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::afastdata::Error> {
483 let mut offset: usize = 0;
484 #(#field_desers)*
485 Ok((#construct, offset))
486 }
487 fn from_bytes_with(data: &[u8], __afast_marker__: &str) -> Result<(Self, usize), ::afastdata::Error> {
488 let mut offset: usize = 0;
489 #(#field_desers_with)*
490 Ok((#construct_with, offset))
491 }
492 }
493 }
494 }
495 Data::Enum(data) => {
496 let (tag_ty, _) = tag_type();
497 let mut arms = Vec::new();
498 let mut arms_with = Vec::new();
499 for (i, variant) in data.variants.iter().enumerate() {
500 let variant_name = &variant.ident;
501
502 match &variant.fields {
503 Fields::Unit => {
504 arms.push(quote! {
505 #i => {
506 Ok((#name::#variant_name, offset))
507 }
508 });
509 arms_with.push(quote! {
510 #i => {
511 Ok((#name::#variant_name, offset))
512 }
513 });
514 }
515 Fields::Unnamed(fields) => {
516 let mut field_desers = Vec::new();
517 let mut field_desers_with = Vec::new();
518 let mut field_names = Vec::new();
519 for (i, f) in fields.unnamed.iter().enumerate() {
520 let fname = syn::Ident::new(&format!("__f{}", i), variant_name.span());
521 let ftype = &f.ty;
522 let (skip, default_fn) = has_skip_attr(&f.attrs);
523 if skip {
524 if let Some(func_name) = default_fn.clone() {
525 match syn::parse_str::<syn::Ident>(&func_name) {
526 Ok(ident) => {
527 field_desers.push(quote! {
528 let #fname: #ftype = #ident();
529 });
530 field_desers_with.push(quote! {
531 let #fname: #ftype = #ident();
532 });
533 }
534 Err(_) => {
535 field_desers.push(quote! {
536 compile_error!(concat!("invalid function name in skip: ", #func_name));
537 });
538 field_desers_with.push(quote! {
539 compile_error!(concat!("invalid function name in skip: ", #func_name));
540 });
541 }
542 }
543 } else {
544 field_desers.push(quote! {
545 let #fname: #ftype = <#ftype as ::std::default::Default>::default();
546 });
547 field_desers_with.push(quote! {
548 let #fname: #ftype = <#ftype as ::std::default::Default>::default();
549 });
550 }
551 } else {
552 let validates = parse_validations(&fname, ftype, &f.attrs);
553 field_desers.push(quote! {
554 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
555 let #fname: #ftype = __val;
556 #(#validates)*
557 offset += __new_offset;
558 });
559 // _with: check skip_with
560 let skip_with = has_skip_with_attr(&f.attrs);
561 if let Some((m, sw_default)) = skip_with {
562 let default_expr = if let Some(fn_name) = sw_default {
563 match syn::parse_str::<syn::Ident>(&fn_name) {
564 Ok(ident) => quote! { #ident() },
565 Err(_) => {
566 quote! { { compile_error!(concat!("invalid function name in skip_with: ", #fn_name)); <#ftype as ::std::default::Default>::default() } }
567 }
568 }
569 } else {
570 quote! { <#ftype as ::std::default::Default>::default() }
571 };
572 field_desers_with.push(quote! {
573 let #fname: #ftype = if __afast_marker__ == #m {
574 #default_expr
575 } else {
576 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
577 #(#validates)*
578 offset += __new_offset;
579 __val
580 };
581 });
582 } else {
583 field_desers_with.push(quote! {
584 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
585 let #fname: #ftype = __val;
586 #(#validates)*
587 offset += __new_offset;
588 });
589 }
590 }
591 field_names.push(fname);
592 }
593 arms.push(quote! {
594 #i => {
595 #(#field_desers)*
596 Ok((#name::#variant_name(#(#field_names),*), offset))
597 }
598 });
599 arms_with.push(quote! {
600 #i => {
601 #(#field_desers_with)*
602 Ok((#name::#variant_name(#(#field_names),*), offset))
603 }
604 });
605 }
606 Fields::Named(fields) => {
607 let mut field_desers = Vec::new();
608 let mut field_desers_with = Vec::new();
609 let mut field_names = Vec::new();
610 for f in &fields.named {
611 let fname = f.ident.as_ref().unwrap();
612 let ftype = &f.ty;
613 let (skip, default_fn) = has_skip_attr(&f.attrs);
614 if skip {
615 if let Some(func_name) = default_fn.clone() {
616 match syn::parse_str::<syn::Ident>(&func_name) {
617 Ok(ident) => {
618 field_desers.push(quote! {
619 let #fname: #ftype = #ident();
620 });
621 field_desers_with.push(quote! {
622 let #fname: #ftype = #ident();
623 });
624 }
625 Err(_) => {
626 field_desers.push(quote! {
627 compile_error!(concat!("invalid function name in skip: ", #func_name));
628 });
629 field_desers_with.push(quote! {
630 compile_error!(concat!("invalid function name in skip: ", #func_name));
631 });
632 }
633 }
634 } else {
635 field_desers.push(quote! {
636 let #fname: #ftype = <#ftype as ::std::default::Default>::default();
637 });
638 field_desers_with.push(quote! {
639 let #fname: #ftype = <#ftype as ::std::default::Default>::default();
640 });
641 }
642 } else {
643 let validates = parse_validations(fname, ftype, &f.attrs);
644 field_desers.push(quote! {
645 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
646 let #fname: #ftype = __val;
647 #(#validates)*
648 offset += __new_offset;
649 });
650 // _with: check skip_with
651 let skip_with = has_skip_with_attr(&f.attrs);
652 if let Some((m, sw_default)) = skip_with {
653 let default_expr = if let Some(fn_name) = sw_default {
654 match syn::parse_str::<syn::Ident>(&fn_name) {
655 Ok(ident) => quote! { #ident() },
656 Err(_) => {
657 quote! { { compile_error!(concat!("invalid function name in skip_with: ", #fn_name)); <#ftype as ::std::default::Default>::default() } }
658 }
659 }
660 } else {
661 quote! { <#ftype as ::std::default::Default>::default() }
662 };
663 field_desers_with.push(quote! {
664 let #fname: #ftype = if __afast_marker__ == #m {
665 #default_expr
666 } else {
667 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
668 #(#validates)*
669 offset += __new_offset;
670 __val
671 };
672 });
673 } else {
674 field_desers_with.push(quote! {
675 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
676 let #fname: #ftype = __val;
677 #(#validates)*
678 offset += __new_offset;
679 });
680 }
681 }
682 field_names.push(fname);
683 }
684 arms.push(quote! {
685 #i => {
686 #(#field_desers)*
687 Ok((#name::#variant_name { #(#field_names),* }, offset))
688 }
689 });
690 arms_with.push(quote! {
691 #i => {
692 #(#field_desers_with)*
693 Ok((#name::#variant_name { #(#field_names),* }, offset))
694 }
695 });
696 }
697 }
698 }
699
700 quote! {
701 impl #impl_generics ::afastdata::AFastDeserialize for #name #ty_generics {
702 fn from_bytes(data: &[u8]) -> Result<(Self, usize), ::afastdata::Error> {
703 let mut offset: usize = 0;
704 let (__tag_bytes, __new_offset) = <#tag_ty as ::afastdata::AFastDeserialize>::from_bytes(&data[offset..])?;
705 offset += __new_offset;
706 match __tag_bytes as usize {
707 #(#arms)*
708 v => Err(::afastdata::Error::deserialize(format!("Unknown variant tag: {} for {}", v, ::std::stringify!(#name)))),
709 }
710 }
711 fn from_bytes_with(data: &[u8], __afast_marker__: &str) -> Result<(Self, usize), ::afastdata::Error> {
712 let mut offset: usize = 0;
713 let (__tag_bytes, __new_offset) = <#tag_ty as ::afastdata::AFastDeserialize>::from_bytes(&data[offset..])?;
714 offset += __new_offset;
715 match __tag_bytes as usize {
716 #(#arms_with)*
717 v => Err(::afastdata::Error::deserialize(format!("Unknown variant tag: {} for {}", v, ::std::stringify!(#name)))),
718 }
719 }
720 }
721 }
722 }
723 Data::Union(_) => panic!("AFastDeserialize does not support unions"),
724 };
725
726 TokenStream::from(expanded)
727}
728
729/// 为结构体的字段生成序列化代码。内部辅助函数。
730///
731/// Generates serialization code for struct fields. Internal helper.
732///
733/// # 参数 / Parameters
734///
735/// - `fields`:结构体的字段定义 / The struct's field definitions
736/// - `self_prefix`:访问字段时使用的前缀(如 `self` 或变体解构变量)
737/// / The prefix used to access fields (e.g., `self` or a variant destructure variable)
738///
739/// # 返回值 / Returns
740///
741/// 返回一个 `TokenStream` 列表,每个元素对应一个字段的序列化语句。
742///
743/// Returns a list of `TokenStream`s, each corresponding to a serialization statement
744/// for one field.
745///
746/// # 生成格式 / Generated Format
747///
748/// - **命名字段 (Named)**:`bytes.extend(AFastSerialize::to_bytes(&self.field_name));`
749/// - **元组字段 (Unnamed)**:`bytes.extend(AFastSerialize::to_bytes(&self.0));`
750/// - **单元字段 (Unit)**:不生成任何代码 / Generates no code
751fn generate_serialize_fields(
752 fields: &Fields,
753 self_prefix: proc_macro2::TokenStream,
754) -> Vec<proc_macro2::TokenStream> {
755 match fields {
756 Fields::Named(named) => named
757 .named
758 .iter()
759 .filter(|f| !has_skip_attr(&f.attrs).0)
760 .map(|f| {
761 let fname = f.ident.as_ref().unwrap();
762 quote! {
763 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#fname));
764 }
765 })
766 .collect(),
767 Fields::Unnamed(unnamed) => unnamed
768 .unnamed
769 .iter()
770 .enumerate()
771 .filter(|(_, f)| !has_skip_attr(&f.attrs).0)
772 .map(|(i, _)| {
773 let idx = Index::from(i);
774 quote! {
775 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#idx));
776 }
777 })
778 .collect(),
779 Fields::Unit => vec![],
780 }
781}
782
783/// 为结构体的字段生成带 marker 的序列化代码。内部辅助函数。
784///
785/// Generates marker-aware serialization code for struct fields. Internal helper.
786///
787/// 跳过 `#[afast(skip)]` 字段,marker 匹配的 `#[afast(skip_with(...))]` 字段在运行时跳过。
788///
789/// Skips `#[afast(skip)]` fields unconditionally. `#[afast(skip_with(...))]` fields
790/// whose marker matches are skipped at runtime.
791fn generate_serialize_fields_with(
792 fields: &Fields,
793 self_prefix: proc_macro2::TokenStream,
794 marker: &proc_macro2::Ident,
795) -> Vec<proc_macro2::TokenStream> {
796 match fields {
797 Fields::Named(named) => {
798 let mut stmts = Vec::new();
799 for f in &named.named {
800 if has_skip_attr(&f.attrs).0 {
801 continue;
802 }
803 let fname = f.ident.as_ref().unwrap();
804 let skip_with = has_skip_with_attr(&f.attrs);
805 if let Some((m, _)) = skip_with {
806 stmts.push(quote! {
807 if #m != #marker {
808 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#fname));
809 }
810 });
811 } else {
812 stmts.push(quote! {
813 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#fname));
814 });
815 }
816 }
817 stmts
818 }
819 Fields::Unnamed(unnamed) => {
820 let mut stmts = Vec::new();
821 for (i, f) in unnamed.unnamed.iter().enumerate() {
822 if has_skip_attr(&f.attrs).0 {
823 continue;
824 }
825 let idx = Index::from(i);
826 let skip_with = has_skip_with_attr(&f.attrs);
827 if let Some((m, _)) = skip_with {
828 stmts.push(quote! {
829 if #m != #marker {
830 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#idx));
831 }
832 });
833 } else {
834 stmts.push(quote! {
835 bytes.extend(::afastdata::AFastSerialize::to_bytes(&#self_prefix.#idx));
836 });
837 }
838 }
839 stmts
840 }
841 Fields::Unit => vec![],
842 }
843}
844
845fn has_skip_attr(attrs: &[Attribute]) -> (bool, Option<String>) {
846 for attr in attrs {
847 if attr.path().is_ident("afast")
848 && let Ok(nested) =
849 attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
850 {
851 for meta in nested {
852 match meta {
853 Meta::Path(path) if path.is_ident("skip") => {
854 return (true, None);
855 }
856 Meta::List(meta_list) if meta_list.path.is_ident("skip") => {
857 if let Ok(lit_str) = syn::parse2::<LitStr>(meta_list.tokens.clone()) {
858 return (true, Some(lit_str.value()));
859 } else {
860 return (true, None);
861 }
862 }
863 _ => {}
864 }
865 }
866 }
867 }
868 (false, None)
869}
870
871/// 检查字段是否有 `#[afast(skip_with("marker"))]` 或
872/// `#[afast(skip_with("marker", "default_fn"))]` 属性。
873///
874/// Checks whether a field has `#[afast(skip_with("marker"))]` or
875/// `#[afast(skip_with("marker", "default_fn"))]` attribute.
876///
877/// 返回值:`(marker, default_fn)`
878/// - `Some(("marker", None))`:`#[afast(skip_with("marker"))]`,反序列化用 Default
879/// - `Some(("marker", Some("fn")))`:`#[afast(skip_with("marker", "fn"))]`
880/// - `None`:无 skip_with 属性
881fn has_skip_with_attr(attrs: &[Attribute]) -> Option<(String, Option<String>)> {
882 for attr in attrs {
883 if attr.path().is_ident("afast")
884 && let Ok(nested) =
885 attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
886 {
887 for meta in nested {
888 if let Meta::List(meta_list) = meta {
889 if meta_list.path.is_ident("skip_with") {
890 let tokens = meta_list.tokens.clone();
891 if let Ok(args) = syn::parse2::<SkipWithArgs>(tokens) {
892 return Some((args.marker.value(), args.default_fn.map(|s| s.value())));
893 }
894 return None;
895 }
896 }
897 }
898 }
899 }
900 None
901}
902
903struct SkipWithArgs {
904 marker: LitStr,
905 default_fn: Option<LitStr>,
906}
907
908impl Parse for SkipWithArgs {
909 fn parse(input: ParseStream) -> syn::Result<Self> {
910 let marker: LitStr = input.parse()?;
911 let default_fn = if input.peek(Token![,]) {
912 input.parse::<Token![,]>()?;
913 Some(input.parse::<LitStr>()?)
914 } else {
915 None
916 };
917 Ok(SkipWithArgs { marker, default_fn })
918 }
919}
920
921enum RangeValue {
922 Int(LitInt),
923 Float(LitFloat),
924}
925
926impl RangeValue {
927 fn to_token_stream(&self) -> proc_macro2::TokenStream {
928 match self {
929 RangeValue::Int(v) => quote! { #v },
930 RangeValue::Float(v) => quote! { #v },
931 }
932 }
933}
934
935struct Range {
936 value: RangeValue,
937 _comma1: Token![,],
938 code: LitInt,
939 _comma2: Token![,],
940 msg: LitStr,
941}
942
943impl Parse for Range {
944 fn parse(input: ParseStream) -> syn::Result<Self> {
945 // Try to parse as float first, then as int
946 let value = if input.peek(LitFloat) {
947 RangeValue::Float(input.parse()?)
948 } else {
949 RangeValue::Int(input.parse()?)
950 };
951 Ok(Range {
952 value,
953 _comma1: input.parse()?,
954 code: input.parse()?,
955 _comma2: input.parse()?,
956 msg: input.parse()?,
957 })
958 }
959}
960
961struct Length {
962 min: LitInt,
963 _comma1: Token![,],
964 max: LitInt,
965 _comma2: Token![,],
966 code: LitInt,
967 _comma3: Token![,],
968 msg: LitStr,
969}
970
971impl Parse for Length {
972 fn parse(input: ParseStream) -> syn::Result<Self> {
973 Ok(Length {
974 min: input.parse()?,
975 _comma1: input.parse()?,
976 max: input.parse()?,
977 _comma2: input.parse()?,
978 code: input.parse()?,
979 _comma3: input.parse()?,
980 msg: input.parse()?,
981 })
982 }
983}
984
985#[derive(Clone)]
986enum ValidateValue {
987 Int(i64),
988 Float(f64),
989 Bool(bool),
990 Str(String),
991}
992
993impl ValidateValue {
994 /// 将值转换为代码生成中使用的 TokenStream
995 ///
996 /// 例如:
997 /// ValidateValue::Int(42) → quote! { 42 }
998 /// ValidateValue::Str("hello") → quote! { "hello" }
999 fn to_token_stream(&self) -> proc_macro2::TokenStream {
1000 match self {
1001 ValidateValue::Int(v) => quote! { #v },
1002
1003 ValidateValue::Float(v) => {
1004 // 浮点数通过字符串解析来保持精度
1005 let v_str = v.to_string();
1006 v_str.parse().unwrap_or_else(|_| {
1007 // 如果字符串解析失败,使用直接值
1008 quote! { #v }
1009 })
1010 }
1011
1012 ValidateValue::Bool(v) => quote! { #v },
1013 ValidateValue::Str(v) => quote! { #v },
1014 }
1015 }
1016}
1017
1018struct OfValidator {
1019 allowed_values: Vec<ValidateValue>,
1020 code: syn::LitInt,
1021 msg: syn::LitStr,
1022}
1023
1024impl Parse for OfValidator {
1025 fn parse(input: ParseStream) -> syn::Result<Self> {
1026 let content;
1027 syn::bracketed!(content in input);
1028
1029 let mut values = Vec::new();
1030
1031 if !content.is_empty() {
1032 loop {
1033 let lit = content.parse::<Lit>()?;
1034
1035 let value = match lit {
1036 Lit::Int(lit_int) => {
1037 let int_value: i64 = lit_int.base10_parse()?;
1038 ValidateValue::Int(int_value)
1039 }
1040
1041 Lit::Float(lit_float) => {
1042 let float_value: f64 = lit_float.base10_parse()?;
1043 ValidateValue::Float(float_value)
1044 }
1045
1046 Lit::Bool(lit_bool) => ValidateValue::Bool(lit_bool.value),
1047
1048 Lit::Str(lit_str) => ValidateValue::Str(lit_str.value()),
1049
1050 _ => {
1051 return Err(syn::Error::new_spanned(
1052 &lit,
1053 "unsupported literal type in 'of' validator; \
1054 only int, float, bool, and str literals are supported",
1055 ));
1056 }
1057 };
1058
1059 values.push(value);
1060
1061 if !content.peek(Token![,]) {
1062 break;
1063 }
1064
1065 content.parse::<Token![,]>()?;
1066
1067 if content.is_empty() {
1068 break;
1069 }
1070 }
1071 }
1072
1073 input.parse::<Token![,]>()?;
1074
1075 let code = input.parse::<syn::LitInt>()?;
1076
1077 input.parse::<Token![,]>()?;
1078
1079 let msg = input.parse::<syn::LitStr>()?;
1080
1081 Ok(OfValidator {
1082 allowed_values: values,
1083 code,
1084 msg,
1085 })
1086 }
1087}
1088
1089/// 检测字段类型是否为数值类型(i8..i128, u8..u128, f32, f64)。
1090///
1091/// Checks whether the field type is a numeric type.
1092fn is_numeric_type(ty: &Type) -> bool {
1093 if let Type::Path(TypePath { path, .. }) = ty {
1094 if let Some(segment) = path.segments.last() {
1095 let name = segment.ident.to_string();
1096 return matches!(
1097 name.as_str(),
1098 "i8" | "i16"
1099 | "i32"
1100 | "i64"
1101 | "i128"
1102 | "u8"
1103 | "u16"
1104 | "u32"
1105 | "u64"
1106 | "u128"
1107 | "usize"
1108 | "f32"
1109 | "f64"
1110 );
1111 }
1112 }
1113 false
1114}
1115
1116/// 检测字段类型是否为 Option<T>。
1117///
1118/// Checks whether the field type is `Option<T>`.
1119fn is_option_type(ty: &Type) -> bool {
1120 if let Type::Path(TypePath {
1121 path: Path { segments, .. },
1122 ..
1123 }) = ty
1124 {
1125 segments.len() == 1 && segments[0].ident == "Option"
1126 } else {
1127 false
1128 }
1129}
1130
1131/// 提取 Option<T> 的内部类型 T。
1132///
1133/// Extracts the inner type `T` from `Option<T>`.
1134fn extract_option_inner(ty: &Type) -> Option<&Type> {
1135 if let Type::Path(TypePath {
1136 path: Path { segments, .. },
1137 ..
1138 }) = ty
1139 {
1140 if segments.len() == 1 && segments[0].ident == "Option" {
1141 if let syn::PathArguments::AngleBracketed(args) = &segments[0].arguments {
1142 if let Some(syn::GenericArgument::Type(inner)) = args.args.first() {
1143 return Some(inner);
1144 }
1145 }
1146 }
1147 }
1148 None
1149}
1150
1151/// 检测字段类型是否为可进行比较校验的类型(数值类型或 Option<数值类型>)。
1152///
1153/// Checks whether the field type supports comparison validation
1154/// (numeric type or Option<numeric type>).
1155fn is_comparable_type(ty: &Type) -> bool {
1156 if is_numeric_type(ty) {
1157 return true;
1158 }
1159 if let Some(inner) = extract_option_inner(ty) {
1160 return is_numeric_type(inner);
1161 }
1162 false
1163}
1164
1165/// 检测字段类型是否为字符串或集合类型(String, &str, Vec<T>, [T; N])。
1166///
1167/// Checks whether the field type is a string or collection type.
1168fn is_collection_type(ty: &Type) -> bool {
1169 if let Type::Path(TypePath { path, .. }) = ty {
1170 if let Some(segment) = path.segments.last() {
1171 let name = segment.ident.to_string();
1172 return matches!(
1173 name.as_str(),
1174 "String" | "Vec" | "BTreeSet" | "BTreeMap" | "HashSet" | "HashMap"
1175 );
1176 }
1177 }
1178 // [T; N] arrays
1179 if let Type::Array(_) = ty {
1180 return true;
1181 }
1182 // &str
1183 if let Type::Reference(r) = ty {
1184 if let Type::Path(TypePath { path, .. }) = &*r.elem {
1185 if let Some(segment) = path.segments.last() {
1186 return segment.ident == "str";
1187 }
1188 }
1189 }
1190 false
1191}
1192
1193/// 解析字段上的 `#[afast(...)]` 校验属性,生成校验代码。
1194///
1195/// Parses `#[afast(...)]` validation attributes on a field and generates
1196/// validation code blocks.
1197///
1198/// # 参数 / Parameters
1199///
1200/// - `field_name`:字段名 / Field name
1201/// - `field_type`:字段类型 / Field type
1202/// - `attrs`:字段的属性列表 / Field attributes
1203///
1204/// # 返回值 / Returns
1205///
1206/// 返回校验语句的 `TokenStream` 列表。
1207///
1208/// Returns a list of validation `TokenStream` blocks.
1209fn parse_validations(
1210 field_name: &syn::Ident,
1211 field_type: &Type,
1212 attrs: &[Attribute],
1213) -> Vec<proc_macro2::TokenStream> {
1214 let mut validates = Vec::new();
1215 for attr in attrs {
1216 if attr.path().is_ident("afast") {
1217 let nested = match attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
1218 {
1219 Ok(n) => n,
1220 Err(e) => {
1221 validates.push(e.to_compile_error());
1222 continue;
1223 }
1224 };
1225 for meta in nested {
1226 if let Meta::List(meta) = meta {
1227 if meta.path.is_ident("gt") {
1228 if !is_comparable_type(field_type) {
1229 validates.push(
1230 syn::Error::new_spanned(
1231 &meta.path,
1232 format!(
1233 "validation `gt` is only supported on numeric types or Option<numeric>, but field `{}` is not",
1234 field_name
1235 ),
1236 )
1237 .to_compile_error(),
1238 );
1239 continue;
1240 }
1241 let inner = match meta.parse_args::<Range>() {
1242 Ok(v) => v,
1243 Err(e) => {
1244 validates.push(e.to_compile_error());
1245 continue;
1246 }
1247 };
1248 let cmp_value = inner.value.to_token_stream();
1249 let code = match inner.code.base10_parse::<i64>() {
1250 Ok(v) => v,
1251 Err(e) => {
1252 validates.push(
1253 syn::Error::new_spanned(
1254 &inner.code,
1255 format!("invalid error code: {}", e),
1256 )
1257 .to_compile_error(),
1258 );
1259 continue;
1260 }
1261 };
1262 let err_msg = inner
1263 .msg
1264 .value()
1265 .replace("${field}", &field_name.to_string());
1266 if is_option_type(field_type) {
1267 validates.push(quote! {
1268 if let Some(ref __val) = #field_name {
1269 if *__val <= #cmp_value {
1270 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1271 }
1272 }
1273 });
1274 } else {
1275 validates.push(quote! {
1276 if #field_name <= #cmp_value {
1277 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1278 }
1279 });
1280 }
1281 } else if meta.path.is_ident("gte") {
1282 if !is_comparable_type(field_type) {
1283 validates.push(
1284 syn::Error::new_spanned(
1285 &meta.path,
1286 format!(
1287 "validation `gte` is only supported on numeric types (or Option<numeric>), but field `{}` is not",
1288 field_name
1289 ),
1290 )
1291 .to_compile_error(),
1292 );
1293 continue;
1294 }
1295 let inner = match meta.parse_args::<Range>() {
1296 Ok(v) => v,
1297 Err(e) => {
1298 validates.push(e.to_compile_error());
1299 continue;
1300 }
1301 };
1302 let cmp_value = inner.value.to_token_stream();
1303 let code = match inner.code.base10_parse::<i64>() {
1304 Ok(v) => v,
1305 Err(e) => {
1306 validates.push(
1307 syn::Error::new_spanned(
1308 &inner.code,
1309 format!("invalid error code: {}", e),
1310 )
1311 .to_compile_error(),
1312 );
1313 continue;
1314 }
1315 };
1316 let err_msg = inner
1317 .msg
1318 .value()
1319 .replace("${field}", &field_name.to_string());
1320 if is_option_type(field_type) {
1321 validates.push(quote! {
1322 if let Some(ref __val) = #field_name {
1323 if *__val < #cmp_value {
1324 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1325 }
1326 }
1327 });
1328 } else {
1329 validates.push(quote! {
1330 if #field_name < #cmp_value {
1331 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1332 }
1333 });
1334 }
1335 } else if meta.path.is_ident("lt") {
1336 if !is_comparable_type(field_type) {
1337 validates.push(
1338 syn::Error::new_spanned(
1339 &meta.path,
1340 format!(
1341 "validation `lt` is only supported on numeric types (or Option<numeric>), but field `{}` is not",
1342 field_name
1343 ),
1344 )
1345 .to_compile_error(),
1346 );
1347 continue;
1348 }
1349 let inner = match meta.parse_args::<Range>() {
1350 Ok(v) => v,
1351 Err(e) => {
1352 validates.push(e.to_compile_error());
1353 continue;
1354 }
1355 };
1356 let cmp_value = inner.value.to_token_stream();
1357 let code = match inner.code.base10_parse::<i64>() {
1358 Ok(v) => v,
1359 Err(e) => {
1360 validates.push(
1361 syn::Error::new_spanned(
1362 &inner.code,
1363 format!("invalid error code: {}", e),
1364 )
1365 .to_compile_error(),
1366 );
1367 continue;
1368 }
1369 };
1370 let err_msg = inner
1371 .msg
1372 .value()
1373 .replace("${field}", &field_name.to_string());
1374 if is_option_type(field_type) {
1375 validates.push(quote! {
1376 if let Some(ref __val) = #field_name {
1377 if *__val >= #cmp_value {
1378 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1379 }
1380 }
1381 });
1382 } else {
1383 validates.push(quote! {
1384 if #field_name >= #cmp_value {
1385 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1386 }
1387 });
1388 }
1389 } else if meta.path.is_ident("lte") {
1390 if !is_comparable_type(field_type) {
1391 validates.push(
1392 syn::Error::new_spanned(
1393 &meta.path,
1394 format!(
1395 "validation `lte` is only supported on numeric types (or Option<numeric>), but field `{}` is not",
1396 field_name
1397 ),
1398 )
1399 .to_compile_error(),
1400 );
1401 continue;
1402 }
1403 let inner = match meta.parse_args::<Range>() {
1404 Ok(v) => v,
1405 Err(e) => {
1406 validates.push(e.to_compile_error());
1407 continue;
1408 }
1409 };
1410 let cmp_value = inner.value.to_token_stream();
1411 let code = match inner.code.base10_parse::<i64>() {
1412 Ok(v) => v,
1413 Err(e) => {
1414 validates.push(
1415 syn::Error::new_spanned(
1416 &inner.code,
1417 format!("invalid error code: {}", e),
1418 )
1419 .to_compile_error(),
1420 );
1421 continue;
1422 }
1423 };
1424 let err_msg = inner
1425 .msg
1426 .value()
1427 .replace("${field}", &field_name.to_string());
1428 if is_option_type(field_type) {
1429 validates.push(quote! {
1430 if let Some(ref __val) = #field_name {
1431 if *__val > #cmp_value {
1432 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1433 }
1434 }
1435 });
1436 } else {
1437 validates.push(quote! {
1438 if #field_name > #cmp_value {
1439 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1440 }
1441 });
1442 }
1443 } else if meta.path.is_ident("len") {
1444 let field_is_option = is_option_type(field_type);
1445 // For Option<T>, check if inner type is a collection
1446 // For non-Option, check directly
1447 if field_is_option {
1448 // Option<T> is allowed - inner type check is deferred to runtime
1449 } else if !is_collection_type(field_type) {
1450 validates.push(
1451 syn::Error::new_spanned(
1452 &meta.path,
1453 format!(
1454 "validation `len` is only supported on String, &[u8], Vec<T>, [T; N], or Option<T> wrapping these types, but field `{}` is not",
1455 field_name
1456 ),
1457 )
1458 .to_compile_error(),
1459 );
1460 continue;
1461 }
1462
1463 let inner = match meta.parse_args::<Length>() {
1464 Ok(v) => v,
1465 Err(e) => {
1466 validates.push(e.to_compile_error());
1467 continue;
1468 }
1469 };
1470 let min_value = match inner.min.base10_parse::<i64>() {
1471 Ok(v) => v,
1472 Err(e) => {
1473 validates.push(
1474 syn::Error::new_spanned(
1475 &inner.min,
1476 format!("invalid min value: {}", e),
1477 )
1478 .to_compile_error(),
1479 );
1480 continue;
1481 }
1482 };
1483 let max_value = match inner.max.base10_parse::<i64>() {
1484 Ok(v) => v,
1485 Err(e) => {
1486 validates.push(
1487 syn::Error::new_spanned(
1488 &inner.max,
1489 format!("invalid max value: {}", e),
1490 )
1491 .to_compile_error(),
1492 );
1493 continue;
1494 }
1495 };
1496 let code = match inner.code.base10_parse::<i64>() {
1497 Ok(v) => v,
1498 Err(e) => {
1499 validates.push(
1500 syn::Error::new_spanned(
1501 &inner.code,
1502 format!("invalid error code: {}", e),
1503 )
1504 .to_compile_error(),
1505 );
1506 continue;
1507 }
1508 };
1509 let err_msg = inner
1510 .msg
1511 .value()
1512 .replace("${field}", &field_name.to_string());
1513 // -1 is a sentinel meaning "no limit", so skip range check when either is -1
1514 if min_value >= 0 && max_value >= 0 && min_value > max_value {
1515 validates.push(
1516 syn::Error::new_spanned(
1517 &meta.path,
1518 format!(
1519 "invalid len validation: min ({}) > max ({}) for field `{}`",
1520 min_value, max_value, field_name
1521 ),
1522 )
1523 .to_compile_error(),
1524 );
1525 continue;
1526 }
1527 if min_value < 0 && max_value < 0 {
1528 validates.push(
1529 syn::Error::new_spanned(
1530 &meta.path,
1531 format!(
1532 "invalid len validation: both min and max are negative for field `{}`",
1533 field_name
1534 ),
1535 )
1536 .to_compile_error(),
1537 );
1538 continue;
1539 } else if min_value < 0 {
1540 let max: usize = match max_value.try_into() {
1541 Ok(v) => v,
1542 Err(_) => {
1543 validates.push(
1544 syn::Error::new_spanned(
1545 &inner.max,
1546 "value too large for usize",
1547 )
1548 .to_compile_error(),
1549 );
1550 continue;
1551 }
1552 };
1553 if field_is_option {
1554 validates.push(quote! {
1555 if let Some(ref __val) = #field_name {
1556 if __val.len() > #max {
1557 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1558 }
1559 }
1560 });
1561 } else {
1562 validates.push(quote! {
1563 if #field_name.len() > #max {
1564 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1565 }
1566 });
1567 }
1568 } else if max_value < 0 {
1569 let min: usize = match min_value.try_into() {
1570 Ok(v) => v,
1571 Err(_) => {
1572 validates.push(
1573 syn::Error::new_spanned(
1574 &inner.min,
1575 "value too large for usize",
1576 )
1577 .to_compile_error(),
1578 );
1579 continue;
1580 }
1581 };
1582 if field_is_option {
1583 validates.push(quote! {
1584 if let Some(ref __val) = #field_name {
1585 if __val.len() < #min {
1586 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1587 }
1588 }
1589 });
1590 } else {
1591 validates.push(quote! {
1592 if #field_name.len() < #min {
1593 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1594 }
1595 });
1596 }
1597 } else {
1598 let min: usize = match min_value.try_into() {
1599 Ok(v) => v,
1600 Err(_) => {
1601 validates.push(
1602 syn::Error::new_spanned(
1603 &inner.min,
1604 "value too large for usize",
1605 )
1606 .to_compile_error(),
1607 );
1608 continue;
1609 }
1610 };
1611 let max: usize = match max_value.try_into() {
1612 Ok(v) => v,
1613 Err(_) => {
1614 validates.push(
1615 syn::Error::new_spanned(
1616 &inner.max,
1617 "value too large for usize",
1618 )
1619 .to_compile_error(),
1620 );
1621 continue;
1622 }
1623 };
1624 if field_is_option {
1625 validates.push(quote! {
1626 let length = match &#field_name {
1627 Some(s) => {
1628 let __length = s.len();
1629 if __length < #min || __length > #max {
1630 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1631 }
1632 },
1633 None => {},
1634 };
1635 });
1636 } else {
1637 validates.push(quote! {
1638 if #field_name.len() < #min || #field_name.len() > #max {
1639 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1640 }
1641 });
1642 }
1643 }
1644 } else if meta.path.is_ident("of") {
1645 let inner = match meta.parse_args::<OfValidator>() {
1646 Ok(v) => v,
1647 Err(e) => {
1648 validates.push(e.to_compile_error());
1649 continue;
1650 }
1651 };
1652 let allowed_values = inner.allowed_values.clone();
1653 let code = match inner.code.base10_parse::<i64>() {
1654 Ok(v) => v,
1655 Err(e) => {
1656 validates.push(
1657 syn::Error::new_spanned(
1658 &inner.code,
1659 format!("invalid error code: {}", e),
1660 )
1661 .to_compile_error(),
1662 );
1663 continue;
1664 }
1665 };
1666 let err_msg = inner
1667 .msg
1668 .value()
1669 .replace("${field}", &field_name.to_string());
1670 let values_tokens: Vec<_> =
1671 allowed_values.iter().map(|v| v.to_token_stream()).collect();
1672 validates.push(quote! {
1673 if !matches!(#field_name, #(#values_tokens)|*) {
1674 return Err(::afastdata::Error::validate(#code, #err_msg.to_string()));
1675 }
1676 });
1677 } else if meta.path.is_ident("func") {
1678 let inner = match meta.parse_args::<LitStr>() {
1679 Ok(v) => v,
1680 Err(e) => {
1681 validates.push(e.to_compile_error());
1682 continue;
1683 }
1684 };
1685 let ident = match syn::parse_str::<syn::Ident>(&inner.value()) {
1686 Ok(v) => v,
1687 Err(e) => {
1688 validates.push(
1689 syn::Error::new_spanned(
1690 &inner,
1691 format!("invalid function name `{}`: {}", inner.value(), e),
1692 )
1693 .to_compile_error(),
1694 );
1695 continue;
1696 }
1697 };
1698 let field = field_name.to_string();
1699 validates.push(quote! {
1700 match #ident(&#field_name, #field) {
1701 Ok(()) => {},
1702 Err(e) => return Err(e.to_afastdata_error()),
1703 }
1704 });
1705 }
1706 }
1707 }
1708 }
1709 }
1710 validates
1711}
1712
1713/// 为结构体的字段生成反序列化代码以及构造表达式。内部辅助函数。
1714///
1715/// Generates deserialization code for struct fields along with the construction
1716/// expression. Internal helper.
1717///
1718/// # 参数 / Parameters
1719///
1720/// - `fields`:结构体的字段定义 / The struct's field definitions
1721/// - `name`:结构体类型的标识符 / The struct type's identifier
1722/// - `ty_generics`:类型的泛型参数(用于构造时的 turbofish 语法)
1723/// / The type's generic parameters (used for turbofish syntax during construction)
1724///
1725/// # 返回值 / Returns
1726///
1727/// 返回 `(构造表达式, 反序列化语句列表)`:
1728/// - 构造表达式:用于创建结构体实例的 `TokenStream`
1729/// - 反序列化语句:每个字段的 `from_bytes()` 调用和偏移量更新
1730///
1731/// Returns `(construction_expression, deserialization_statements)`:
1732/// - Construction expression: A `TokenStream` for creating the struct instance
1733/// - Deserialization statements: `from_bytes()` calls and offset updates for each field
1734///
1735/// # 泛型构造 / Generic Construction
1736///
1737/// 使用 `as_turbofish()` 生成正确的泛型语法。例如 `MyStruct::<T>` 而非
1738/// `MyStruct <T>`(后者会被解析为比较操作)。
1739///
1740/// Uses `as_turbofish()` to generate correct generic syntax. For example,
1741/// `MyStruct::<T>` instead of `MyStruct <T>` (which would be parsed as a
1742/// comparison operation).
1743fn generate_deserialize_fields(
1744 fields: &Fields,
1745 name: &syn::Ident,
1746 ty_generics: &syn::TypeGenerics,
1747) -> (proc_macro2::TokenStream, Vec<proc_macro2::TokenStream>) {
1748 // 在表达式上下文中使用 turbofish 语法:Name::<T>
1749 // In expression context, use turbofish syntax: Name::<T>
1750 let ty_params = ty_generics.as_turbofish();
1751 match fields {
1752 Fields::Named(named) => {
1753 let mut desers = Vec::new();
1754 let mut field_names = Vec::new();
1755 for f in &named.named {
1756 let fname = f.ident.as_ref().unwrap();
1757 let ftype = &f.ty;
1758 field_names.push(fname.clone());
1759
1760 let validates = parse_validations(fname, ftype, &f.attrs);
1761 let (skip, default) = has_skip_attr(&f.attrs);
1762 if skip {
1763 if let Some(default) = default {
1764 match syn::parse_str::<syn::Ident>(&default) {
1765 Ok(ident) => {
1766 desers.push(quote! {
1767 let #fname: #ftype = #ident();
1768 });
1769 }
1770 Err(_) => {
1771 desers.push(quote! {
1772 compile_error!(concat!("invalid function name in skip: ", #default));
1773 });
1774 }
1775 }
1776 } else {
1777 desers.push(quote! {
1778 let #fname: #ftype = #ftype::default();
1779 });
1780 }
1781 } else {
1782 desers.push(quote! {
1783 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1784 let #fname: #ftype = __val;
1785 #(#validates)*
1786 offset += __new_offset;
1787 });
1788 }
1789 }
1790 let construct = quote! {
1791 #name #ty_params { #(#field_names),* }
1792 };
1793 (construct, desers)
1794 }
1795 Fields::Unnamed(unnamed) => {
1796 let mut desers = Vec::new();
1797 let mut field_names = Vec::new();
1798 for (i, f) in unnamed.unnamed.iter().enumerate() {
1799 let fname = syn::Ident::new(&format!("__f{}", i), name.span());
1800 let ftype = &f.ty;
1801 let (skip, default_fn) = has_skip_attr(&f.attrs);
1802 if skip {
1803 if let Some(func_name) = default_fn {
1804 match syn::parse_str::<syn::Ident>(&func_name) {
1805 Ok(ident) => {
1806 desers.push(quote! {
1807 let #fname: #ftype = #ident();
1808 });
1809 }
1810 Err(_) => {
1811 desers.push(quote! {
1812 compile_error!(concat!("invalid function name in skip: ", #func_name));
1813 });
1814 }
1815 }
1816 } else {
1817 desers.push(quote! {
1818 let #fname: #ftype = <#ftype as ::std::default::Default>::default();
1819 });
1820 }
1821 } else {
1822 let validates = parse_validations(&fname, ftype, &f.attrs);
1823 desers.push(quote! {
1824 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1825 let #fname: #ftype = __val;
1826 #(#validates)*
1827 offset += __new_offset;
1828 });
1829 }
1830 field_names.push(fname);
1831 }
1832 let construct = quote! {
1833 #name #ty_params ( #(#field_names),* )
1834 };
1835 (construct, desers)
1836 }
1837 Fields::Unit => {
1838 let construct = quote! { #name #ty_params };
1839 (construct, vec![])
1840 }
1841 }
1842}
1843
1844/// 为结构体的字段生成带 marker 的反序列化代码以及构造表达式。内部辅助函数。
1845///
1846/// Generates marker-aware deserialization code for struct fields along with the
1847/// construction expression. Internal helper.
1848///
1849/// marker 匹配的 `skip_with` 字段使用默认值或自定义函数填充,不从字节流读取。
1850///
1851/// `skip_with` fields whose marker matches are filled with default values or custom
1852/// functions, without reading from the byte stream.
1853fn generate_deserialize_fields_with(
1854 fields: &Fields,
1855 name: &syn::Ident,
1856 ty_generics: &syn::TypeGenerics,
1857 marker: &str,
1858) -> (proc_macro2::TokenStream, Vec<proc_macro2::TokenStream>) {
1859 let ty_params = ty_generics.as_turbofish();
1860 // marker 参数是生成代码中的参数名(如 "__afast_marker__"),不是实际值
1861 // The marker parameter is the parameter name in generated code, not the actual value
1862 let marker_ident = syn::Ident::new(marker, proc_macro2::Span::call_site());
1863 match fields {
1864 Fields::Named(named) => {
1865 let mut desers = Vec::new();
1866 let mut field_names = Vec::new();
1867 for f in &named.named {
1868 let fname = f.ident.as_ref().unwrap();
1869 let ftype = &f.ty;
1870 field_names.push(fname.clone());
1871
1872 let (skip, _) = has_skip_attr(&f.attrs);
1873 if skip {
1874 desers.push(quote! {
1875 let #fname: #ftype = <#ftype as ::std::default::Default>::default();
1876 });
1877 } else {
1878 let skip_with = has_skip_with_attr(&f.attrs);
1879 if let Some((m, default_fn)) = skip_with {
1880 let default_expr = if let Some(fn_name) = default_fn {
1881 match syn::parse_str::<syn::Ident>(&fn_name) {
1882 Ok(ident) => quote! { #ident() },
1883 Err(_) => {
1884 quote! { { compile_error!(concat!("invalid function name in skip_with: ", #fn_name)); <#ftype as ::std::default::Default>::default() } }
1885 }
1886 }
1887 } else {
1888 quote! { <#ftype as ::std::default::Default>::default() }
1889 };
1890 let validates = parse_validations(fname, ftype, &f.attrs);
1891 desers.push(quote! {
1892 let #fname: #ftype = if #marker_ident == #m {
1893 #default_expr
1894 } else {
1895 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1896 #(#validates)*
1897 offset += __new_offset;
1898 __val
1899 };
1900 });
1901 } else {
1902 let validates = parse_validations(fname, ftype, &f.attrs);
1903 desers.push(quote! {
1904 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1905 let #fname: #ftype = __val;
1906 #(#validates)*
1907 offset += __new_offset;
1908 });
1909 }
1910 }
1911 }
1912 let construct = quote! {
1913 #name #ty_params { #(#field_names),* }
1914 };
1915 (construct, desers)
1916 }
1917 Fields::Unnamed(unnamed) => {
1918 let mut desers = Vec::new();
1919 let mut field_names = Vec::new();
1920 for (i, f) in unnamed.unnamed.iter().enumerate() {
1921 let fname = syn::Ident::new(&format!("__f{}", i), name.span());
1922 let ftype = &f.ty;
1923 field_names.push(fname.clone());
1924
1925 let (skip, _) = has_skip_attr(&f.attrs);
1926 if skip {
1927 desers.push(quote! {
1928 let #fname: #ftype = <#ftype as ::std::default::Default>::default();
1929 });
1930 } else {
1931 let skip_with = has_skip_with_attr(&f.attrs);
1932 if let Some((m, default_fn)) = skip_with {
1933 let default_expr = if let Some(fn_name) = default_fn {
1934 match syn::parse_str::<syn::Ident>(&fn_name) {
1935 Ok(ident) => quote! { #ident() },
1936 Err(_) => {
1937 quote! { { compile_error!(concat!("invalid function name in skip_with: ", #fn_name)); <#ftype as ::std::default::Default>::default() } }
1938 }
1939 }
1940 } else {
1941 quote! { <#ftype as ::std::default::Default>::default() }
1942 };
1943 let validates = parse_validations(&fname, ftype, &f.attrs);
1944 desers.push(quote! {
1945 let #fname: #ftype = if #marker_ident == #m {
1946 #default_expr
1947 } else {
1948 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1949 #(#validates)*
1950 offset += __new_offset;
1951 __val
1952 };
1953 });
1954 } else {
1955 let validates = parse_validations(&fname, ftype, &f.attrs);
1956 desers.push(quote! {
1957 let (__val, __new_offset) = ::afastdata::AFastDeserialize::from_bytes(&data[offset..])?;
1958 let #fname: #ftype = __val;
1959 #(#validates)*
1960 offset += __new_offset;
1961 });
1962 }
1963 }
1964 }
1965 let construct = quote! {
1966 #name #ty_params ( #(#field_names),* )
1967 };
1968 (construct, desers)
1969 }
1970 Fields::Unit => {
1971 let construct = quote! { #name #ty_params };
1972 (construct, vec![])
1973 }
1974 }
1975}