Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions rust/fory-derive/src/fory_row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,19 @@
// specific language governing permissions and limitations
// under the License.

use crate::util::sorted_fields;
use crate::util::{extract_fields, source_fields};
use proc_macro::TokenStream;
use quote::quote;

pub fn derive_row(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let fields = match &ast.data {
syn::Data::Struct(s) => sorted_fields(&s.fields),
let source_fields = match &ast.data {
syn::Data::Struct(s) => source_fields(&s.fields),
_ => {
panic!("only struct be supported")
}
};
let fields = extract_fields(&source_fields);

let write_exprs = fields.iter().enumerate().map(|(index, field)| {
let ty = &field.ty;
Expand Down
49 changes: 25 additions & 24 deletions rust/fory-derive/src/object/derive_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::object::misc;
use crate::object::read::gen_read_field;
use crate::object::util::{get_filtered_fields_iter, get_sorted_field_names};
use crate::object::write::gen_write_field;
use crate::util::sorted_fields;
use crate::util::{extract_fields, source_fields};
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::{DataEnum, Fields};
Expand Down Expand Up @@ -119,8 +119,9 @@ pub(crate) fn gen_named_variant_meta_type_impl_with_enum_name(
fields: &syn::FieldsNamed,
) -> TokenStream {
let fields_clone = syn::Fields::Named(fields.clone());
let sorted_fields_slice = sorted_fields(&fields_clone);
let filtered_fields: Vec<_> = get_filtered_fields_iter(&sorted_fields_slice).collect();
let source_fields = source_fields(&fields_clone);
let fields_slice = extract_fields(&source_fields);
let filtered_fields: Vec<_> = get_filtered_fields_iter(&fields_slice).collect();
let sorted_field_names_vec = get_sorted_field_names(&filtered_fields);

// Generate individual field name literals
Expand All @@ -131,7 +132,7 @@ pub(crate) fn gen_named_variant_meta_type_impl_with_enum_name(
})
.collect();

let fields_info_ts = misc::gen_field_fields_info(&sorted_fields_slice);
let fields_info_ts = misc::gen_field_fields_info(&source_fields);

// Include enum name to make meta type unique
let meta_type_ident = Ident::new(
Expand Down Expand Up @@ -239,20 +240,20 @@ fn rust_variant_branches(data_enum: &DataEnum, default_variant_value: u32) -> Ve
}
}
Fields::Named(fields_named) => {
use crate::util::sorted_fields;
use crate::util::source_fields;

let fields_clone = syn::Fields::Named(fields_named.clone());
let sorted_fields = sorted_fields(&fields_clone);
let source_fields = source_fields(&fields_clone);

let field_idents: Vec<_> = sorted_fields
let field_idents: Vec<_> = source_fields
.iter()
.map(|f| f.ident.as_ref().unwrap())
.map(|sf| sf.field.ident.as_ref().unwrap())
.collect();

let write_fields: Vec<_> = sorted_fields
let write_fields: Vec<_> = source_fields
.iter()
.zip(field_idents.iter())
.map(|(f, ident)| gen_write_field(f, ident, false))
.map(|(sf, ident)| gen_write_field(sf.field, ident, false))
.collect();

quote! {
Expand Down Expand Up @@ -322,16 +323,16 @@ fn rust_compatible_variant_write_branches(
proc_macro2::Span::call_site()
);
let fields_clone = syn::Fields::Named(fields_named.clone());
let sorted_fields = sorted_fields(&fields_clone);
let field_idents: Vec<_> = sorted_fields
let source_fields = source_fields(&fields_clone);
let field_idents: Vec<_> = source_fields
.iter()
.map(|f| f.ident.as_ref().unwrap())
.map(|sf| sf.field.ident.as_ref().unwrap())
.collect();

let write_fields: Vec<_> = sorted_fields
let write_fields: Vec<_> = source_fields
.iter()
.zip(field_idents.iter())
.map(|(f, ident)| gen_write_field(f, ident, false))
.map(|(sf, ident)| gen_write_field(sf.field, ident, false))
.collect();

quote! {
Expand Down Expand Up @@ -505,19 +506,19 @@ fn rust_variant_read_branches(
}
Fields::Named(fields_named) => {
let fields_clone = syn::Fields::Named(fields_named.clone());
let sorted_fields = sorted_fields(&fields_clone);
let source_fields = source_fields(&fields_clone);

let field_idents: Vec<_> = sorted_fields
let field_idents: Vec<_> = source_fields
.iter()
.map(|f| f.ident.as_ref().unwrap())
.map(|sf| sf.field.ident.as_ref().unwrap())
.collect();

let read_fields: Vec<_> = sorted_fields
let read_fields: Vec<_> = source_fields
.iter()
.zip(field_idents.iter())
.map(|(f, ident)| {
.map(|(sf, ident)| {
let field_name = ident.to_string();
gen_read_field(f, ident, &field_name)
gen_read_field(sf.field, ident, &field_name)
})
.collect();

Expand Down Expand Up @@ -629,16 +630,16 @@ fn rust_compatible_variant_read_branches(
}
}
Fields::Named(fields_named) => {
use crate::util::sorted_fields;
use crate::util::source_fields;

// Sort fields to match the meta type generation
let fields_clone = syn::Fields::Named(fields_named.clone());
let sorted_fields_slice = sorted_fields(&fields_clone);
let source_fields = source_fields(&fields_clone);

// Generate compatible read logic using gen_read_compatible_with_construction
let compatible_read_body =
crate::object::read::gen_read_compatible_with_construction(
&sorted_fields_slice,
&source_fields,
Some(ident),
);

Expand Down
158 changes: 79 additions & 79 deletions rust/fory-derive/src/object/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ use syn::Field;

use super::field_meta::{classify_field_type, parse_field_meta};
use super::util::{
classify_trait_object_field, generic_tree_to_tokens, get_filtered_fields_iter,
classify_trait_object_field, generic_tree_to_tokens, get_filtered_source_fields_iter,
get_sort_fields_ts, parse_generic_tree, StructField,
};
use crate::util::SourceField;

// Global type ID counter that auto-grows from 0 at macro processing time
static TYPE_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
Expand Down Expand Up @@ -72,95 +73,94 @@ pub fn gen_get_sorted_field_names(fields: &[&Field]) -> TokenStream {
}
}

pub fn gen_field_fields_info(fields: &[&Field]) -> TokenStream {
let field_infos = get_filtered_fields_iter(fields)
.enumerate()
.map(|(idx, field)| {
let ty = &field.ty;
let name = super::util::get_field_name(field, idx);
pub fn gen_field_fields_info(source_fields: &[SourceField<'_>]) -> TokenStream {
let field_infos = get_filtered_source_fields_iter(source_fields).map(|sf| {
let field = sf.field;
let ty = &field.ty;
let name = &sf.field_name;

// Parse field metadata for nullable/ref tracking and field ID
let meta = parse_field_meta(field).unwrap_or_default();
let type_class = classify_field_type(ty);
let nullable = meta.effective_nullable(type_class);
let ref_tracking = meta.effective_ref_tracking(type_class);
// Only use explicit field ID when user sets #[fory(id = N)]
// Otherwise use -1 to indicate field name encoding should be used
let field_id = if meta.uses_tag_id() {
meta.effective_id() as i16
} else {
-1i16 // Use field name encoding when no explicit ID
};
// Parse field metadata for nullable/ref tracking and field ID
let meta = parse_field_meta(field).unwrap_or_default();
let type_class = classify_field_type(ty);
let nullable = meta.effective_nullable(type_class);
let ref_tracking = meta.effective_ref_tracking(type_class);
// Only use explicit field ID when user sets #[fory(id = N)]
// Otherwise use -1 to indicate field name encoding should be used
let field_id = if meta.uses_tag_id() {
meta.effective_id() as i16
} else {
-1i16 // Use field name encoding when no explicit ID
};

match classify_trait_object_field(ty) {
StructField::None => {
let generic_tree = parse_generic_tree(ty);
let generic_token = generic_tree_to_tokens(&generic_tree);
quote! {
fory_core::meta::FieldInfo::new_with_id(
#field_id,
#name,
{
let mut ft = #generic_token;
ft.nullable = #nullable;
ft.ref_tracking = #ref_tracking;
ft
}
)
}
match classify_trait_object_field(ty) {
StructField::None => {
let generic_tree = parse_generic_tree(ty);
let generic_token = generic_tree_to_tokens(&generic_tree);
quote! {
fory_core::meta::FieldInfo::new_with_id(
#field_id,
#name,
{
let mut ft = #generic_token;
ft.nullable = #nullable;
ft.ref_tracking = #ref_tracking;
ft
}
)
}
}
StructField::VecBox(_) | StructField::VecRc(_) | StructField::VecArc(_) => {
quote! {
fory_core::meta::FieldInfo::new_with_id(#field_id, #name, fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::LIST as u32,
nullable: #nullable,
ref_tracking: #ref_tracking,
generics: vec![fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::UNKNOWN as u32,
nullable: false,
ref_tracking: false,
generics: Vec::new()
}]
})
}
StructField::VecBox(_) | StructField::VecRc(_) | StructField::VecArc(_) => {
quote! {
fory_core::meta::FieldInfo::new_with_id(#field_id, #name, fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::LIST as u32,
nullable: #nullable,
ref_tracking: #ref_tracking,
generics: vec![fory_core::meta::FieldType {
}
StructField::HashMapBox(key_ty, _)
| StructField::HashMapRc(key_ty, _)
| StructField::HashMapArc(key_ty, _) => {
let key_generic_tree = parse_generic_tree(key_ty.as_ref());
let key_generic_token = generic_tree_to_tokens(&key_generic_tree);
quote! {
fory_core::meta::FieldInfo::new_with_id(#field_id, #name, fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::MAP as u32,
nullable: #nullable,
ref_tracking: #ref_tracking,
generics: vec![
#key_generic_token,
fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::UNKNOWN as u32,
nullable: false,
ref_tracking: false,
generics: Vec::new()
}]
})
}
}
StructField::HashMapBox(key_ty, _)
| StructField::HashMapRc(key_ty, _)
| StructField::HashMapArc(key_ty, _) => {
let key_generic_tree = parse_generic_tree(key_ty.as_ref());
let key_generic_token = generic_tree_to_tokens(&key_generic_tree);
quote! {
fory_core::meta::FieldInfo::new_with_id(#field_id, #name, fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::MAP as u32,
nullable: #nullable,
ref_tracking: #ref_tracking,
generics: vec![
#key_generic_token,
fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::UNKNOWN as u32,
nullable: false,
ref_tracking: false,
generics: Vec::new()
}
]
})
}
}
]
})
}
_ => {
quote! {
fory_core::meta::FieldInfo::new_with_id(#field_id, #name, fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::UNKNOWN as u32,
nullable: #nullable,
ref_tracking: #ref_tracking,
generics: Vec::new()
})
}
}
_ => {
quote! {
fory_core::meta::FieldInfo::new_with_id(#field_id, #name, fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::UNKNOWN as u32,
nullable: #nullable,
ref_tracking: #ref_tracking,
generics: Vec::new()
})
}
}
});
}
});

// Get sorted field names for sorting
let static_field_names = get_sort_fields_ts(fields);
let fields: Vec<&Field> = source_fields.iter().map(|sf| sf.field).collect();
let static_field_names = get_sort_fields_ts(&fields);

quote! {
let mut field_infos: Vec<fory_core::meta::FieldInfo> = vec![#(#field_infos),*];
Expand Down
Loading
Loading