ariesdevil commented on code in PR #3092:
URL: https://github.com/apache/fory/pull/3092#discussion_r2647134725
##########
rust/fory-derive/src/util.rs:
##########
@@ -17,38 +17,73 @@
use syn::{Field, Fields, GenericArgument, PathArguments, Type, TypePath,
TypeTraitObject};
-pub fn sorted_fields(fields: &Fields) -> Vec<&Field> {
- let fields = fields.iter().collect::<Vec<&Field>>();
+/// Sorted field with its original index preserved.
+///
+/// For tuple structs, `original_index` is the field's position in the original
+/// struct definition (0, 1, 2, ...), which is used as the field name.
+#[derive(Clone, Copy)]
+pub struct SortedField<'a> {
+ pub original_index: usize,
+ pub field: &'a Field,
+}
+
+/// Returns sorted fields along with their original indices.
+///
+/// For both named structs and tuple structs, fields are sorted by type for
+/// optimal serialization. The original index is preserved so that:
+/// - For named structs: field names can be used directly
+/// - For tuple structs: the original index (0, 1, 2, ...) is used as field
name
+pub fn sorted_fields(fields: &Fields) -> Vec<SortedField<'_>> {
+ let fields: Vec<&Field> = fields.iter().collect();
get_sorted_fields(&fields)
}
-pub fn get_sorted_fields<'a>(fields: &[&'a Field]) -> Vec<&'a Field> {
- use crate::object::util::{get_sorted_field_names, is_tuple_struct};
+/// Returns sorted fields with their original indices preserved.
+pub fn get_sorted_fields<'a>(fields: &[&'a Field]) -> Vec<SortedField<'a>> {
+ use crate::object::util::get_sorted_field_names;
- // For tuple structs, we must preserve the original field order
- // because fields are accessed by index (self.0, self.1, etc.)
- // Sorting would cause type mismatches during
serialization/deserialization.
- if is_tuple_struct(fields) {
- return fields.to_vec();
- }
-
- // For named structs, sort fields by type for optimal memory layout
+ let is_tuple = !fields.is_empty() && fields[0].ident.is_none();
let sorted_names = get_sorted_field_names(fields);
let mut sorted_fields = Vec::with_capacity(fields.len());
for name in &sorted_names {
- // For named structs, field.ident is Some
- if let Some(field) = fields
- .iter()
- .find(|f| f.ident.as_ref().map(|ident| ident ==
name).unwrap_or(false))
- {
- sorted_fields.push(*field);
+ if is_tuple {
+ // For tuple structs, field name is the original index as string
+ if let Ok(idx) = name.parse::<usize>() {
+ if idx < fields.len() {
+ sorted_fields.push(SortedField {
+ original_index: idx,
+ field: fields[idx],
+ });
+ }
+ }
+ } else {
+ // For named structs, match by field identifier
+ for (idx, field) in fields.iter().enumerate() {
+ if field
+ .ident
+ .as_ref()
+ .map(|ident| ident == name)
+ .unwrap_or(false)
+ {
+ sorted_fields.push(SortedField {
+ original_index: idx,
+ field,
+ });
+ break;
+ }
+ }
}
}
sorted_fields
}
+/// Extract just the fields from sorted fields.
+pub fn fields_only<'a>(sorted: &[SortedField<'a>]) -> Vec<&'a Field> {
Review Comment:
Sure
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]