1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-24 08:22:14 +02:00

use reflect2 to replace reflect

This commit is contained in:
Tao Wen 2018-02-22 10:12:08 +08:00
parent a3866383f5
commit 99fc16a363
22 changed files with 307 additions and 286 deletions

12
any.go
View File

@ -90,7 +90,7 @@ func Wrap(val interface{}) Any {
if isAny {
return asAny
}
typ := reflect.TypeOf(val)
typ := reflect2.TypeOf(val)
switch typ.Kind() {
case reflect.Slice:
return wrapArray(val)
@ -245,27 +245,27 @@ func locatePath(iter *Iterator, path []interface{}) Any {
return iter.readAny()
}
var anyType = reflect.TypeOf((*Any)(nil)).Elem()
var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem()
func createDecoderOfAny(ctx *ctx, typ reflect.Type) ValDecoder {
func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ == anyType {
return &directAnyCodec{}
}
if typ.Implements(anyType) {
return &anyCodec{
valType: reflect2.Type2(typ),
valType: typ,
}
}
return nil
}
func createEncoderOfAny(ctx *ctx, typ reflect.Type) ValEncoder {
func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ == anyType {
return &directAnyCodec{}
}
if typ.Implements(anyType) {
return &anyCodec{
valType: reflect2.Type2(typ),
valType: typ,
}
}
return nil

View File

@ -3,8 +3,8 @@ package jsoniter
import (
"encoding/json"
"io"
"reflect"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
// Config customize how the API should behave.
@ -118,12 +118,12 @@ func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) {
}, func(ptr unsafe.Pointer) bool {
return false
}}
extension[reflect.TypeOf((*json.RawMessage)(nil)).Elem()] = encoder
extension[reflect.TypeOf((*RawMessage)(nil)).Elem()] = encoder
extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder
extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder
}
func (cfg *frozenConfig) useNumber(extension DecoderExtension) {
extension[reflect.TypeOf((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
if iter.WhatIsNext() == NumberValue {
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
} else {
@ -169,8 +169,8 @@ func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool {
// for float variables for better performance.
func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) {
// for better performance
extension[reflect.TypeOf((*float32)(nil)).Elem()] = &lossyFloat32Encoder{}
extension[reflect.TypeOf((*float64)(nil)).Elem()] = &lossyFloat64Encoder{}
extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{}
extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{}
}
type htmlEscapedStringEncoder struct {
@ -186,7 +186,7 @@ func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
}
func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) {
encoderExtension[reflect.TypeOf((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{}
encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{}
}
func (cfg *frozenConfig) cleanDecoders() {

View File

@ -3,7 +3,6 @@
package jsoniter
import (
"reflect"
"sync"
)
@ -26,15 +25,15 @@ func (cfg *frozenConfig) initCache() {
cfg.encoderCache = sync.Map{}
}
func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder ValDecoder) {
func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) {
cfg.decoderCache.Store(cacheKey, decoder)
}
func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder ValEncoder) {
func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) {
cfg.encoderCache.Store(cacheKey, encoder)
}
func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder {
decoder, found := cfg.decoderCache.Load(cacheKey)
if found {
return decoder.(ValDecoder)
@ -42,7 +41,7 @@ func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
return nil
}
func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
encoder, found := cfg.encoderCache.Load(cacheKey)
if found {
return encoder.(ValEncoder)

View File

@ -15,8 +15,8 @@ type frozenConfig struct {
onlyTaggedField bool
disallowUnknownFields bool
cacheLock *sync.RWMutex
decoderCache map[reflect.Type]ValDecoder
encoderCache map[reflect.Type]ValEncoder
decoderCache map[reflect2.Type]ValDecoder
encoderCache map[reflect2.Type]ValEncoder
extensions []Extension
streamPool chan *Stream
iteratorPool chan *Iterator
@ -24,30 +24,30 @@ type frozenConfig struct {
func (cfg *frozenConfig) initCache() {
cfg.cacheLock = &sync.RWMutex{}
cfg.decoderCache = map[reflect.Type]ValDecoder{}
cfg.encoderCache = map[reflect.Type]ValEncoder{}
cfg.decoderCache = map[reflect2.Type]ValDecoder{}
cfg.encoderCache = map[reflect2.Type]ValEncoder{}
}
func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder ValDecoder) {
func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect2.Type, decoder ValDecoder) {
cfg.cacheLock.Lock()
cfg.decoderCache[cacheKey] = decoder
cfg.cacheLock.Unlock()
}
func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder ValEncoder) {
func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect2.Type, encoder ValEncoder) {
cfg.cacheLock.Lock()
cfg.encoderCache[cacheKey] = encoder
cfg.cacheLock.Unlock()
}
func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect2.Type) ValDecoder {
cfg.cacheLock.RLock()
decoder, _ := cfg.decoderCache[cacheKey].(ValDecoder)
cfg.cacheLock.RUnlock()
return decoder
}
func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect2.Type) ValEncoder {
cfg.cacheLock.RLock()
encoder, _ := cfg.encoderCache[cacheKey].(ValEncoder)
cfg.cacheLock.RUnlock()

View File

@ -9,6 +9,7 @@ import (
"unsafe"
"github.com/json-iterator/go"
"github.com/v2pro/plz/reflect2"
)
const maxUint = ^uint(0)
@ -148,7 +149,7 @@ type tolerateEmptyArrayExtension struct {
jsoniter.DummyExtension
}
func (extension *tolerateEmptyArrayExtension) DecorateDecoder(typ reflect.Type, decoder jsoniter.ValDecoder) jsoniter.ValDecoder {
func (extension *tolerateEmptyArrayExtension) DecorateDecoder(typ reflect2.Type, decoder jsoniter.ValDecoder) jsoniter.ValDecoder {
if typ.Kind() == reflect.Struct || typ.Kind() == reflect.Map {
return &tolerateEmptyArrayDecoder{decoder}
}

View File

@ -17,8 +17,8 @@ type namingStrategyExtension struct {
func (extension *namingStrategyExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) {
for _, binding := range structDescriptor.Fields {
binding.ToNames = []string{extension.translate(binding.Field.Name)}
binding.FromNames = []string{extension.translate(binding.Field.Name)}
binding.ToNames = []string{extension.translate(binding.Field.Name())}
binding.FromNames = []string{extension.translate(binding.Field.Name())}
}
}

View File

@ -16,10 +16,10 @@ type privateFieldsExtension struct {
func (extension *privateFieldsExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) {
for _, binding := range structDescriptor.Fields {
isPrivate := unicode.IsLower(rune(binding.Field.Name[0]))
isPrivate := unicode.IsLower(rune(binding.Field.Name()[0]))
if isPrivate {
binding.FromNames = []string{binding.Field.Name}
binding.ToNames = []string{binding.Field.Name}
binding.FromNames = []string{binding.Field.Name()}
binding.ToNames = []string{binding.Field.Name()}
}
}
}

View File

@ -36,8 +36,8 @@ type checkIsEmpty interface {
type ctx struct {
*frozenConfig
prefix string
encoders map[reflect.Type]ValEncoder
decoders map[reflect.Type]ValDecoder
encoders map[reflect2.Type]ValEncoder
decoders map[reflect2.Type]ValDecoder
}
func (b *ctx) append(prefix string) *ctx {
@ -51,7 +51,7 @@ func (b *ctx) append(prefix string) *ctx {
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
func (iter *Iterator) ReadVal(obj interface{}) {
typ := reflect.TypeOf(obj)
typ := reflect2.TypeOf(obj)
if typ.Kind() != reflect.Ptr {
iter.ReportError("ReadVal", "can only unmarshal into pointer")
return
@ -71,13 +71,13 @@ func (stream *Stream) WriteVal(val interface{}) {
stream.WriteNil()
return
}
typ := reflect.TypeOf(val)
typ := reflect2.TypeOf(val)
encoder := stream.cfg.EncoderOf(typ)
encoder.Encode(reflect2.PtrOf(val), stream)
}
func (cfg *frozenConfig) DecoderOf(typ reflect.Type) ValDecoder {
cacheKey := typ
func (cfg *frozenConfig) DecoderOf(typ reflect2.Type) ValDecoder {
cacheKey := typ.RType()
decoder := cfg.getDecoderFromCache(cacheKey)
if decoder != nil {
return decoder
@ -85,15 +85,16 @@ func (cfg *frozenConfig) DecoderOf(typ reflect.Type) ValDecoder {
ctx := &ctx{
frozenConfig: cfg,
prefix: "",
decoders: map[reflect.Type]ValDecoder{},
encoders: map[reflect.Type]ValEncoder{},
decoders: map[reflect2.Type]ValDecoder{},
encoders: map[reflect2.Type]ValEncoder{},
}
decoder = decoderOfType(ctx, typ.Elem())
ptrType := typ.(*reflect2.UnsafePtrType)
decoder = decoderOfType(ctx, ptrType.Elem())
cfg.addDecoderToCache(cacheKey, decoder)
return decoder
}
func decoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
func decoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := getTypeDecoderFromExtension(ctx, typ)
if decoder != nil {
return decoder
@ -108,7 +109,7 @@ func decoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
return decoder
}
func createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
func createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := ctx.decoders[typ]
if decoder != nil {
return decoder
@ -120,7 +121,7 @@ func createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
return decoder
}
func _createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
func _createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := createDecoderOfJsonRawMessage(ctx, typ)
if decoder != nil {
return decoder
@ -143,8 +144,8 @@ func _createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
}
switch typ.Kind() {
case reflect.Interface:
if typ.NumMethod() > 0 {
ifaceType := reflect2.Type2(typ).(*reflect2.UnsafeIFaceType)
ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType)
if isIFace {
return &ifaceDecoder{valType: ifaceType}
}
return &efaceDecoder{}
@ -163,8 +164,8 @@ func _createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
}
}
func (cfg *frozenConfig) EncoderOf(typ reflect.Type) ValEncoder {
cacheKey := typ
func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder {
cacheKey := typ.RType()
encoder := cfg.getEncoderFromCache(cacheKey)
if encoder != nil {
return encoder
@ -172,11 +173,11 @@ func (cfg *frozenConfig) EncoderOf(typ reflect.Type) ValEncoder {
ctx := &ctx{
frozenConfig: cfg,
prefix: "",
decoders: map[reflect.Type]ValDecoder{},
encoders: map[reflect.Type]ValEncoder{},
decoders: map[reflect2.Type]ValDecoder{},
encoders: map[reflect2.Type]ValEncoder{},
}
encoder = encoderOfType(ctx, typ)
if shouldFixOnePtr(typ) {
if typ.LikePtr() {
encoder = &onePtrEncoder{encoder}
}
cfg.addEncoderToCache(cacheKey, encoder)
@ -195,11 +196,7 @@ func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
}
func shouldFixOnePtr(typ reflect.Type) bool {
return reflect2.Type2(typ).LikePtr()
}
func encoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := getTypeEncoderFromExtension(ctx, typ)
if encoder != nil {
return encoder
@ -214,7 +211,7 @@ func encoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
return encoder
}
func createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := ctx.encoders[typ]
if encoder != nil {
return encoder
@ -225,7 +222,7 @@ func createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
placeholder.encoder = encoder
return encoder
}
func _createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := createEncoderOfJsonRawMessage(ctx, typ)
if encoder != nil {
return encoder
@ -249,7 +246,7 @@ func _createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
kind := typ.Kind()
switch kind {
case reflect.Interface:
return &dynamicEncoder{reflect2.Type2(typ)}
return &dynamicEncoder{typ}
case reflect.Struct:
return encoderOfStruct(ctx, typ)
case reflect.Array:

View File

@ -3,21 +3,23 @@ package jsoniter
import (
"fmt"
"io"
"reflect"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func decoderOfArray(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := decoderOfType(ctx.append("[arrayElem]"), typ.Elem())
return &arrayDecoder{typ, typ.Elem(), decoder}
func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder {
arrayType := typ.(*reflect2.UnsafeArrayType)
decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
return &arrayDecoder{arrayType, decoder}
}
func encoderOfArray(ctx *ctx, typ reflect.Type) ValEncoder {
if typ.Len() == 0 {
func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder {
arrayType := typ.(*reflect2.UnsafeArrayType)
if arrayType.Len() == 0 {
return emptyArrayEncoder{}
}
encoder := encoderOfType(ctx.append("[arrayElem]"), typ.Elem())
return &arrayEncoder{typ, typ.Elem(), encoder}
encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
return &arrayEncoder{arrayType, encoder}
}
type emptyArrayEncoder struct{}
@ -31,8 +33,7 @@ func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
}
type arrayEncoder struct {
arrayType reflect.Type
elemType reflect.Type
arrayType *reflect2.UnsafeArrayType
elemEncoder ValEncoder
}
@ -42,8 +43,8 @@ func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.elemEncoder.Encode(elemPtr, stream)
for i := 1; i < encoder.arrayType.Len(); i++ {
stream.WriteMore()
elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
if stream.Error != nil && stream.Error != io.EOF {
@ -56,8 +57,7 @@ func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
}
type arrayDecoder struct {
arrayType reflect.Type
elemType reflect.Type
arrayType *reflect2.UnsafeArrayType
elemDecoder ValDecoder
}
@ -69,14 +69,36 @@ func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
offset := uintptr(0)
iter.ReadArrayCB(func(iter *Iterator) bool {
if offset < decoder.arrayType.Size() {
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(ptr)+offset), iter)
offset += decoder.elemType.Size()
} else {
c := iter.nextToken()
arrayType := decoder.arrayType
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
return
}
if c != '[' {
iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c}))
return
}
c = iter.nextToken()
if c == ']' {
return
}
iter.unreadByte()
elemPtr := arrayType.UnsafeGetIndex(ptr, 0)
decoder.elemDecoder.Decode(elemPtr, iter)
length := 1
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
if length >= arrayType.Len() {
iter.Skip()
continue
}
return true
})
idx := length
length += 1
elemPtr = arrayType.UnsafeGetIndex(ptr, idx)
decoder.elemDecoder.Decode(elemPtr, iter)
}
if c != ']' {
iter.ReportError("decode array", "expect ], but found "+string([]byte{c}))
return
}
}

View File

@ -18,7 +18,7 @@ var extensions = []Extension{}
// StructDescriptor describe how should we encode/decode the struct
type StructDescriptor struct {
Type reflect.Type
Type reflect2.Type
Fields []*Binding
}
@ -26,7 +26,7 @@ type StructDescriptor struct {
// Can not use map here to keep field orders.
func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
for _, binding := range structDescriptor.Fields {
if binding.Field.Name == fieldName {
if binding.Field.Name() == fieldName {
return binding
}
}
@ -36,7 +36,7 @@ func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
// Binding describe how should we encode/decode the struct field
type Binding struct {
levels []int
Field *reflect.StructField
Field reflect2.StructField
FromNames []string
ToNames []string
Encoder ValEncoder
@ -47,10 +47,10 @@ type Binding struct {
// Can also rename fields by UpdateStructDescriptor.
type Extension interface {
UpdateStructDescriptor(structDescriptor *StructDescriptor)
CreateDecoder(typ reflect.Type) ValDecoder
CreateEncoder(typ reflect.Type) ValEncoder
DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder
DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder
CreateDecoder(typ reflect2.Type) ValDecoder
CreateEncoder(typ reflect2.Type) ValEncoder
DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder
DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder
}
// DummyExtension embed this type get dummy implementation for all methods of Extension
@ -62,74 +62,74 @@ func (extension *DummyExtension) UpdateStructDescriptor(structDescriptor *Struct
}
// CreateDecoder No-op
func (extension *DummyExtension) CreateDecoder(typ reflect.Type) ValDecoder {
func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateEncoder No-op
func (extension *DummyExtension) CreateEncoder(typ reflect.Type) ValEncoder {
func (extension *DummyExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// DecorateDecoder No-op
func (extension *DummyExtension) DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder {
func (extension *DummyExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
}
// DecorateEncoder No-op
func (extension *DummyExtension) DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder {
func (extension *DummyExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder {
return encoder
}
type EncoderExtension map[reflect.Type]ValEncoder
type EncoderExtension map[reflect2.Type]ValEncoder
// UpdateStructDescriptor No-op
func (extension EncoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
}
// CreateDecoder No-op
func (extension EncoderExtension) CreateDecoder(typ reflect.Type) ValDecoder {
func (extension EncoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateEncoder get encoder from map
func (extension EncoderExtension) CreateEncoder(typ reflect.Type) ValEncoder {
func (extension EncoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return extension[typ]
}
// DecorateDecoder No-op
func (extension EncoderExtension) DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder {
func (extension EncoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
}
// DecorateEncoder No-op
func (extension EncoderExtension) DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder {
func (extension EncoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder {
return encoder
}
type DecoderExtension map[reflect.Type]ValDecoder
type DecoderExtension map[reflect2.Type]ValDecoder
// UpdateStructDescriptor No-op
func (extension DecoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
}
// CreateDecoder get decoder from map
func (extension DecoderExtension) CreateDecoder(typ reflect.Type) ValDecoder {
func (extension DecoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return extension[typ]
}
// CreateEncoder No-op
func (extension DecoderExtension) CreateEncoder(typ reflect.Type) ValEncoder {
func (extension DecoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// DecorateDecoder No-op
func (extension DecoderExtension) DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder {
func (extension DecoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
}
// DecorateEncoder No-op
func (extension DecoderExtension) DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder {
func (extension DecoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder {
return encoder
}
@ -208,7 +208,7 @@ func RegisterExtension(extension Extension) {
extensions = append(extensions, extension)
}
func getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
func getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := _getTypeDecoderFromExtension(ctx, typ)
if decoder != nil {
for _, extension := range extensions {
@ -220,7 +220,7 @@ func getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
}
return decoder
}
func _getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
func _getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder {
for _, extension := range extensions {
decoder := extension.CreateDecoder(typ)
if decoder != nil {
@ -239,15 +239,16 @@ func _getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
return decoder
}
if typ.Kind() == reflect.Ptr {
decoder := typeDecoders[typ.Elem().String()]
ptrType := typ.(*reflect2.UnsafePtrType)
decoder := typeDecoders[ptrType.Elem().String()]
if decoder != nil {
return &OptionalDecoder{reflect2.Type2(typ.Elem()), decoder}
return &OptionalDecoder{ptrType.Elem(), decoder}
}
}
return nil
}
func getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
func getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := _getTypeEncoderFromExtension(ctx, typ)
if encoder != nil {
for _, extension := range extensions {
@ -260,7 +261,7 @@ func getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
return encoder
}
func _getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
func _getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder {
for _, extension := range extensions {
encoder := extension.CreateEncoder(typ)
if encoder != nil {
@ -279,7 +280,8 @@ func _getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
return encoder
}
if typ.Kind() == reflect.Ptr {
encoder := typeEncoders[typ.Elem().String()]
typePtr := typ.(*reflect2.UnsafePtrType)
encoder := typeEncoders[typePtr.Elem().String()]
if encoder != nil {
return &OptionalEncoder{encoder}
}
@ -287,12 +289,13 @@ func _getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
return nil
}
func describeStruct(ctx *ctx, typ reflect.Type) *StructDescriptor {
func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
structType := typ.(*reflect2.UnsafeStructType)
embeddedBindings := []*Binding{}
bindings := []*Binding{}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
tag, hastag := field.Tag.Lookup(ctx.getTagKey())
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
if ctx.onlyTaggedField && !hastag {
continue
}
@ -300,43 +303,46 @@ func describeStruct(ctx *ctx, typ reflect.Type) *StructDescriptor {
if tag == "-" {
continue
}
if field.Anonymous && (tag == "" || tagParts[0] == "") {
if field.Type.Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, field.Type)
if field.Anonymous() && (tag == "" || tagParts[0] == "") {
if field.Type().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, field.Type())
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty}
binding.Decoder = &structFieldDecoder{field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, field.Type.Elem())
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &dereferenceEncoder{binding.Encoder}
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
binding.Decoder = &dereferenceDecoder{reflect2.Type2(field.Type.Elem()), binding.Decoder}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
} else if field.Type().Kind() == reflect.Ptr {
ptrType := field.Type().(*reflect2.UnsafePtrType)
if ptrType.Elem().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, ptrType.Elem())
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &dereferenceEncoder{binding.Encoder}
binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty}
binding.Decoder = &dereferenceDecoder{ptrType.Elem(), binding.Decoder}
binding.Decoder = &structFieldDecoder{field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
}
continue
}
}
fieldNames := calcFieldNames(field.Name, tagParts[0], tag)
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
fieldNames := calcFieldNames(field.Name(), tagParts[0], tag)
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name())
decoder := fieldDecoders[fieldCacheKey]
if decoder == nil {
decoder = decoderOfType(ctx.append(field.Name), field.Type)
decoder = decoderOfType(ctx.append(field.Name()), field.Type())
}
encoder := fieldEncoders[fieldCacheKey]
if encoder == nil {
encoder = encoderOfType(ctx.append(field.Name), field.Type)
encoder = encoderOfType(ctx.append(field.Name()), field.Type())
}
binding := &Binding{
Field: &field,
Field: field,
FromNames: fieldNames,
ToNames: fieldNames,
Decoder: decoder,
@ -347,7 +353,7 @@ func describeStruct(ctx *ctx, typ reflect.Type) *StructDescriptor {
}
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
}
func createStructDescriptor(ctx *ctx, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
structDescriptor := &StructDescriptor{
Type: typ,
Fields: bindings,
@ -366,21 +372,6 @@ func createStructDescriptor(ctx *ctx, typ reflect.Type, bindings []*Binding, emb
return structDescriptor
}
func isStructOnePtr(typ reflect.Type) bool {
if typ.NumField() == 1 {
firstField := typ.Field(0)
switch firstField.Type.Kind() {
case reflect.Ptr:
return true
case reflect.Map:
return true
case reflect.Struct:
return isStructOnePtr(firstField.Type)
}
}
return false
}
type sortableBindings []*Binding
func (bindings sortableBindings) Len() int {
@ -408,12 +399,12 @@ func (bindings sortableBindings) Swap(i, j int) {
func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) {
for _, binding := range structDescriptor.Fields {
shouldOmitEmpty := false
tagParts := strings.Split(binding.Field.Tag.Get(cfg.getTagKey()), ",")
tagParts := strings.Split(binding.Field.Tag().Get(cfg.getTagKey()), ",")
for _, tagPart := range tagParts[1:] {
if tagPart == "omitempty" {
shouldOmitEmpty = true
} else if tagPart == "string" {
if binding.Field.Type.Kind() == reflect.String {
if binding.Field.Type().Kind() == reflect.String {
binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg}
binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg}
} else {

View File

@ -4,7 +4,7 @@ import (
"encoding/json"
"strconv"
"unsafe"
"reflect"
"github.com/v2pro/plz/reflect2"
)
type Number string
@ -32,10 +32,10 @@ func CastJsonNumber(val interface{}) (string, bool) {
return "", false
}
var jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem()
var jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem()
var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem()
var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem()
func createDecoderOfJsonNumber(ctx *ctx, typ reflect.Type) ValDecoder {
func createDecoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}
}
@ -45,7 +45,7 @@ func createDecoderOfJsonNumber(ctx *ctx, typ reflect.Type) ValDecoder {
return nil
}
func createEncoderOfJsonNumber(ctx *ctx, typ reflect.Type) ValEncoder {
func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}
}

View File

@ -3,13 +3,13 @@ package jsoniter
import (
"unsafe"
"encoding/json"
"reflect"
"github.com/v2pro/plz/reflect2"
)
var jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
var jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem()
var jsonRawMessageType = reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()
var jsoniterRawMessageType = reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()
func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect.Type) ValEncoder {
func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}
}
@ -19,7 +19,7 @@ func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect.Type) ValEncoder {
return nil
}
func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect.Type) ValDecoder {
func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}
}

View File

@ -8,10 +8,10 @@ import (
"fmt"
)
func decoderOfMap(ctx *ctx, typ reflect.Type) ValDecoder {
keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), typ.Key())
elemDecoder := decoderOfType(ctx.append("[mapElem]"), typ.Elem())
mapType := reflect2.Type2(typ).(*reflect2.UnsafeMapType)
func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder {
mapType := typ.(*reflect2.UnsafeMapType)
keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key())
elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem())
return &mapDecoder{
mapType: mapType,
keyType: mapType.Key(),
@ -21,25 +21,26 @@ func decoderOfMap(ctx *ctx, typ reflect.Type) ValDecoder {
}
}
func encoderOfMap(ctx *ctx, typ reflect.Type) ValEncoder {
func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
mapType := typ.(*reflect2.UnsafeMapType)
if ctx.sortMapKeys {
return &sortKeysMapEncoder{
mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType),
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), typ.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), typ.Elem()),
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
}
}
return &mapEncoder{
mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType),
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), typ.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), typ.Elem()),
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
}
}
func decoderOfMapKey(ctx *ctx, typ reflect.Type) ValDecoder {
func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
switch typ.Kind() {
case reflect.String:
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String).Type1())
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
@ -48,30 +49,30 @@ func decoderOfMapKey(ctx *ctx, typ reflect.Type) ValDecoder {
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1()
typ = reflect2.DefaultTypeOfKind(typ.Kind())
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
default:
ptrType := reflect.PtrTo(typ)
ptrType := reflect2.PtrTo(typ)
if ptrType.Implements(textMarshalerType) {
return &referenceDecoder{
&textUnmarshalerDecoder{
valType: reflect2.Type2(ptrType),
valType: ptrType,
},
}
}
if typ.Implements(textMarshalerType) {
return &textUnmarshalerDecoder{
valType: reflect2.Type2(typ),
valType: typ,
}
}
return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
}
}
func encoderOfMapKey(ctx *ctx, typ reflect.Type) ValEncoder {
func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
switch typ.Kind() {
case reflect.String:
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String).Type1())
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
@ -80,18 +81,18 @@ func encoderOfMapKey(ctx *ctx, typ reflect.Type) ValEncoder {
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1()
typ = reflect2.DefaultTypeOfKind(typ.Kind())
return &numericMapKeyEncoder{encoderOfType(ctx, typ)}
default:
if typ == textMarshalerType {
return &directTextMarshalerEncoder{
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
}
if typ.Implements(textMarshalerType) {
return &textMarshalerEncoder{
valType: reflect2.Type2(typ),
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
valType: typ,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
}
return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}

View File

@ -5,30 +5,29 @@ import (
"unsafe"
"encoding"
"encoding/json"
"reflect"
)
var marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
var unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
var marshalerType = reflect2.TypeOfPtr((*json.Marshaler)(nil)).Elem()
var unmarshalerType = reflect2.TypeOfPtr((*json.Unmarshaler)(nil)).Elem()
var textMarshalerType = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem()
var textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem()
func createDecoderOfMarshaler(ctx *ctx, typ reflect.Type) ValDecoder {
ptrType := reflect.PtrTo(typ)
func createDecoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValDecoder {
ptrType := reflect2.PtrTo(typ)
if ptrType.Implements(unmarshalerType) {
return &referenceDecoder{
&unmarshalerDecoder{reflect2.Type2(ptrType)},
&unmarshalerDecoder{ptrType},
}
}
if ptrType.Implements(textUnmarshalerType) {
return &referenceDecoder{
&textUnmarshalerDecoder{reflect2.Type2(ptrType)},
&textUnmarshalerDecoder{ptrType},
}
}
return nil
}
func createEncoderOfMarshaler(ctx *ctx, typ reflect.Type) ValEncoder {
func createEncoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ == marshalerType {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &directMarshalerEncoder{
@ -39,16 +38,16 @@ func createEncoderOfMarshaler(ctx *ctx, typ reflect.Type) ValEncoder {
if typ.Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &marshalerEncoder{
valType: reflect2.Type2(typ),
valType: typ,
checkIsEmpty: checkIsEmpty,
}
return encoder
}
ptrType := reflect.PtrTo(typ)
ptrType := reflect2.PtrTo(typ)
if ctx.prefix != "" && ptrType.Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
var encoder ValEncoder = &marshalerEncoder{
valType: reflect2.Type2(ptrType),
valType: ptrType,
checkIsEmpty: checkIsEmpty,
}
return &referenceEncoder{encoder}
@ -57,15 +56,15 @@ func createEncoderOfMarshaler(ctx *ctx, typ reflect.Type) ValEncoder {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &directTextMarshalerEncoder{
checkIsEmpty: checkIsEmpty,
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
return encoder
}
if typ.Implements(textMarshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &textMarshalerEncoder{
valType: reflect2.Type2(typ),
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
valType: typ,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
checkIsEmpty: checkIsEmpty,
}
return encoder
@ -74,8 +73,8 @@ func createEncoderOfMarshaler(ctx *ctx, typ reflect.Type) ValEncoder {
if ctx.prefix != "" && ptrType.Implements(textMarshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
var encoder ValEncoder = &textMarshalerEncoder{
valType: reflect2.Type2(ptrType),
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
valType: ptrType,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
checkIsEmpty: checkIsEmpty,
}
return &referenceEncoder{encoder}

View File

@ -7,8 +7,8 @@ import (
"github.com/v2pro/plz/reflect2"
)
func createEncoderOfNative(ctx *ctx, typ reflect.Type) ValEncoder {
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
func createEncoderOfNative(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 {
sliceDecoder := decoderOfSlice(ctx, typ)
return &base64Codec{sliceDecoder: sliceDecoder}
}
@ -17,85 +17,85 @@ func createEncoderOfNative(ctx *ctx, typ reflect.Type) ValEncoder {
switch kind {
case reflect.String:
if typeName != "string" {
return encoderOfType(ctx, reflect.TypeOf((*string)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return encoderOfType(ctx, reflect.TypeOf((*int)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem())
}
return &intCodec{}
case reflect.Int8:
if typeName != "int8" {
return encoderOfType(ctx, reflect.TypeOf((*int8)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return encoderOfType(ctx, reflect.TypeOf((*int16)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return encoderOfType(ctx, reflect.TypeOf((*int32)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return encoderOfType(ctx, reflect.TypeOf((*int64)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return encoderOfType(ctx, reflect.TypeOf((*uint)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem())
}
return &uintCodec{}
case reflect.Uint8:
if typeName != "uint8" {
return encoderOfType(ctx, reflect.TypeOf((*uint8)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return encoderOfType(ctx, reflect.TypeOf((*uint16)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return encoderOfType(ctx, reflect.TypeOf((*uint32)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return encoderOfType(ctx, reflect.TypeOf((*uintptr)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}
case reflect.Uint64:
if typeName != "uint64" {
return encoderOfType(ctx, reflect.TypeOf((*uint64)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return encoderOfType(ctx, reflect.TypeOf((*float32)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return encoderOfType(ctx, reflect.TypeOf((*float64)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return encoderOfType(ctx, reflect.TypeOf((*bool)(nil)).Elem())
return encoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem())
}
return &boolCodec{}
}
return nil
}
func createDecoderOfNative(ctx *ctx, typ reflect.Type) ValDecoder {
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 {
sliceDecoder := decoderOfSlice(ctx, typ)
return &base64Codec{sliceDecoder: sliceDecoder}
}
@ -103,77 +103,77 @@ func createDecoderOfNative(ctx *ctx, typ reflect.Type) ValDecoder {
switch typ.Kind() {
case reflect.String:
if typeName != "string" {
return decoderOfType(ctx, reflect.TypeOf((*string)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return decoderOfType(ctx, reflect.TypeOf((*int)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem())
}
return &intCodec{}
case reflect.Int8:
if typeName != "int8" {
return decoderOfType(ctx, reflect.TypeOf((*int8)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return decoderOfType(ctx, reflect.TypeOf((*int16)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return decoderOfType(ctx, reflect.TypeOf((*int32)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return decoderOfType(ctx, reflect.TypeOf((*int64)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return decoderOfType(ctx, reflect.TypeOf((*uint)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem())
}
return &uintCodec{}
case reflect.Uint8:
if typeName != "uint8" {
return decoderOfType(ctx, reflect.TypeOf((*uint8)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return decoderOfType(ctx, reflect.TypeOf((*uint16)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return decoderOfType(ctx, reflect.TypeOf((*uint32)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return decoderOfType(ctx, reflect.TypeOf((*uintptr)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}
case reflect.Uint64:
if typeName != "uint64" {
return decoderOfType(ctx, reflect.TypeOf((*uint64)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return decoderOfType(ctx, reflect.TypeOf((*float32)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return decoderOfType(ctx, reflect.TypeOf((*float64)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return decoderOfType(ctx, reflect.TypeOf((*bool)(nil)).Elem())
return decoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem())
}
return &boolCodec{}
}

View File

@ -6,17 +6,19 @@ import (
"github.com/v2pro/plz/reflect2"
)
func decoderOfOptional(ctx *ctx, typ reflect.Type) ValDecoder {
elemType := typ.Elem()
func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
decoder := decoderOfType(ctx, elemType)
if ctx.prefix == "" && elemType.Kind() == reflect.Ptr {
return &dereferenceDecoder{reflect2.Type2(elemType), decoder}
return &dereferenceDecoder{elemType, decoder}
}
return &OptionalDecoder{reflect2.Type2(elemType), decoder}
return &OptionalDecoder{elemType, decoder}
}
func encoderOfOptional(ctx *ctx, typ reflect.Type) ValEncoder {
elemType := typ.Elem()
func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
elemEncoder := encoderOfType(ctx, elemType)
encoder := &OptionalEncoder{elemEncoder}
return encoder

View File

@ -3,20 +3,19 @@ package jsoniter
import (
"fmt"
"io"
"reflect"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func decoderOfSlice(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := decoderOfType(ctx.append("[sliceElem]"), typ.Elem())
sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType)
func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
return &sliceDecoder{sliceType, decoder}
}
func encoderOfSlice(ctx *ctx, typ reflect.Type) ValEncoder {
encoder := encoderOfType(ctx.append("[sliceElem]"), typ.Elem())
sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType)
func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
return &sliceEncoder{sliceType, encoder}
}
@ -73,7 +72,7 @@ func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
return
}
if c != '[' {
iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c}))
iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c}))
return
}
c = iter.nextToken()
@ -94,7 +93,7 @@ func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
decoder.elemDecoder.Decode(elemPtr, iter)
}
if c != ']' {
iter.ReportError("decode array", "expect ], but found "+string([]byte{c}))
iter.ReportError("decode slice", "expect ], but found "+string([]byte{c}))
return
}
}

View File

@ -3,12 +3,12 @@ package jsoniter
import (
"fmt"
"io"
"reflect"
"strings"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func decoderOfStruct(ctx *ctx, typ reflect.Type) ValDecoder {
func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder {
bindings := map[string]*Binding{}
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
@ -34,7 +34,7 @@ func decoderOfStruct(ctx *ctx, typ reflect.Type) ValDecoder {
return createStructDecoder(ctx, typ, fields)
}
func createStructDecoder(ctx *ctx, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder {
if ctx.disallowUnknownFields {
return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
}
@ -480,7 +480,7 @@ func createStructDecoder(ctx *ctx, typ reflect.Type, fields map[string]*structFi
}
type generalStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fields map[string]*structFieldDecoder
disallowUnknownFields bool
}
@ -535,7 +535,7 @@ func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *It
}
type skipObjectDecoder struct {
typ reflect.Type
typ reflect2.Type
}
func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
@ -548,7 +548,7 @@ func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
type oneFieldStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash int64
fieldDecoder *structFieldDecoder
}
@ -573,7 +573,7 @@ func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
}
type twoFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -603,7 +603,7 @@ func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
type threeFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -637,7 +637,7 @@ func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
type fourFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -675,7 +675,7 @@ func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
type fiveFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -717,7 +717,7 @@ func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
type sixFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -763,7 +763,7 @@ func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
type sevenFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -813,7 +813,7 @@ func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
type eightFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -867,7 +867,7 @@ func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
type nineFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -925,7 +925,7 @@ func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
type tenFieldsStructDecoder struct {
typ reflect.Type
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
@ -987,12 +987,12 @@ func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
type structFieldDecoder struct {
field *reflect.StructField
field reflect2.StructField
fieldDecoder ValDecoder
}
func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := unsafe.Pointer(uintptr(ptr) + decoder.field.Offset)
fieldPtr := decoder.field.UnsafeGet(ptr)
decoder.fieldDecoder.Decode(fieldPtr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name, iter.Error.Error())

View File

@ -8,7 +8,7 @@ import (
"github.com/v2pro/plz/reflect2"
)
func encoderOfStruct(ctx *ctx, typ reflect.Type) ValEncoder {
func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder {
type bindingTo struct {
binding *Binding
toName string
@ -46,7 +46,7 @@ func encoderOfStruct(ctx *ctx, typ reflect.Type) ValEncoder {
return &structEncoder{typ, finalOrderedFields}
}
func createCheckIsEmpty(ctx *ctx, typ reflect.Type) checkIsEmpty {
func createCheckIsEmpty(ctx *ctx, typ reflect2.Type) checkIsEmpty {
kind := typ.Kind()
switch kind {
case reflect.String:
@ -80,7 +80,7 @@ func createCheckIsEmpty(ctx *ctx, typ reflect.Type) checkIsEmpty {
case reflect.Bool:
return &boolCodec{}
case reflect.Interface:
return &dynamicEncoder{reflect2.Type2(typ)}
return &dynamicEncoder{typ}
case reflect.Struct:
return &structEncoder{typ: typ}
case reflect.Array:
@ -97,8 +97,8 @@ func createCheckIsEmpty(ctx *ctx, typ reflect.Type) checkIsEmpty {
}
func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) {
newTagged := new.Field.Tag.Get(cfg.getTagKey()) != ""
oldTagged := old.Field.Tag.Get(cfg.getTagKey()) != ""
newTagged := new.Field.Tag().Get(cfg.getTagKey()) != ""
oldTagged := old.Field.Tag().Get(cfg.getTagKey()) != ""
if newTagged {
if oldTagged {
if len(old.levels) > len(new.levels) {
@ -126,21 +126,21 @@ func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ig
}
type structFieldEncoder struct {
field *reflect.StructField
field reflect2.StructField
fieldEncoder ValEncoder
omitempty bool
}
func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
fieldPtr := unsafe.Pointer(uintptr(ptr) + encoder.field.Offset)
fieldPtr := encoder.field.UnsafeGet(ptr)
encoder.fieldEncoder.Encode(fieldPtr, stream)
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%s: %s", encoder.field.Name, stream.Error.Error())
stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error())
}
}
func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
fieldPtr := unsafe.Pointer(uintptr(ptr) + encoder.field.Offset)
fieldPtr := encoder.field.UnsafeGet(ptr)
return encoder.fieldEncoder.IsEmpty(fieldPtr)
}
@ -149,7 +149,7 @@ func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
if !converted {
return false
}
fieldPtr := unsafe.Pointer(uintptr(ptr) + encoder.field.Offset)
fieldPtr := encoder.field.UnsafeGet(ptr)
return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
}
@ -158,7 +158,7 @@ type IsEmbeddedPtrNil interface {
}
type structEncoder struct {
typ reflect.Type
typ reflect2.Type
fields []structFieldTo
}

View File

@ -11,7 +11,7 @@ import (
)
type testCase struct {
ptr interface{}
ptr interface{}
inputs []string
}

View File

@ -7,4 +7,14 @@ func init() {
[1]*float64{&two},
[2]*float64{},
)
unmarshalCases = append(unmarshalCases, unmarshalCase{
ptr: (*[0]int)(nil),
input: `[1]`,
}, unmarshalCase{
ptr: (*[1]int)(nil),
input: `[2]`,
}, unmarshalCase{
ptr: (*[1]int)(nil),
input: `[]`,
})
}

View File

@ -2,11 +2,11 @@ package test
import (
"testing"
"reflect"
"encoding/json"
"github.com/stretchr/testify/require"
"github.com/json-iterator/go"
"fmt"
"github.com/v2pro/plz/reflect2"
)
type unmarshalCase struct {
@ -42,9 +42,9 @@ func Test_unmarshal(t *testing.T) {
obj1 = testCase.obj()
obj2 = testCase.obj()
} else {
valType := reflect.TypeOf(testCase.ptr).Elem()
obj1 = reflect.New(valType).Interface()
obj2 = reflect.New(valType).Interface()
valType := reflect2.TypeOfPtr(testCase.ptr).Elem()
obj1 = valType.New()
obj2 = valType.New()
}
err1 := json.Unmarshal([]byte(testCase.input), obj1)
should.NoError(err1, "json")
@ -66,7 +66,7 @@ func Test_marshal(t *testing.T) {
for i, testCase := range marshalCases {
var name string
if testCase != nil {
name = fmt.Sprintf("[%v]%v/%s", i, testCase, reflect.TypeOf(testCase).String())
name = fmt.Sprintf("[%v]%v/%s", i, testCase, reflect2.TypeOf(testCase).String())
}
t.Run(name, func(t *testing.T) {
should := require.New(t)