Sfoglia il codice sorgente

suport encode interface

Tao Wen 8 anni fa
parent
commit
9b587c0f22

+ 1 - 1
feature_any.go

@@ -185,7 +185,7 @@ func (iter *Iterator) readObjectAny(reusableIter *Iterator) Any {
 func (iter *Iterator) readArrayAny(reusableIter *Iterator) Any {
 	level := 1
 	lazyBuf := make([]byte, 1, 32)
-	lazyBuf[0] = '{'
+	lazyBuf[0] = '['
 	for {
 		start := iter.head
 		for i := iter.head; i < iter.tail; i++ {

+ 27 - 0
feature_any_array.go

@@ -1,5 +1,9 @@
 package jsoniter
 
+import (
+	"unsafe"
+)
+
 type arrayLazyAny struct {
 	baseAny
 	buf       []byte
@@ -231,3 +235,26 @@ func (any *arrayLazyAny) IterateArray() (func() (Any, bool), bool) {
 		}
 	}, true
 }
+
+
+
+func (any *arrayLazyAny) GetArray() []Any {
+	any.fillCache()
+	return any.cache
+}
+
+func (any *arrayLazyAny) SetArray(newList []Any) bool {
+	any.fillCache()
+	any.cache = newList
+	return true
+}
+
+func (any *arrayLazyAny) WriteTo(stream *Stream) {
+	if len(any.remaining) == len(any.buf) {
+		// nothing has been parsed yet
+		stream.WriteRaw(*(*string)(unsafe.Pointer(&any.buf)))
+	} else {
+		any.fillCache()
+		stream.WriteVal(any.cache)
+	}
+}

+ 4 - 0
feature_any_int.go

@@ -67,6 +67,10 @@ func (any *intLazyAny) ToString() string {
 	return *(*string)(unsafe.Pointer(&any.buf))
 }
 
+func (any *intLazyAny) WriteTo(stream *Stream) {
+	stream.WriteRaw(*(*string)(unsafe.Pointer(&any.buf)))
+}
+
 type intAny struct {
 	baseAny
 	err   error

+ 10 - 0
feature_any_object.go

@@ -272,4 +272,14 @@ func (any *objectLazyAny) SetObject(val map[string]Any) bool {
 	any.fillCache()
 	any.cache = val
 	return true
+}
+
+func (any *objectLazyAny) WriteTo(stream *Stream) {
+	if len(any.remaining) == len(any.buf) {
+		// nothing has been parsed yet
+		stream.WriteRaw(*(*string)(unsafe.Pointer(&any.buf)))
+	} else {
+		any.fillCache()
+		stream.WriteVal(any.cache)
+	}
 }

+ 39 - 17
feature_reflect.go

@@ -20,8 +20,19 @@ For a simple struct binding, it will be reflect.Value free and allocation free
 type Decoder interface {
 	decode(ptr unsafe.Pointer, iter *Iterator)
 }
+
 type Encoder interface {
 	encode(ptr unsafe.Pointer, stream *Stream)
+	encodeInterface(val interface{}, stream *Stream)
+}
+
+func WriteToStream(val interface{}, stream *Stream, encoder Encoder) {
+	e := (*emptyInterface)(unsafe.Pointer(&val))
+	if reflect.TypeOf(val).Kind() == reflect.Ptr {
+		encoder.encode(unsafe.Pointer(&e.word), stream)
+	} else {
+		encoder.encode(e.word, stream)
+	}
 }
 
 type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
@@ -44,6 +55,10 @@ func (encoder *funcEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	encoder.fun(ptr, stream)
 }
 
+func (encoder *funcEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 var DECODERS unsafe.Pointer
 var ENCODERS unsafe.Pointer
 
@@ -52,6 +67,7 @@ var fieldDecoders map[string]Decoder
 var typeEncoders map[string]Encoder
 var fieldEncoders map[string]Encoder
 var extensions []ExtensionFunc
+var anyType reflect.Type
 
 func init() {
 	typeDecoders = map[string]Decoder{}
@@ -61,10 +77,7 @@ func init() {
 	extensions = []ExtensionFunc{}
 	atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{}))
 	atomic.StorePointer(&ENCODERS, unsafe.Pointer(&map[string]Encoder{}))
-	RegisterTypeEncoder("*jsoniter.intAny", func(ptr unsafe.Pointer, stream *Stream) {
-		val := *(**intAny)(ptr)
-		val.WriteTo(stream)
-	})
+	anyType = reflect.TypeOf((*Any)(nil)).Elem()
 }
 
 func addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
@@ -170,6 +183,10 @@ func (encoder *optionalEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	}
 }
 
+func (encoder *optionalEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type mapDecoder struct {
 	mapType      reflect.Type
 	elemType     reflect.Type
@@ -212,12 +229,15 @@ func (encoder *mapEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 		}
 		stream.WriteObjectField(key.String())
 		val := realVal.MapIndex(key).Interface()
-		e := (*emptyInterface)(unsafe.Pointer(&val))
-		encoder.elemEncoder.encode(e.word, stream)
+		encoder.elemEncoder.encodeInterface(val, stream)
 	}
 	stream.WriteObjectEnd()
 }
 
+func (encoder *mapEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type mapInterfaceEncoder struct {
 	mapType      reflect.Type
 	elemType     reflect.Type
@@ -243,6 +263,10 @@ func (encoder *mapInterfaceEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteObjectEnd()
 }
 
+func (encoder *mapInterfaceEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 // emptyInterface is the header for an interface{} value.
 type emptyInterface struct {
 	typ  *struct{}
@@ -285,13 +309,7 @@ func (stream *Stream) WriteVal(val interface{}) {
 		cachedEncoder = encoder
 		addEncoderToCache(cacheKey, encoder)
 	}
-
-	e := (*emptyInterface)(unsafe.Pointer(&val))
-	if typ.Kind() == reflect.Ptr {
-		cachedEncoder.encode(unsafe.Pointer(&e.word), stream)
-	} else {
-		cachedEncoder.encode(e.word, stream)
-	}
+	cachedEncoder.encodeInterface(val, stream)
 }
 
 type prefix string
@@ -365,6 +383,9 @@ func decoderOfType(typ reflect.Type) (Decoder, error) {
 }
 
 func encoderOfType(typ reflect.Type) (Encoder, error) {
+	if typ.ConvertibleTo(anyType) {
+		return &anyCodec{}, nil
+	}
 	typeName := typ.String()
 	typeEncoder := typeEncoders[typeName]
 	if typeEncoder != nil {
@@ -442,14 +463,15 @@ func decoderOfMap(typ reflect.Type) (Decoder, error) {
 }
 
 func encoderOfMap(typ reflect.Type) (Encoder, error) {
-	encoder, err := encoderOfType(typ.Elem())
+	elemType := typ.Elem()
+	encoder, err := encoderOfType(elemType)
 	if err != nil {
 		return nil, err
 	}
 	mapInterface := reflect.New(typ).Elem().Interface()
-	if typ.Elem().Kind() == reflect.Interface {
-		return &mapInterfaceEncoder{typ, typ.Elem(), encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
+	if elemType.Kind() == reflect.Interface && elemType.NumMethod() == 0 {
+		return &mapInterfaceEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
 	} else {
-		return &mapEncoder{typ, typ.Elem(), encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
+		return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
 	}
 }

+ 4 - 0
feature_reflect_array.go

@@ -49,6 +49,10 @@ func (encoder *sliceEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	}
 }
 
+func (encoder *sliceEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type sliceDecoder struct {
 	sliceType   reflect.Type
 	elemType    reflect.Type

+ 76 - 1
feature_reflect_native.go

@@ -15,6 +15,10 @@ func (codec *stringCodec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteString(*((*string)(ptr)))
 }
 
+func (encoder *stringCodec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type intCodec struct {
 }
 
@@ -26,6 +30,10 @@ func (codec *intCodec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteInt(*((*int)(ptr)))
 }
 
+func (encoder *intCodec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type int8Codec struct {
 }
 
@@ -37,6 +45,10 @@ func (codec *int8Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteInt8(*((*int8)(ptr)))
 }
 
+func (encoder *int8Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type int16Codec struct {
 }
 
@@ -48,6 +60,10 @@ func (codec *int16Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteInt16(*((*int16)(ptr)))
 }
 
+func (encoder *int16Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type int32Codec struct {
 }
 
@@ -59,6 +75,10 @@ func (codec *int32Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteInt32(*((*int32)(ptr)))
 }
 
+func (encoder *int32Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type int64Codec struct {
 }
 
@@ -70,6 +90,10 @@ func (codec *int64Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteInt64(*((*int64)(ptr)))
 }
 
+func (encoder *int64Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type uintCodec struct {
 }
 
@@ -81,6 +105,10 @@ func (codec *uintCodec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteUint(*((*uint)(ptr)))
 }
 
+func (encoder *uintCodec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type uint8Codec struct {
 }
 
@@ -92,6 +120,10 @@ func (codec *uint8Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteUint8(*((*uint8)(ptr)))
 }
 
+func (encoder *uint8Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type uint16Codec struct {
 }
 
@@ -99,10 +131,14 @@ func (decoder *uint16Codec) decode(ptr unsafe.Pointer, iter *Iterator) {
 	*((*uint16)(ptr)) = iter.ReadUint16()
 }
 
-func (decoder *uint16Codec) encode(ptr unsafe.Pointer, stream *Stream) {
+func (codec *uint16Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteUint16(*((*uint16)(ptr)))
 }
 
+func (encoder *uint16Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type uint32Codec struct {
 }
 
@@ -114,6 +150,10 @@ func (codec *uint32Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteUint32(*((*uint32)(ptr)))
 }
 
+func (encoder *uint32Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type uint64Codec struct {
 }
 
@@ -125,6 +165,10 @@ func (codec *uint64Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteUint64(*((*uint64)(ptr)))
 }
 
+func (encoder *uint64Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type float32Codec struct {
 }
 
@@ -136,6 +180,10 @@ func (codec *float32Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteFloat32(*((*float32)(ptr)))
 }
 
+func (encoder *float32Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type float64Codec struct {
 }
 
@@ -147,6 +195,10 @@ func (codec *float64Codec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteFloat64(*((*float64)(ptr)))
 }
 
+func (encoder *float64Codec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type boolCodec struct {
 }
 
@@ -158,6 +210,10 @@ func (codec *boolCodec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteBool(*((*bool)(ptr)))
 }
 
+func (encoder *boolCodec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 type interfaceCodec struct {
 }
 
@@ -169,6 +225,25 @@ func (codec *interfaceCodec) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteVal(*((*interface{})(ptr)))
 }
 
+func (encoder *interfaceCodec) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
+type anyCodec struct {
+}
+
+func (codec *anyCodec) decode(ptr unsafe.Pointer, iter *Iterator) {
+	*((*Any)(ptr)) = iter.ReadAny()
+}
+
+func (codec *anyCodec) encode(ptr unsafe.Pointer, stream *Stream) {
+	(*((*Any)(ptr))).WriteTo(stream)
+}
+
+func (encoder *anyCodec) encodeInterface(val interface{}, stream *Stream) {
+	(val.(Any)).WriteTo(stream)
+}
+
 type stringNumberDecoder struct {
 	elemDecoder Decoder
 }

+ 13 - 0
feature_reflect_object.go

@@ -405,6 +405,10 @@ func (encoder *structFieldEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	}
 }
 
+func (encoder *structFieldEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
 
 type structEncoder struct {
 	firstField *structFieldEncoder
@@ -421,9 +425,18 @@ func (encoder *structEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteObjectEnd()
 }
 
+func (encoder *structEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
+
 type emptyStructEncoder struct {
 }
 
 func (encoder *emptyStructEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	stream.WriteEmptyObject()
+}
+
+func (encoder *emptyStructEncoder) encodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
 }

+ 11 - 1
jsoniter_array_test.go

@@ -82,13 +82,23 @@ func Test_read_array_with_any_iterator(t *testing.T) {
 	should.Equal([]int{1, 2}, elements)
 }
 
-func Test_array_any_get(t *testing.T) {
+func Test_array_lazy_any_get(t *testing.T) {
 	should := require.New(t)
 	any, err := UnmarshalAnyFromString("[1,[2,3],4]")
 	should.Nil(err)
 	should.Equal(3, any.Get(1,1).ToInt())
 }
 
+func Test_array_lazy_any_set(t *testing.T) {
+	should := require.New(t)
+	any, err := UnmarshalAnyFromString("[1,[2,3],4]")
+	should.Nil(err)
+	any.GetArray()[0] = WrapInt64(2)
+	str, err := MarshalToString(any)
+	should.Nil(err)
+	should.Equal("[2,[2,3],4]", str)
+}
+
 func Test_invalid_array(t *testing.T) {
 	_, err := UnmarshalAnyFromString("[")
 	if err == nil || err == io.EOF {

+ 3 - 1
jsoniter_object_test.go

@@ -152,7 +152,9 @@ func Test_object_lazy_any_set(t *testing.T) {
 	any, err := UnmarshalAnyFromString(`{"a":{"b":{"c":"d"}}}`)
 	should.Nil(err)
 	any.GetObject()["a"] = WrapInt64(1)
-	should.Equal(`{"a":1}`, any.ToString())
+	str, err := MarshalToString(any)
+	should.Nil(err)
+	should.Equal(`{"a":1}`, str)
 }
 
 func Test_write_object(t *testing.T) {