1
0
mirror of https://github.com/json-iterator/go.git synced 2025-08-13 22:12:45 +02:00

support recursive struct

This commit is contained in:
Tao Wen
2018-02-21 17:59:41 +08:00
parent 2fcbb23d96
commit a3866383f5
14 changed files with 221 additions and 151 deletions

4
any.go
View File

@@ -247,7 +247,7 @@ func locatePath(iter *Iterator, path []interface{}) Any {
var anyType = reflect.TypeOf((*Any)(nil)).Elem() var anyType = reflect.TypeOf((*Any)(nil)).Elem()
func createDecoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func createDecoderOfAny(ctx *ctx, typ reflect.Type) ValDecoder {
if typ == anyType { if typ == anyType {
return &directAnyCodec{} return &directAnyCodec{}
} }
@@ -259,7 +259,7 @@ func createDecoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValD
return nil return nil
} }
func createEncoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func createEncoderOfAny(ctx *ctx, typ reflect.Type) ValEncoder {
if typ == anyType { if typ == anyType {
return &directAnyCodec{} return &directAnyCodec{}
} }

View File

@@ -33,6 +33,22 @@ type checkIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool IsEmpty(ptr unsafe.Pointer) bool
} }
type ctx struct {
*frozenConfig
prefix string
encoders map[reflect.Type]ValEncoder
decoders map[reflect.Type]ValDecoder
}
func (b *ctx) append(prefix string) *ctx {
return &ctx{
frozenConfig: b.frozenConfig,
prefix: b.prefix + " " + prefix,
encoders: b.encoders,
decoders: b.decoders,
}
}
// 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 := reflect.TypeOf(obj)
@@ -66,44 +82,62 @@ func (cfg *frozenConfig) DecoderOf(typ reflect.Type) ValDecoder {
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
decoder = decoderOfType(cfg, "", typ.Elem()) ctx := &ctx{
frozenConfig: cfg,
prefix: "",
decoders: map[reflect.Type]ValDecoder{},
encoders: map[reflect.Type]ValEncoder{},
}
decoder = decoderOfType(ctx, typ.Elem())
cfg.addDecoderToCache(cacheKey, decoder) cfg.addDecoderToCache(cacheKey, decoder)
return decoder return decoder
} }
func decoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func decoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := getTypeDecoderFromExtension(cfg, typ) decoder := getTypeDecoderFromExtension(ctx, typ)
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
decoder = createDecoderOfType(cfg, prefix, typ) decoder = createDecoderOfType(ctx, typ)
for _, extension := range extensions { for _, extension := range extensions {
decoder = extension.DecorateDecoder(typ, decoder) decoder = extension.DecorateDecoder(typ, decoder)
} }
for _, extension := range cfg.extensions { for _, extension := range ctx.extensions {
decoder = extension.DecorateDecoder(typ, decoder) decoder = extension.DecorateDecoder(typ, decoder)
} }
return decoder return decoder
} }
func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := createDecoderOfJsonRawMessage(cfg, prefix, typ) decoder := ctx.decoders[typ]
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
decoder = createDecoderOfJsonNumber(cfg, prefix, typ) placeholder := &placeholderDecoder{}
ctx.decoders[typ] = placeholder
decoder = _createDecoderOfType(ctx, typ)
placeholder.decoder = decoder
return decoder
}
func _createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := createDecoderOfJsonRawMessage(ctx, typ)
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
decoder = createDecoderOfMarshaler(cfg, prefix, typ) decoder = createDecoderOfJsonNumber(ctx, typ)
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
decoder = createDecoderOfAny(cfg, prefix, typ) decoder = createDecoderOfMarshaler(ctx, typ)
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
decoder = createDecoderOfNative(cfg, prefix, typ) decoder = createDecoderOfAny(ctx, typ)
if decoder != nil {
return decoder
}
decoder = createDecoderOfNative(ctx, typ)
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
@@ -115,17 +149,17 @@ func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val
} }
return &efaceDecoder{} return &efaceDecoder{}
case reflect.Struct: case reflect.Struct:
return decoderOfStruct(cfg, prefix, typ) return decoderOfStruct(ctx, typ)
case reflect.Array: case reflect.Array:
return decoderOfArray(cfg, prefix, typ) return decoderOfArray(ctx, typ)
case reflect.Slice: case reflect.Slice:
return decoderOfSlice(cfg, prefix, typ) return decoderOfSlice(ctx, typ)
case reflect.Map: case reflect.Map:
return decoderOfMap(cfg, prefix, typ) return decoderOfMap(ctx, typ)
case reflect.Ptr: case reflect.Ptr:
return decoderOfOptional(cfg, prefix, typ) return decoderOfOptional(ctx, typ)
default: default:
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())} return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
} }
} }
@@ -135,7 +169,13 @@ func (cfg *frozenConfig) EncoderOf(typ reflect.Type) ValEncoder {
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
encoder = encoderOfType(cfg, "", typ) ctx := &ctx{
frozenConfig: cfg,
prefix: "",
decoders: map[reflect.Type]ValDecoder{},
encoders: map[reflect.Type]ValEncoder{},
}
encoder = encoderOfType(ctx, typ)
if shouldFixOnePtr(typ) { if shouldFixOnePtr(typ) {
encoder = &onePtrEncoder{encoder} encoder = &onePtrEncoder{encoder}
} }
@@ -159,39 +199,50 @@ func shouldFixOnePtr(typ reflect.Type) bool {
return reflect2.Type2(typ).LikePtr() return reflect2.Type2(typ).LikePtr()
} }
func encoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func encoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
encoder := getTypeEncoderFromExtension(cfg, typ) encoder := getTypeEncoderFromExtension(ctx, typ)
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
encoder = createEncoderOfType(cfg, prefix, typ) encoder = createEncoderOfType(ctx, typ)
for _, extension := range extensions { for _, extension := range extensions {
encoder = extension.DecorateEncoder(typ, encoder) encoder = extension.DecorateEncoder(typ, encoder)
} }
for _, extension := range cfg.extensions { for _, extension := range ctx.extensions {
encoder = extension.DecorateEncoder(typ, encoder) encoder = extension.DecorateEncoder(typ, encoder)
} }
return encoder return encoder
} }
func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
encoder := createEncoderOfJsonRawMessage(cfg, prefix, typ) encoder := ctx.encoders[typ]
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
encoder = createEncoderOfJsonNumber(cfg, prefix, typ) placeholder := &placeholderEncoder{}
ctx.encoders[typ] = placeholder
encoder = _createEncoderOfType(ctx, typ)
placeholder.encoder = encoder
return encoder
}
func _createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
encoder := createEncoderOfJsonRawMessage(ctx, typ)
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
encoder = createEncoderOfMarshaler(cfg, prefix, typ) encoder = createEncoderOfJsonNumber(ctx, typ)
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
encoder = createEncoderOfAny(cfg, prefix, typ) encoder = createEncoderOfMarshaler(ctx, typ)
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
encoder = createEncoderOfNative(cfg, prefix, typ) encoder = createEncoderOfAny(ctx, typ)
if encoder != nil {
return encoder
}
encoder = createEncoderOfNative(ctx, typ)
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
@@ -200,17 +251,17 @@ func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val
case reflect.Interface: case reflect.Interface:
return &dynamicEncoder{reflect2.Type2(typ)} return &dynamicEncoder{reflect2.Type2(typ)}
case reflect.Struct: case reflect.Struct:
return encoderOfStruct(cfg, prefix, typ) return encoderOfStruct(ctx, typ)
case reflect.Array: case reflect.Array:
return encoderOfArray(cfg, prefix, typ) return encoderOfArray(ctx, typ)
case reflect.Slice: case reflect.Slice:
return encoderOfSlice(cfg, prefix, typ) return encoderOfSlice(ctx, typ)
case reflect.Map: case reflect.Map:
return encoderOfMap(cfg, prefix, typ) return encoderOfMap(ctx, typ)
case reflect.Ptr: case reflect.Ptr:
return encoderOfOptional(cfg, prefix, typ) return encoderOfOptional(ctx, typ)
default: default:
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())} return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
} }
} }
@@ -243,3 +294,23 @@ func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool { func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false return false
} }
type placeholderDecoder struct {
decoder ValDecoder
}
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.decoder.Decode(ptr, iter)
}
type placeholderEncoder struct {
encoder ValEncoder
}
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.encoder.Encode(ptr, stream)
}
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(ptr)
}

View File

@@ -7,16 +7,16 @@ import (
"unsafe" "unsafe"
) )
func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func decoderOfArray(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := decoderOfType(cfg, prefix+"[array]->", typ.Elem()) decoder := decoderOfType(ctx.append("[arrayElem]"), typ.Elem())
return &arrayDecoder{typ, typ.Elem(), decoder} return &arrayDecoder{typ, typ.Elem(), decoder}
} }
func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func encoderOfArray(ctx *ctx, typ reflect.Type) ValEncoder {
if typ.Len() == 0 { if typ.Len() == 0 {
return emptyArrayEncoder{} return emptyArrayEncoder{}
} }
encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem()) encoder := encoderOfType(ctx.append("[arrayElem]"), typ.Elem())
return &arrayEncoder{typ, typ.Elem(), encoder} return &arrayEncoder{typ, typ.Elem(), encoder}
} }

View File

@@ -208,26 +208,26 @@ func RegisterExtension(extension Extension) {
extensions = append(extensions, extension) extensions = append(extensions, extension)
} }
func getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecoder { func getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := _getTypeDecoderFromExtension(cfg, typ) decoder := _getTypeDecoderFromExtension(ctx, typ)
if decoder != nil { if decoder != nil {
for _, extension := range extensions { for _, extension := range extensions {
decoder = extension.DecorateDecoder(typ, decoder) decoder = extension.DecorateDecoder(typ, decoder)
} }
for _, extension := range cfg.extensions { for _, extension := range ctx.extensions {
decoder = extension.DecorateDecoder(typ, decoder) decoder = extension.DecorateDecoder(typ, decoder)
} }
} }
return decoder return decoder
} }
func _getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecoder { func _getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
for _, extension := range extensions { for _, extension := range extensions {
decoder := extension.CreateDecoder(typ) decoder := extension.CreateDecoder(typ)
if decoder != nil { if decoder != nil {
return decoder return decoder
} }
} }
for _, extension := range cfg.extensions { for _, extension := range ctx.extensions {
decoder := extension.CreateDecoder(typ) decoder := extension.CreateDecoder(typ)
if decoder != nil { if decoder != nil {
return decoder return decoder
@@ -247,27 +247,27 @@ func _getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecode
return nil return nil
} }
func getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncoder { func getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
encoder := _getTypeEncoderFromExtension(cfg, typ) encoder := _getTypeEncoderFromExtension(ctx, typ)
if encoder != nil { if encoder != nil {
for _, extension := range extensions { for _, extension := range extensions {
encoder = extension.DecorateEncoder(typ, encoder) encoder = extension.DecorateEncoder(typ, encoder)
} }
for _, extension := range cfg.extensions { for _, extension := range ctx.extensions {
encoder = extension.DecorateEncoder(typ, encoder) encoder = extension.DecorateEncoder(typ, encoder)
} }
} }
return encoder return encoder
} }
func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncoder { func _getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
for _, extension := range extensions { for _, extension := range extensions {
encoder := extension.CreateEncoder(typ) encoder := extension.CreateEncoder(typ)
if encoder != nil { if encoder != nil {
return encoder return encoder
} }
} }
for _, extension := range cfg.extensions { for _, extension := range ctx.extensions {
encoder := extension.CreateEncoder(typ) encoder := extension.CreateEncoder(typ)
if encoder != nil { if encoder != nil {
return encoder return encoder
@@ -287,13 +287,13 @@ func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncode
return nil return nil
} }
func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructDescriptor { func describeStruct(ctx *ctx, typ reflect.Type) *StructDescriptor {
embeddedBindings := []*Binding{} embeddedBindings := []*Binding{}
bindings := []*Binding{} bindings := []*Binding{}
for i := 0; i < typ.NumField(); i++ { for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i) field := typ.Field(i)
tag, hastag := field.Tag.Lookup(cfg.getTagKey()) tag, hastag := field.Tag.Lookup(ctx.getTagKey())
if cfg.onlyTaggedField && !hastag { if ctx.onlyTaggedField && !hastag {
continue continue
} }
tagParts := strings.Split(tag, ",") tagParts := strings.Split(tag, ",")
@@ -302,7 +302,7 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
} }
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(cfg, prefix, 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
@@ -312,7 +312,7 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
} }
continue continue
} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct { } else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
structDescriptor := describeStruct(cfg, prefix, field.Type.Elem()) structDescriptor := describeStruct(ctx, field.Type.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
@@ -329,11 +329,11 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name) fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
decoder := fieldDecoders[fieldCacheKey] decoder := fieldDecoders[fieldCacheKey]
if decoder == nil { if decoder == nil {
decoder = decoderOfType(cfg, prefix+typ.String()+"."+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(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type) encoder = encoderOfType(ctx.append(field.Name), field.Type)
} }
binding := &Binding{ binding := &Binding{
Field: &field, Field: &field,
@@ -345,9 +345,9 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
binding.levels = []int{i} binding.levels = []int{i}
bindings = append(bindings, binding) bindings = append(bindings, binding)
} }
return createStructDescriptor(cfg, typ, bindings, embeddedBindings) return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
} }
func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { func createStructDescriptor(ctx *ctx, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
structDescriptor := &StructDescriptor{ structDescriptor := &StructDescriptor{
Type: typ, Type: typ,
Fields: bindings, Fields: bindings,
@@ -355,10 +355,10 @@ func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Bin
for _, extension := range extensions { for _, extension := range extensions {
extension.UpdateStructDescriptor(structDescriptor) extension.UpdateStructDescriptor(structDescriptor)
} }
for _, extension := range cfg.extensions { for _, extension := range ctx.extensions {
extension.UpdateStructDescriptor(structDescriptor) extension.UpdateStructDescriptor(structDescriptor)
} }
processTags(structDescriptor, cfg) processTags(structDescriptor, ctx.frozenConfig)
// merge normal & embedded bindings & sort with original order // merge normal & embedded bindings & sort with original order
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...)) allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
sort.Sort(allBindings) sort.Sort(allBindings)

View File

@@ -35,7 +35,7 @@ func CastJsonNumber(val interface{}) (string, bool) {
var jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem() var jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem()
var jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem() var jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem()
func createDecoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func createDecoderOfJsonNumber(ctx *ctx, typ reflect.Type) ValDecoder {
if typ.AssignableTo(jsonNumberType) { if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{} return &jsonNumberCodec{}
} }
@@ -45,7 +45,7 @@ func createDecoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Typ
return nil return nil
} }
func createEncoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func createEncoderOfJsonNumber(ctx *ctx, typ reflect.Type) ValEncoder {
if typ.AssignableTo(jsonNumberType) { if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{} return &jsonNumberCodec{}
} }

View File

@@ -9,7 +9,7 @@ import (
var jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem() var jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
var jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem() var jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem()
func createEncoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect.Type) ValEncoder {
if typ == jsonRawMessageType { if typ == jsonRawMessageType {
return &jsonRawMessageCodec{} return &jsonRawMessageCodec{}
} }
@@ -19,7 +19,7 @@ func createEncoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect
return nil return nil
} }
func createDecoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect.Type) ValDecoder {
if typ == jsonRawMessageType { if typ == jsonRawMessageType {
return &jsonRawMessageCodec{} return &jsonRawMessageCodec{}
} }

View File

@@ -8,9 +8,9 @@ import (
"fmt" "fmt"
) )
func decoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func decoderOfMap(ctx *ctx, typ reflect.Type) ValDecoder {
keyDecoder := decoderOfMapKey(cfg, prefix+" [mapKey]", typ.Key()) keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), typ.Key())
elemDecoder := decoderOfType(cfg, prefix+" [mapElem]", typ.Elem()) elemDecoder := decoderOfType(ctx.append("[mapElem]"), typ.Elem())
mapType := reflect2.Type2(typ).(*reflect2.UnsafeMapType) mapType := reflect2.Type2(typ).(*reflect2.UnsafeMapType)
return &mapDecoder{ return &mapDecoder{
mapType: mapType, mapType: mapType,
@@ -21,25 +21,25 @@ func decoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder
} }
} }
func encoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func encoderOfMap(ctx *ctx, typ reflect.Type) ValEncoder {
if cfg.sortMapKeys { if ctx.sortMapKeys {
return &sortKeysMapEncoder{ return &sortKeysMapEncoder{
mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType), mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType),
keyEncoder: encoderOfMapKey(cfg, prefix+" [mapKey]", typ.Key()), keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), typ.Key()),
elemEncoder: encoderOfType(cfg, prefix+" [mapElem]", typ.Elem()), elemEncoder: encoderOfType(ctx.append("[mapElem]"), typ.Elem()),
} }
} }
return &mapEncoder{ return &mapEncoder{
mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType), mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType),
keyEncoder: encoderOfMapKey(cfg, prefix+" [mapKey]", typ.Key()), keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), typ.Key()),
elemEncoder: encoderOfType(cfg, prefix+" [mapElem]", typ.Elem()), elemEncoder: encoderOfType(ctx.append("[mapElem]"), typ.Elem()),
} }
} }
func decoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func decoderOfMapKey(ctx *ctx, typ reflect.Type) ValDecoder {
switch typ.Kind() { switch typ.Kind() {
case reflect.String: case reflect.String:
return decoderOfType(cfg, prefix, reflect2.DefaultTypeOfKind(reflect.String).Type1()) return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String).Type1())
case reflect.Bool, case reflect.Bool,
reflect.Uint8, reflect.Int8, reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16, reflect.Uint16, reflect.Int16,
@@ -49,7 +49,7 @@ func decoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
reflect.Float32, reflect.Float64, reflect.Float32, reflect.Float64,
reflect.Uintptr: reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1() typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1()
return &numericMapKeyDecoder{decoderOfType(cfg, prefix, typ)} return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
default: default:
ptrType := reflect.PtrTo(typ) ptrType := reflect.PtrTo(typ)
if ptrType.Implements(textMarshalerType) { if ptrType.Implements(textMarshalerType) {
@@ -68,10 +68,10 @@ func decoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
} }
} }
func encoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func encoderOfMapKey(ctx *ctx, typ reflect.Type) ValEncoder {
switch typ.Kind() { switch typ.Kind() {
case reflect.String: case reflect.String:
return encoderOfType(cfg, prefix, reflect2.DefaultTypeOfKind(reflect.String).Type1()) return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String).Type1())
case reflect.Bool, case reflect.Bool,
reflect.Uint8, reflect.Int8, reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16, reflect.Uint16, reflect.Int16,
@@ -81,17 +81,17 @@ func encoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
reflect.Float32, reflect.Float64, reflect.Float32, reflect.Float64,
reflect.Uintptr: reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1() typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1()
return &numericMapKeyEncoder{encoderOfType(cfg, prefix, typ)} return &numericMapKeyEncoder{encoderOfType(ctx, typ)}
default: default:
if typ == textMarshalerType { if typ == textMarshalerType {
return &directTextMarshalerEncoder{ return &directTextMarshalerEncoder{
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")), stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
} }
} }
if typ.Implements(textMarshalerType) { if typ.Implements(textMarshalerType) {
return &textMarshalerEncoder{ return &textMarshalerEncoder{
valType: reflect2.Type2(typ), valType: reflect2.Type2(typ),
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")), stringEncoder: ctx.EncoderOf(reflect.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

@@ -13,7 +13,7 @@ var unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
func createDecoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func createDecoderOfMarshaler(ctx *ctx, typ reflect.Type) ValDecoder {
ptrType := reflect.PtrTo(typ) ptrType := reflect.PtrTo(typ)
if ptrType.Implements(unmarshalerType) { if ptrType.Implements(unmarshalerType) {
return &referenceDecoder{ return &referenceDecoder{
@@ -28,16 +28,16 @@ func createDecoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type
return nil return nil
} }
func createEncoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func createEncoderOfMarshaler(ctx *ctx, typ reflect.Type) ValEncoder {
if typ == marshalerType { if typ == marshalerType {
checkIsEmpty := createCheckIsEmpty(cfg, typ) checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &directMarshalerEncoder{ var encoder ValEncoder = &directMarshalerEncoder{
checkIsEmpty: checkIsEmpty, checkIsEmpty: checkIsEmpty,
} }
return encoder return encoder
} }
if typ.Implements(marshalerType) { if typ.Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(cfg, typ) checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &marshalerEncoder{ var encoder ValEncoder = &marshalerEncoder{
valType: reflect2.Type2(typ), valType: reflect2.Type2(typ),
checkIsEmpty: checkIsEmpty, checkIsEmpty: checkIsEmpty,
@@ -45,8 +45,8 @@ func createEncoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type
return encoder return encoder
} }
ptrType := reflect.PtrTo(typ) ptrType := reflect.PtrTo(typ)
if prefix != "" && ptrType.Implements(marshalerType) { if ctx.prefix != "" && ptrType.Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(cfg, ptrType) checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
var encoder ValEncoder = &marshalerEncoder{ var encoder ValEncoder = &marshalerEncoder{
valType: reflect2.Type2(ptrType), valType: reflect2.Type2(ptrType),
checkIsEmpty: checkIsEmpty, checkIsEmpty: checkIsEmpty,
@@ -54,28 +54,28 @@ func createEncoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type
return &referenceEncoder{encoder} return &referenceEncoder{encoder}
} }
if typ == textMarshalerType { if typ == textMarshalerType {
checkIsEmpty := createCheckIsEmpty(cfg, typ) checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &directTextMarshalerEncoder{ var encoder ValEncoder = &directTextMarshalerEncoder{
checkIsEmpty: checkIsEmpty, checkIsEmpty: checkIsEmpty,
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")), stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
} }
return encoder return encoder
} }
if typ.Implements(textMarshalerType) { if typ.Implements(textMarshalerType) {
checkIsEmpty := createCheckIsEmpty(cfg, typ) checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &textMarshalerEncoder{ var encoder ValEncoder = &textMarshalerEncoder{
valType: reflect2.Type2(typ), valType: reflect2.Type2(typ),
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")), stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
checkIsEmpty: checkIsEmpty, checkIsEmpty: checkIsEmpty,
} }
return encoder return encoder
} }
// if prefix is empty, the type is the root type // if prefix is empty, the type is the root type
if prefix != "" && ptrType.Implements(textMarshalerType) { if ctx.prefix != "" && ptrType.Implements(textMarshalerType) {
checkIsEmpty := createCheckIsEmpty(cfg, ptrType) checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
var encoder ValEncoder = &textMarshalerEncoder{ var encoder ValEncoder = &textMarshalerEncoder{
valType: reflect2.Type2(ptrType), valType: reflect2.Type2(ptrType),
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")), stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
checkIsEmpty: checkIsEmpty, checkIsEmpty: checkIsEmpty,
} }
return &referenceEncoder{encoder} return &referenceEncoder{encoder}

View File

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

View File

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

View File

@@ -8,14 +8,14 @@ import (
"github.com/v2pro/plz/reflect2" "github.com/v2pro/plz/reflect2"
) )
func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func decoderOfSlice(ctx *ctx, typ reflect.Type) ValDecoder {
decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem()) decoder := decoderOfType(ctx.append("[sliceElem]"), typ.Elem())
sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType) sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType)
return &sliceDecoder{sliceType, decoder} return &sliceDecoder{sliceType, decoder}
} }
func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func encoderOfSlice(ctx *ctx, typ reflect.Type) ValEncoder {
encoder := encoderOfType(cfg, prefix+"[slice]->", typ.Elem()) encoder := encoderOfType(ctx.append("[sliceElem]"), typ.Elem())
sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType) sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType)
return &sliceEncoder{sliceType, encoder} return &sliceEncoder{sliceType, encoder}
} }

View File

@@ -8,9 +8,9 @@ import (
"unsafe" "unsafe"
) )
func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { func decoderOfStruct(ctx *ctx, typ reflect.Type) ValDecoder {
bindings := map[string]*Binding{} bindings := map[string]*Binding{}
structDescriptor := describeStruct(cfg, prefix, typ) structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames { for _, fromName := range binding.FromNames {
old := bindings[fromName] old := bindings[fromName]
@@ -18,7 +18,7 @@ func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
bindings[fromName] = binding bindings[fromName] = binding
continue continue
} }
ignoreOld, ignoreNew := resolveConflictBinding(cfg, old, binding) ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding)
if ignoreOld { if ignoreOld {
delete(bindings, fromName) delete(bindings, fromName)
} }
@@ -31,11 +31,11 @@ func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
for k, binding := range bindings { for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder) fields[k] = binding.Decoder.(*structFieldDecoder)
} }
return createStructDecoder(cfg, typ, fields) return createStructDecoder(ctx, typ, fields)
} }
func createStructDecoder(cfg *frozenConfig, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder { func createStructDecoder(ctx *ctx, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
if cfg.disallowUnknownFields { if ctx.disallowUnknownFields {
return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true} return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
} }
knownHash := map[int64]struct{}{ knownHash := map[int64]struct{}{

View File

@@ -8,14 +8,14 @@ import (
"github.com/v2pro/plz/reflect2" "github.com/v2pro/plz/reflect2"
) )
func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { func encoderOfStruct(ctx *ctx, typ reflect.Type) ValEncoder {
type bindingTo struct { type bindingTo struct {
binding *Binding binding *Binding
toName string toName string
ignored bool ignored bool
} }
orderedBindings := []*bindingTo{} orderedBindings := []*bindingTo{}
structDescriptor := describeStruct(cfg, prefix, typ) structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames { for _, toName := range binding.ToNames {
new := &bindingTo{ new := &bindingTo{
@@ -26,7 +26,7 @@ func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
if old.toName != toName { if old.toName != toName {
continue continue
} }
old.ignored, new.ignored = resolveConflictBinding(cfg, old.binding, new.binding) old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding)
} }
orderedBindings = append(orderedBindings, new) orderedBindings = append(orderedBindings, new)
} }
@@ -46,7 +46,7 @@ func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
return &structEncoder{typ, finalOrderedFields} return &structEncoder{typ, finalOrderedFields}
} }
func createCheckIsEmpty(cfg *frozenConfig, typ reflect.Type) checkIsEmpty { func createCheckIsEmpty(ctx *ctx, typ reflect.Type) checkIsEmpty {
kind := typ.Kind() kind := typ.Kind()
switch kind { switch kind {
case reflect.String: case reflect.String:
@@ -88,7 +88,7 @@ func createCheckIsEmpty(cfg *frozenConfig, typ reflect.Type) checkIsEmpty {
case reflect.Slice: case reflect.Slice:
return &sliceEncoder{} return &sliceEncoder{}
case reflect.Map: case reflect.Map:
return encoderOfMap(cfg, "", typ) return encoderOfMap(ctx, typ)
case reflect.Ptr: case reflect.Ptr:
return &OptionalEncoder{} return &OptionalEncoder{}
default: default:

View File

@@ -120,8 +120,7 @@ func init() {
Field1 string `json:"field-1,omitempty"` Field1 string `json:"field-1,omitempty"`
Field2 func() `json:"-"` Field2 func() `json:"-"`
}{}, }{},
// TODO: fix me structRecursive{},
//structRecursive{},
struct { struct {
*CacheItem *CacheItem