Quellcode durchsuchen

use reflect2 to replace reflect

Tao Wen vor 7 Jahren
Ursprung
Commit
99fc16a363

+ 6 - 6
any.go

@@ -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

+ 7 - 7
config.go

@@ -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() {

+ 4 - 5
config_with_sync_map.go

@@ -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)

+ 8 - 8
config_without_sync_map.go

@@ -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()

+ 2 - 1
extra/fuzzy_decoder.go

@@ -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}
 	}

+ 2 - 2
extra/naming_strategy.go

@@ -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())}
 	}
 }
 

+ 3 - 3
extra/privat_fields.go

@@ -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()}
 		}
 	}
 }

+ 24 - 27
reflect.go

@@ -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:

+ 44 - 22
reflect_array.go

@@ -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
+	}
 }

+ 62 - 71
reflect_extension.go

@@ -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 {

+ 5 - 5
reflect_json_number.go

@@ -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{}
 	}

+ 5 - 5
reflect_json_raw_message.go

@@ -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{}
 	}

+ 24 - 23
reflect_map.go

@@ -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)}

+ 17 - 18
reflect_marshaler.go

@@ -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}

+ 34 - 34
reflect_native.go

@@ -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{}
 	}

+ 8 - 6
reflect_optional.go

@@ -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

+ 8 - 9
reflect_slice.go

@@ -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
 	}
 }

+ 17 - 17
reflect_struct_decoder.go

@@ -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())

+ 11 - 11
reflect_struct_encoder.go

@@ -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
 }
 

+ 1 - 1
skip_tests/skip_test.go

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

+ 10 - 0
value_tests/array_test.go

@@ -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: `[]`,
+	})
 }

+ 5 - 5
value_tests/value_test.go

@@ -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)