sortFields sorts fields according to Fory protocol specification This matches the new field ordering specification for cross-language compatibility
(fields []*FieldInfo)
| 363 | // sortFields sorts fields according to Fory protocol specification |
| 364 | // This matches the new field ordering specification for cross-language compatibility |
| 365 | func sortFields(fields []*FieldInfo) { |
| 366 | sort.Slice(fields, func(i, j int) bool { |
| 367 | f1, f2 := fields[i], fields[j] |
| 368 | |
| 369 | // Categorize fields into groups |
| 370 | group1 := getFieldGroup(f1) |
| 371 | group2 := getFieldGroup(f2) |
| 372 | |
| 373 | // Sort by group first |
| 374 | if group1 != group2 { |
| 375 | return group1 < group2 |
| 376 | } |
| 377 | |
| 378 | // Within same group, apply group-specific sorting |
| 379 | switch group1 { |
| 380 | case groupPrimitive, groupNullablePrimitive: |
| 381 | // Primitive fields: larger size first, smaller later, variable size last |
| 382 | // When same size, sort by type id |
| 383 | // When same size and type id, sort by snake case field name |
| 384 | |
| 385 | // Handle compression types (INT32/INT64/VARINT32/VARINT64 and unsigned variants) |
| 386 | compressI := f1.TypeID == "INT32" || f1.TypeID == "INT64" || |
| 387 | f1.TypeID == "VARINT32" || f1.TypeID == "VARINT64" || |
| 388 | f1.TypeID == "UINT32" || f1.TypeID == "UINT64" || |
| 389 | f1.TypeID == "VAR_UINT32" || f1.TypeID == "VAR_UINT64" |
| 390 | compressJ := f2.TypeID == "INT32" || f2.TypeID == "INT64" || |
| 391 | f2.TypeID == "VARINT32" || f2.TypeID == "VARINT64" || |
| 392 | f2.TypeID == "UINT32" || f2.TypeID == "UINT64" || |
| 393 | f2.TypeID == "VAR_UINT32" || f2.TypeID == "VAR_UINT64" |
| 394 | |
| 395 | if compressI != compressJ { |
| 396 | return !compressI && compressJ // non-compress comes first |
| 397 | } |
| 398 | |
| 399 | // Sort by size (descending) |
| 400 | if f1.PrimitiveSize != f2.PrimitiveSize { |
| 401 | return f1.PrimitiveSize > f2.PrimitiveSize |
| 402 | } |
| 403 | |
| 404 | // Sort by type ID |
| 405 | if f1.TypeID != f2.TypeID { |
| 406 | return getTypeIDValue(f1.TypeID) < getTypeIDValue(f2.TypeID) |
| 407 | } |
| 408 | |
| 409 | // Finally by field identifier |
| 410 | return lessFieldInfoIdentifier(f1, f2) |
| 411 | |
| 412 | case groupNonPrimitive: |
| 413 | return lessFieldInfoIdentifier(f1, f2) |
| 414 | |
| 415 | default: |
| 416 | return lessFieldInfoIdentifier(f1, f2) |
| 417 | } |
| 418 | }) |
| 419 | } |
| 420 | |
| 421 | // Field group constants for sorting. |
| 422 | // This matches reflection's field ordering in field_info.go: |