1
0
mirror of https://github.com/json-iterator/go.git synced 2025-06-06 22:36:25 +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 { if isAny {
return asAny return asAny
} }
typ := reflect.TypeOf(val) typ := reflect2.TypeOf(val)
switch typ.Kind() { switch typ.Kind() {
case reflect.Slice: case reflect.Slice:
return wrapArray(val) return wrapArray(val)
@ -245,27 +245,27 @@ func locatePath(iter *Iterator, path []interface{}) Any {
return iter.readAny() 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 { if typ == anyType {
return &directAnyCodec{} return &directAnyCodec{}
} }
if typ.Implements(anyType) { if typ.Implements(anyType) {
return &anyCodec{ return &anyCodec{
valType: reflect2.Type2(typ), valType: typ,
} }
} }
return nil return nil
} }
func createEncoderOfAny(ctx *ctx, typ reflect.Type) ValEncoder { func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ == anyType { if typ == anyType {
return &directAnyCodec{} return &directAnyCodec{}
} }
if typ.Implements(anyType) { if typ.Implements(anyType) {
return &anyCodec{ return &anyCodec{
valType: reflect2.Type2(typ), valType: typ,
} }
} }
return nil return nil

View File

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

View File

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

View File

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

View File

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

View File

@ -17,8 +17,8 @@ type namingStrategyExtension struct {
func (extension *namingStrategyExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) { func (extension *namingStrategyExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) {
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
binding.ToNames = []string{extension.translate(binding.Field.Name)} binding.ToNames = []string{extension.translate(binding.Field.Name())}
binding.FromNames = []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) { func (extension *privateFieldsExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) {
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
isPrivate := unicode.IsLower(rune(binding.Field.Name[0])) isPrivate := unicode.IsLower(rune(binding.Field.Name()[0]))
if isPrivate { if isPrivate {
binding.FromNames = []string{binding.Field.Name} binding.FromNames = []string{binding.Field.Name()}
binding.ToNames = []string{binding.Field.Name} binding.ToNames = []string{binding.Field.Name()}
} }
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,4 +7,14 @@ func init() {
[1]*float64{&two}, [1]*float64{&two},
[2]*float64{}, [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 ( import (
"testing" "testing"
"reflect"
"encoding/json" "encoding/json"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/json-iterator/go" "github.com/json-iterator/go"
"fmt" "fmt"
"github.com/v2pro/plz/reflect2"
) )
type unmarshalCase struct { type unmarshalCase struct {
@ -42,9 +42,9 @@ func Test_unmarshal(t *testing.T) {
obj1 = testCase.obj() obj1 = testCase.obj()
obj2 = testCase.obj() obj2 = testCase.obj()
} else { } else {
valType := reflect.TypeOf(testCase.ptr).Elem() valType := reflect2.TypeOfPtr(testCase.ptr).Elem()
obj1 = reflect.New(valType).Interface() obj1 = valType.New()
obj2 = reflect.New(valType).Interface() obj2 = valType.New()
} }
err1 := json.Unmarshal([]byte(testCase.input), obj1) err1 := json.Unmarshal([]byte(testCase.input), obj1)
should.NoError(err1, "json") should.NoError(err1, "json")
@ -66,7 +66,7 @@ func Test_marshal(t *testing.T) {
for i, testCase := range marshalCases { for i, testCase := range marshalCases {
var name string var name string
if testCase != nil { 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) { t.Run(name, func(t *testing.T) {
should := require.New(t) should := require.New(t)