Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion go/fory/buffer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
package fory

import (
"github.com/stretchr/testify/require"
"testing"

"github.com/stretchr/testify/require"
)

func TestVarInt(t *testing.T) {
Expand Down
13 changes: 1 addition & 12 deletions go/fory/fory.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,16 +370,6 @@ 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)
}
Expand Down Expand Up @@ -407,7 +397,6 @@ func (f *Fory) writeValue(buffer *ByteBuffer, value reflect.Value, serializer Se
} else {
serializer = typeInfo.Serializer
}
// Serialize the actual value using the serializer
return serializer.Write(f, buffer, value)
}

Expand Down Expand Up @@ -552,7 +541,7 @@ func (f *Fory) readData(buffer *ByteBuffer, value reflect.Value, serializer Seri
2. Deserialization into a user-defined concrete type.
*/
switch {
case value.Kind() == reflect.Interface,
case value.Kind() == reflect.Interface && typeInfo.Type.Kind() != reflect.Slice,
!value.CanSet():
concrete = reflect.New(typeInfo.Type).Elem()
type_ = typeInfo.Type
Expand Down
20 changes: 15 additions & 5 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,17 +102,27 @@ func commonMap() []interface{} {
}
}

/*
- Based on the review, this usage is generally uncommon in practice. We are keeping
the earliest test, and therefore still support serialization of fixed-length arrays
([N]T) for completeness and compatibility.
- Unless the destination type is explicitly an array ([N]T), values are deserialized
into slices ([]T).
- For byte buffers, callers are expected to use []byte. A [N]byte target is not a
typical or supported path here, so we did not add extra deserialization logic for
[N]byte—only []byte is supported.
*/

func commonArray() []interface{} {
return []interface{}{
[100]bool{false, true, true},
[100]byte{1, 2, 3},
// [100]int8{1, 2, 3},
//[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"},
}
}

Expand Down Expand Up @@ -162,7 +172,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
13 changes: 6 additions & 7 deletions go/fory/fory_xlang_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ func TestXLangSerializer(t *testing.T) {
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))
require.Nil(t, fory_.Serialize(buffer, [2]bool{true, false}, nil))
require.Nil(t, fory_.Serialize(buffer, [2]int16{1, fory.MaxInt16}, nil))
require.Nil(t, fory_.Serialize(buffer, [2]int32{1, fory.MaxInt32}, nil))
require.Nil(t, fory_.Serialize(buffer, [2]int64{1, fory.MaxInt64}, nil))
require.Nil(t, fory_.Serialize(buffer, [2]float32{1.0, 2.0}, nil))
require.Nil(t, fory_.Serialize(buffer, [2]float64{1.0, 2.0}, nil))

check := func(buf *fory.ByteBuffer) {
values := []interface{}{
Expand Down Expand Up @@ -260,7 +260,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: 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
3 changes: 2 additions & 1 deletion go/fory/reference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
package fory

import (
"github.com/stretchr/testify/require"
"reflect"
"testing"
"unsafe"

"github.com/stretchr/testify/require"
)

func TestReferenceResolver(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions go/fory/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"bytes"
"encoding/binary"
"fmt"

"github.com/apache/fory/go/fory/meta"
"github.com/spaolacci/murmur3"
)
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