Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
14 changes: 2 additions & 12 deletions go/fory/fory.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,22 +370,13 @@ func (f *Fory) writeValue(buffer *ByteBuffer, value reflect.Value, serializer Se
value = value.Elem()
}

// For array types, pre-convert the value
// so the corresponding slice serializer can be reused
if value.Kind() == reflect.Array {
length := value.Len()
sliceType := reflect.SliceOf(value.Type().Elem())
slice := reflect.MakeSlice(sliceType, length, length)
reflect.Copy(slice, value)
value = slice
}

if serializer != nil {
return serializer.Write(f, buffer, value)
}

// Get type information for the value
typeInfo, err := f.typeResolver.getTypeInfo(value, true)

if err != nil {
return fmt.Errorf("cannot get typeinfo for value %v: %v", value, err)
}
Expand Down Expand Up @@ -537,12 +528,11 @@ func (f *Fory) readReferencableBySerializer(buf *ByteBuffer, value reflect.Value

func (f *Fory) readData(buffer *ByteBuffer, value reflect.Value, serializer Serializer) (err error) {
if serializer == nil {
typeInfo, err := f.typeResolver.readTypeInfo(buffer, value)
typeInfo, err := f.typeResolver.readTypeInfo(buffer)
if err != nil {
return fmt.Errorf("read typeinfo failed: %w", err)
}
serializer = typeInfo.Serializer

var concrete reflect.Value
var type_ reflect.Type
/*
Expand Down
41 changes: 2 additions & 39 deletions go/fory/fory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func commonSlice() []interface{} {
return []interface{}{
(&[100]bool{})[:],
(&[100]byte{})[:],
// (&[100]int8{})[:],
(&[100]int8{})[:],
(&[100]int16{})[:],
(&[100]int32{})[:],
(&[100]int64{})[:],
Expand Down Expand Up @@ -102,20 +102,6 @@ func commonMap() []interface{} {
}
}

func commonArray() []interface{} {
return []interface{}{
[100]bool{false, true, true},
[100]byte{1, 2, 3},
// [100]int8{1, 2, 3},
[100]int16{1, 2, 3},
[100]int32{1, 2, 3},
[100]int64{1, 2, 3},
[100]float32{1, 2, 3},
[100]float64{1, 2, 3},
[100]string{"str1", "str1"},
}
}

func TestSerializePrimitives(t *testing.T) {
for _, referenceTracking := range []bool{false, true} {
fory := NewFory(referenceTracking)
Expand Down Expand Up @@ -162,7 +148,7 @@ func TestSerializeSlice(t *testing.T) {
for _, referenceTracking := range []bool{false, true} {
fory := NewFory(referenceTracking)
serde(t, fory, []byte{0, 1, MaxUint8})
// serde(t, fory, []int8{MinInt8, -1, 0, 1, MaxInt8})
serde(t, fory, []int8{MinInt8, -1, 0, 1, MaxInt8})
serde(t, fory, []int16{MinInt16, -1, 0, 1, MaxInt16})
serde(t, fory, []int32{MinInt32, -1, 0, 1, MaxInt32})
serde(t, fory, []int64{MinInt64, -1, 0, 1, MaxInt64})
Expand Down Expand Up @@ -206,16 +192,6 @@ func TestSerializeMap(t *testing.T) {
}
}

func TestSerializeArray(t *testing.T) {
for _, referenceTracking := range []bool{false, true} {
fory := NewFory(referenceTracking)
for _, data := range commonArray() {
serde(t, fory, data)
}
serde(t, fory, commonArray())
}
}

func TestSerializeStructSimple(t *testing.T) {
for _, referenceTracking := range []bool{false, true} {
fory := NewFory(referenceTracking)
Expand Down Expand Up @@ -583,19 +559,6 @@ func TestMapEachIndividually(t *testing.T) {
}
}

func TestArrayEachIndividually(t *testing.T) {
fory := NewFory(true)
for _, srcAny := range commonArray() {
srcType := reflect.TypeOf(srcAny)
endPtr := reflect.New(srcType)
data, _ := fory.Marshal(srcAny)
_ = fory.Unmarshal(data, endPtr.Interface())
endVal := endPtr.Elem()
endAny := endVal.Interface()
require.Equal(t, srcAny, endAny)
}
}

func TestSliceEachIndividually(t *testing.T) {
fory := NewFory(true)
for _, srcAny := range commonSlice() {
Expand Down
36 changes: 9 additions & 27 deletions go/fory/fory_xlang_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,49 +112,32 @@ func TestXLangSerializer(t *testing.T) {
set.Add(list...)
require.Nil(t, fory_.Serialize(buffer, set, nil))

// test primitive arrays
require.Nil(t, fory_.Serialize(buffer, []bool{true, false}, nil))
require.Nil(t, fory_.Serialize(buffer, []int16{1, fory.MaxInt16}, nil))
require.Nil(t, fory_.Serialize(buffer, []int32{1, fory.MaxInt32}, nil))
require.Nil(t, fory_.Serialize(buffer, []int64{1, fory.MaxInt64}, nil))
require.Nil(t, fory_.Serialize(buffer, []float32{1.0, 2.0}, nil))
require.Nil(t, fory_.Serialize(buffer, []float64{1.0, 2.0}, nil))

check := func(buf *fory.ByteBuffer) {
values := []interface{}{
true, false, int64(-1), int8(fory.MaxInt8), int8(fory.MinInt8), int16(fory.MaxInt16), int16(fory.MinInt16),
int32(fory.MaxInt32), int32(fory.MinInt32), int64(fory.MaxInt64), int64(fory.MinInt64), float32(-1),
float64(-1), "str", day, instant, list, dict, set,
[]bool{true, false}, []int16{1, fory.MaxInt16}, []int32{1, fory.MaxInt32},
[]int64{1, fory.MaxInt64}, []float32{1.0, 2.0}, []float64{1.0, 2.0},
}
for index, value := range values {
var newValue interface{}
require.Nil(t, fory_.Deserialize(buf, &newValue, nil))
switch reflect.ValueOf(value).Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
require.Equal(t, reflect.ValueOf(value).Int(),
reflect.ValueOf(newValue).Int(), fmt.Sprintf("index %d", index))
case reflect.Float32, reflect.Float64:
require.Equal(t, reflect.ValueOf(value).Float(),
reflect.ValueOf(newValue).Float(), fmt.Sprintf("index %d", index))
default:
require.Equal(t, value, newValue, fmt.Sprintf("index %d", index))
}
typ := reflect.TypeOf(value)
holder := reflect.New(typ)
require.Nil(t, fory_.Deserialize(buf, holder.Interface(), nil))
got := holder.Elem().Interface()
require.Equal(t, value, got, fmt.Sprintf("index %d", index))
}
}
check(buffer)

require.Nil(t, ioutil.WriteFile("test_cross_language_serializer.data",
require.Nil(t, ioutil.WriteFile("test_cross_language_serializer_go.data",
buffer.GetByteSlice(0, buffer.WriterIndex()), 0644))
defer func(name string) {
err := os.Remove(name)
require.Nil(t, err)
}("test_cross_language_serializer.data")
}("test_cross_language_serializer_go.data")
require.True(t, executeCommand([]string{"python", "-m", pythonModule,
"test_cross_language_serializer", "test_cross_language_serializer.data"}))
"test_cross_language_serializer_go", "test_cross_language_serializer_go.data"}))

data, err := ioutil.ReadFile("test_cross_language_serializer.data")
data, err := ioutil.ReadFile("test_cross_language_serializer_go.data")
require.Nil(t, err)
buffer = fory.NewByteBuffer(data)
check(buffer)
Expand Down Expand Up @@ -260,7 +243,6 @@ func TestSerializeComplexStruct(t *testing.T) {
obj.F10 = 1 / 3.0
obj.F11 = [2]int16{1, 2}
obj.F12 = []int16{-1, 4}

structRoundBack(t, fory_, obj, "test_serialize_complex_struct")
}

Expand Down
4 changes: 2 additions & 2 deletions go/fory/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,15 +397,15 @@ func (s mapSerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value
valDeclType := (chunkHeader & VALUE_DECL_TYPE) != 0
chunkSize := int(buf.ReadUint8())
if !keyDeclType {
ti, err := resolver.readTypeInfo(buf, value)
ti, err := resolver.readTypeInfo(buf)
if err != nil {
return err
}
keySer = ti.Serializer
keyType = ti.Type
}
if !valDeclType {
ti, err := resolver.readTypeInfo(buf, value)
ti, err := resolver.readTypeInfo(buf)
if err != nil {
return err
}
Expand Down
4 changes: 0 additions & 4 deletions go/fory/reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@ func (r *RefResolver) WriteRefOrNull(buffer *ByteBuffer, value reflect.Value) (r
// reference types such as channel/function are not handled here and will be handled by typeResolver.
switch kind {
case reflect.Ptr:
elemValue := value.Elem()
if elemValue.Kind() == reflect.Array {
length = elemValue.Len()
}
isNil = value.IsNil()
case reflect.Map:
isNil = value.IsNil()
Expand Down
45 changes: 40 additions & 5 deletions go/fory/serializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package fory

import (
"fmt"
"math"
"reflect"
"time"
)
Expand Down Expand Up @@ -153,8 +154,25 @@ func (s int64Serializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) er
}

func (s int64Serializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error {
value.Set(reflect.ValueOf(buf.ReadVarint64()))
return nil
n := buf.ReadVarint64()
switch value.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
value.SetInt(n)
return nil
case reflect.Interface:
var iv interface{}
if f.language == XLANG {
iv = int64(n)
} else if n >= int64(math.MinInt) && n <= int64(math.MaxInt) {
iv = int(n)
} else {
iv = int64(n)
}
value.Set(reflect.ValueOf(iv))
return nil
default:
return fmt.Errorf("cannot assign int64 to %v", value.Type())
}
}

type intSerializer struct {
Expand Down Expand Up @@ -220,8 +238,26 @@ func (s float64Serializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value)
}

func (s float64Serializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error {
value.Set(reflect.ValueOf(buf.ReadFloat64()))
return nil
x := buf.ReadFloat64()

switch value.Kind() {
case reflect.Float32, reflect.Float64:
value.SetFloat(x)
return nil

case reflect.Interface:
var iv interface{}
if f.language == XLANG {
iv = float64(x)
} else {
iv = float64(x)
}
value.Set(reflect.ValueOf(iv))
return nil

default:
return fmt.Errorf("cannot assign float64 to %v", value.Type())
}
}

type stringSerializer struct {
Expand Down Expand Up @@ -462,7 +498,6 @@ func (s *ptrToValueSerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Val
}

func (s *ptrToValueSerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error {
fmt.Printf("type_: %v\n", type_)
newValue := reflect.New(type_.Elem())
value.Set(newValue)
return s.valueSerializer.Read(f, buf, type_.Elem(), newValue.Elem())
Expand Down
18 changes: 9 additions & 9 deletions go/fory/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (s setSerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) erro
collectFlag, elemTypeInfo := s.writeHeader(f, buf, keys)

// Check if all elements are of same type
if (collectFlag & CollectionIsSameType) != 0 {
if (collectFlag & COLL_IS_SAME_TYPE) != 0 {
// Optimized path for same-type elements
return s.writeSameType(f, buf, keys, elemTypeInfo, collectFlag)
}
Expand All @@ -69,7 +69,7 @@ func (s setSerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) erro
// - Element type information (if homogeneous)
func (s setSerializer) writeHeader(f *Fory, buf *ByteBuffer, keys []reflect.Value) (byte, TypeInfo) {
// Initialize collection flags and type tracking variables
collectFlag := CollectionDefaultFlag
collectFlag := COLL_DEFAULT_FLAG
var elemTypeInfo TypeInfo
hasNull := false
hasSameType := true
Expand Down Expand Up @@ -103,15 +103,15 @@ func (s setSerializer) writeHeader(f *Fory, buf *ByteBuffer, keys []reflect.Valu

// Set collection flags based on findings
if hasNull {
collectFlag |= CollectionHasNull // Mark if collection contains null values
collectFlag |= COLL_HAS_NULL // Mark if collection contains null values
}
if hasSameType {
collectFlag |= CollectionIsSameType // Mark if elements have different types
collectFlag |= COLL_IS_SAME_TYPE // Mark if elements have different types
}

// Enable reference tracking if configured
if f.refTracking {
collectFlag |= CollectionTrackingRef
collectFlag |= COLL_TRACKING_REF
}

// Write metadata to buffer
Expand All @@ -129,7 +129,7 @@ func (s setSerializer) writeHeader(f *Fory, buf *ByteBuffer, keys []reflect.Valu
// writeSameType efficiently serializes a collection where all elements share the same type
func (s setSerializer) writeSameType(f *Fory, buf *ByteBuffer, keys []reflect.Value, typeInfo TypeInfo, flag byte) error {
serializer := typeInfo.Serializer
trackRefs := (flag & CollectionTrackingRef) != 0 // Check if reference tracking is enabled
trackRefs := (flag & COLL_TRACKING_REF) != 0 // Check if reference tracking is enabled

for _, key := range keys {
key = UnwrapReflectValue(key)
Expand Down Expand Up @@ -206,7 +206,7 @@ func (s setSerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value
var elemTypeInfo TypeInfo

// If all elements are same type, read the shared type info
if (collectFlag & CollectionIsSameType) != 0 {
if (collectFlag & COLL_IS_SAME_TYPE) != 0 {
typeID := buf.ReadVarInt32()
elemTypeInfo, _ = f.typeResolver.getTypeInfoById(int16(typeID))
}
Expand All @@ -219,7 +219,7 @@ func (s setSerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value
f.refResolver.Reference(value)

// Choose appropriate deserialization path based on type consistency
if (collectFlag & CollectionIsSameType) != 0 {
if (collectFlag & COLL_IS_SAME_TYPE) != 0 {
return s.readSameType(f, buf, value, elemTypeInfo, collectFlag, length)
}
return s.readDifferentTypes(f, buf, value, length)
Expand All @@ -228,7 +228,7 @@ func (s setSerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value
// readSameType handles deserialization of sets where all elements share the same type
func (s setSerializer) readSameType(f *Fory, buf *ByteBuffer, value reflect.Value, typeInfo TypeInfo, flag int8, length int) error {
// Determine if reference tracking is enabled
trackRefs := (flag & CollectionTrackingRef) != 0
trackRefs := (flag & COLL_TRACKING_REF) != 0
serializer := typeInfo.Serializer

for i := 0; i < length; i++ {
Expand Down
Loading
Loading