Skip to content

Commit d7602fe

Browse files
committed
Dynamic struct
1 parent 83117d4 commit d7602fe

4 files changed

Lines changed: 212 additions & 259 deletions

File tree

secretary/utils/binstruct/binary_struct.go

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"fmt"
1212
"math"
1313
"reflect"
14+
"sort"
1415
)
1516

1617
// Serialize struct to binary []byte (Little-Endian)
@@ -27,16 +28,16 @@ func Serialize(s interface{}) ([]byte, error) {
2728
buf := new(bytes.Buffer)
2829
typ := reflect.TypeOf(s)
2930

30-
for i := 0; i < typ.NumField(); i++ {
31+
sortedFields := getSortedFields(typ)
32+
for _, field := range sortedFields {
3133

32-
field := typ.Field(i)
3334
tag := field.Tag.Get("bin")
3435

3536
// Skip fields without bin tag
3637
if tag == "" {
3738
continue
3839
}
39-
fieldValue, numBytes, maxStorableSize, maxSize, array_elem_len := extractFieldParameters(val, i, field)
40+
fieldValue, numBytes, maxStorableSize, maxSize, array_elem_len := extractFieldParameters(val, field)
4041

4142
// Handle fields based on their types
4243
switch fieldValue.Kind() {
@@ -203,14 +204,14 @@ func Deserialize(data []byte, s interface{}) error {
203204
val = val.Elem()
204205
typ := val.Type()
205206

206-
for i := 0; i < typ.NumField(); i++ {
207+
sortedFields := getSortedFields(typ)
208+
for _, field := range sortedFields {
207209

208-
field := typ.Field(i)
209210
tag := field.Tag.Get("bin")
210211
if tag == "" {
211212
continue
212213
}
213-
fieldValue, numBytes, _, _, array_elem_len := extractFieldParameters(val, i, field)
214+
fieldValue, numBytes, _, _, array_elem_len := extractFieldParameters(val, field)
214215

215216
// Handle fields based on their types
216217
switch fieldValue.Kind() {
@@ -400,9 +401,12 @@ func Compare(a, b interface{}) (bool, error) {
400401
valB := reflect.ValueOf(b)
401402
typ := reflect.TypeOf(a)
402403

403-
for i := 0; i < typ.NumField(); i++ {
404+
sortedFields := getSortedFields(typ)
405+
for i := range sortedFields {
406+
404407
fieldA := valA.Field(i)
405408
fieldB := valB.Field(i)
409+
406410
tag := typ.Field(i).Tag.Get("bin")
407411

408412
// Skip fields without bin tag
@@ -493,8 +497,9 @@ func MarshalJSON(s interface{}) ([]byte, error) {
493497
typ := val.Type()
494498
jsonMap := make(map[string]interface{})
495499

496-
for i := 0; i < typ.NumField(); i++ {
497-
field := typ.Field(i)
500+
sortedFields := getSortedFields(typ)
501+
for i, field := range sortedFields {
502+
498503
tag := field.Tag.Get("bin")
499504
if tag == "" || tag == "-" {
500505
continue
@@ -563,20 +568,20 @@ func getByteFromField(field reflect.StructField) int {
563568
return byte
564569
}
565570

566-
func extractFieldParameters(val reflect.Value, i int, field reflect.StructField) (reflect.Value, int, int, int, int) {
567-
fieldValue := val.Field(i)
571+
func extractFieldParameters(val reflect.Value, field reflect.StructField) (reflect.Value, int, int, int, int) {
572+
// Get field value using FieldByIndex
573+
fieldValue := val.FieldByIndex(field.Index)
574+
568575
numBytes := getByteFromField(field)
569576
maxSize := 1<<(numBytes*8) - 1
570577
size := getSizeFromField(field)
571578
if size == 0 {
572579
size = maxSize
573580
}
574581

575-
array_elem_len := getArrayElemLenFromField(field)
576-
577-
// fmt.Printf("\nnumBytes:%d maxSize:%d size:%d\n", numBytes, maxSize, size)
582+
arrayElemLen := getArrayElemLenFromField(field)
578583

579-
return fieldValue, numBytes, maxSize, size, array_elem_len
584+
return fieldValue, numBytes, maxSize, size, arrayElemLen
580585
}
581586

582587
func writeByteLen(buf *bytes.Buffer, numByte int, length int) {
@@ -629,6 +634,24 @@ func reflectKindByteLen(elemBaseKind reflect.Kind) int {
629634
}
630635
}
631636

637+
func getSortedFields(typ reflect.Type) []reflect.StructField {
638+
numFields := typ.NumField()
639+
fields := make([]reflect.StructField, numFields)
640+
641+
for i := 0; i < numFields; i++ {
642+
fields[i] = typ.Field(i)
643+
}
644+
645+
// Sort fields by "bin" tag value (convert to int for correct order)
646+
sort.Slice(fields, func(i, j int) bool {
647+
tagI := fields[i].Tag.Get("bin")
648+
tagJ := fields[j].Tag.Get("bin")
649+
return tagI < tagJ
650+
})
651+
652+
return fields
653+
}
654+
632655
func hash(data interface{}) (string, error) {
633656
// Serialize the struct to JSON
634657
serialized, err := MarshalJSON(data)

secretary/utils/binstruct/binary_struct_test.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,16 @@ func TestBinaryStructSerialize(t *testing.T) {
122122

123123
for _, test := range tests {
124124

125-
binaryData, _ := Serialize(test.s)
125+
binaryData, err := Serialize(test.s)
126+
if err != nil {
127+
t.Fatal(err)
128+
}
126129

127130
var d testStruct
128-
Deserialize(binaryData, &d)
129-
t.Logf("\n----------------------------------------\nOriginal: %+v\n\nSerializ: %+v\n\nDeserial: %+v\n", test.s, binaryData, d)
131+
err = Deserialize(binaryData, &d)
132+
if err != nil {
133+
t.Fatal(err)
134+
}
130135

131136
jsonH, err := MarshalJSON(test.s)
132137
if err != nil {
@@ -137,8 +142,14 @@ func TestBinaryStructSerialize(t *testing.T) {
137142
if err != nil {
138143
t.Fatal(err)
139144
}
145+
146+
// utils.Log("binaryData", (binaryData), "s", test.s, "d", d, "jsonH", string(jsonH), "jsonD", string(jsonD))
140147
if test.equal != (bytes.Compare(jsonH, jsonD) == 0) {
141-
t.Fatalf("\n\nCompare Should be equal: %v \n%v:%s \n\n %v:%s\n", test.equal, len(jsonH), string(jsonH), len(jsonD), string(jsonD))
148+
utils.Log("nCompare Should be equal", test.equal,
149+
len(jsonH), string(jsonH),
150+
len(jsonD), string(jsonD),
151+
)
152+
t.Fatal()
142153
}
143154

144155
hashS, _ := hash(test.s)

0 commit comments

Comments
 (0)