Skip to content

Commit 4b225ba

Browse files
committed
refactor go struct serializer
1 parent 4d16d37 commit 4b225ba

File tree

20 files changed

+3514
-3868
lines changed

20 files changed

+3514
-3868
lines changed

go/fory/codegen/utils.go

Lines changed: 80 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type FieldInfo struct {
3333
Index int // Original field index in struct
3434
IsPrimitive bool // Whether it's a Fory primitive type
3535
IsPointer bool // Whether it's a pointer type
36+
Nullable bool // Whether the field can be null (pointer types)
3637
TypeID string // Fory TypeID for sorting
3738
PrimitiveSize int // Size for primitive type sorting
3839
}
@@ -138,8 +139,33 @@ func getTypeID(t types.Type) string {
138139
t = ptr.Elem()
139140
}
140141

141-
// Check slice types
142-
if _, ok := t.(*types.Slice); ok {
142+
// Check slice types - distinguish primitive arrays from generic lists
143+
if slice, ok := t.(*types.Slice); ok {
144+
elemType := slice.Elem()
145+
// For pointer to primitive, unwrap the pointer
146+
if ptr, ok := elemType.(*types.Pointer); ok {
147+
elemType = ptr.Elem()
148+
}
149+
// Check if element is a primitive type (primitive arrays use specific typeIDs)
150+
if basic, ok := elemType.Underlying().(*types.Basic); ok {
151+
switch basic.Kind() {
152+
case types.Bool:
153+
return "BOOL_ARRAY"
154+
case types.Int8:
155+
return "INT8_ARRAY"
156+
case types.Int16:
157+
return "INT16_ARRAY"
158+
case types.Int32:
159+
return "INT32_ARRAY"
160+
case types.Int, types.Int64:
161+
return "INT64_ARRAY"
162+
case types.Float32:
163+
return "FLOAT32_ARRAY"
164+
case types.Float64:
165+
return "FLOAT64_ARRAY"
166+
}
167+
}
168+
// Non-primitive slices use LIST
143169
return "LIST"
144170
}
145171

@@ -263,17 +289,36 @@ func getTypeIDValue(typeID string) int {
263289
case "FLOAT64":
264290
return int(fory.FLOAT64)
265291
case "STRING":
266-
return int(fory.STRING) // 12
292+
return int(fory.STRING) // 9
293+
case "BINARY":
294+
return int(fory.BINARY) // 10
295+
case "LIST":
296+
return int(fory.LIST) // 20
297+
case "SET":
298+
return int(fory.SET) // 21
299+
case "MAP":
300+
return int(fory.MAP) // 22
267301
case "TIMESTAMP":
268302
return int(fory.TIMESTAMP) // 25
269303
case "LOCAL_DATE":
270304
return int(fory.LOCAL_DATE) // 26
271305
case "NAMED_STRUCT":
272306
return int(fory.NAMED_STRUCT) // 17
273-
case "LIST":
274-
return int(fory.LIST) // 21
275-
case "MAP":
276-
return int(fory.MAP) // 23
307+
// Primitive array types
308+
case "BOOL_ARRAY":
309+
return int(fory.BOOL_ARRAY) // 39
310+
case "INT8_ARRAY":
311+
return int(fory.INT8_ARRAY) // 40
312+
case "INT16_ARRAY":
313+
return int(fory.INT16_ARRAY) // 41
314+
case "INT32_ARRAY":
315+
return int(fory.INT32_ARRAY) // 42
316+
case "INT64_ARRAY":
317+
return int(fory.INT64_ARRAY) // 43
318+
case "FLOAT32_ARRAY":
319+
return int(fory.FLOAT32_ARRAY) // 49
320+
case "FLOAT64_ARRAY":
321+
return int(fory.FLOAT64_ARRAY) // 50
277322
default:
278323
return 999 // Unknown types sort last
279324
}
@@ -329,14 +374,15 @@ func sortFields(fields []*FieldInfo) {
329374
return f1.SnakeName < f2.SnakeName
330375

331376
case groupOtherInternalType:
332-
// Other internal type fields: sort by type id then snake case field name
377+
// Internal type fields (STRING, BINARY, LIST, SET, MAP): sort by type id then name only.
378+
// Java does NOT sort by nullable flag for these types.
333379
if f1.TypeID != f2.TypeID {
334380
return getTypeIDValue(f1.TypeID) < getTypeIDValue(f2.TypeID)
335381
}
336382
return f1.SnakeName < f2.SnakeName
337383

338-
case groupList, groupSet, groupMap, groupOther:
339-
// List/Set/Map/Other fields: sort by snake case field name only
384+
case groupPrimitiveArray, groupOther:
385+
// Primitive arrays and other fields: sort by snake case field name only
340386
return f1.SnakeName < f2.SnakeName
341387

342388
default:
@@ -347,13 +393,13 @@ func sortFields(fields []*FieldInfo) {
347393
}
348394

349395
// Field group constants for sorting
396+
// This matches reflection's field ordering in field_info.go:
397+
// primitives → boxed → otherInternalType (STRING/BINARY/LIST/SET/MAP) → primitiveArray → other
350398
const (
351399
groupPrimitive = 0 // primitive and nullable primitive fields
352-
groupOtherInternalType = 1 // other internal type fields (string, timestamp, etc.)
353-
groupList = 2 // list fields
354-
groupSet = 3 // set fields
355-
groupMap = 4 // map fields
356-
groupOther = 5 // other fields
400+
groupOtherInternalType = 1 // STRING, BINARY, LIST, SET, MAP (sorted by typeId, name)
401+
groupPrimitiveArray = 2 // primitive arrays (BOOL_ARRAY, INT32_ARRAY, etc.) - sorted by name
402+
groupOther = 3 // structs, enums, and unknown types - sorted by name
357403
)
358404

359405
// getFieldGroup categorizes a field into its sorting group
@@ -366,38 +412,29 @@ func getFieldGroup(field *FieldInfo) int {
366412
return groupPrimitive
367413
}
368414

369-
// List fields
370-
if typeID == "LIST" {
371-
return groupList
372-
}
373-
374-
// Set fields
375-
if typeID == "SET" {
376-
return groupSet
415+
// Primitive array fields - sorted by name only
416+
primitiveArrayTypes := map[string]bool{
417+
"BOOL_ARRAY": true,
418+
"INT8_ARRAY": true,
419+
"INT16_ARRAY": true,
420+
"INT32_ARRAY": true,
421+
"INT64_ARRAY": true,
422+
"FLOAT32_ARRAY": true,
423+
"FLOAT64_ARRAY": true,
377424
}
378-
379-
// Map fields
380-
if typeID == "MAP" {
381-
return groupMap
425+
if primitiveArrayTypes[typeID] {
426+
return groupPrimitiveArray
382427
}
383428

384-
// Other internal type fields
385-
// These are fory internal types that are not primitives/lists/sets/maps
386-
// Examples: STRING, TIMESTAMP, LOCAL_DATE, NAMED_STRUCT, etc.
429+
// Internal types (STRING, BINARY, LIST, SET, MAP) - sorted by typeId, nullable, name
430+
// These match reflection's category 1 in getFieldCategory
387431
internalTypes := map[string]bool{
388-
"STRING": true,
389-
"TIMESTAMP": true,
390-
"LOCAL_DATE": true,
391-
"NAMED_STRUCT": true,
392-
"STRUCT": true,
393-
"BINARY": true,
394-
"ENUM": true,
395-
"NAMED_ENUM": true,
396-
"EXT": true,
397-
"NAMED_EXT": true,
398-
"INTERFACE": true, // for interface{} types
432+
"STRING": true,
433+
"BINARY": true,
434+
"LIST": true,
435+
"SET": true,
436+
"MAP": true,
399437
}
400-
401438
if internalTypes[typeID] {
402439
return groupOtherInternalType
403440
}
@@ -448,6 +485,7 @@ func analyzeField(field *types.Var, index int) (*FieldInfo, error) {
448485
Index: index,
449486
IsPrimitive: isPrimitive,
450487
IsPointer: isPointer,
488+
Nullable: isPointer, // Pointer types are nullable, slices/maps are non-nullable in xlang mode
451489
TypeID: typeID,
452490
PrimitiveSize: primitiveSize,
453491
}, nil

0 commit comments

Comments
 (0)