Skip to content

Commit 1c6ff8f

Browse files
json: seen data structure used in codec building supports non-structs
1 parent 2ad374a commit 1c6ff8f

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

json/codec.go

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ func typeid(t reflect.Type) unsafe.Pointer {
113113
}
114114

115115
func constructCachedCodec(t reflect.Type, cache map[unsafe.Pointer]codec) codec {
116-
c := constructCodec(t, map[reflect.Type]*structType{}, t.Kind() == reflect.Ptr)
116+
seen := make(seenMap)
117+
c := constructCodec(t, seen, t.Kind() == reflect.Ptr)
117118

118119
if inlined(t) {
119120
c.encode = constructInlineValueEncodeFunc(c.encode)
@@ -123,7 +124,14 @@ func constructCachedCodec(t reflect.Type, cache map[unsafe.Pointer]codec) codec
123124
return c
124125
}
125126

126-
func constructCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) (c codec) {
127+
type seenType struct {
128+
*codec
129+
*structType
130+
}
131+
132+
type seenMap map[reflect.Type]seenType
133+
134+
func constructCodec(t reflect.Type, seen seenMap, canAddr bool) (c codec) {
127135
switch t {
128136
case nullType, nil:
129137
c = codec{encode: encoder.encodeNull, decode: decoder.decodeNull}
@@ -247,7 +255,7 @@ func constructCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr b
247255
return
248256
}
249257

250-
func constructStringCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) codec {
258+
func constructStringCodec(t reflect.Type, seen seenMap, canAddr bool) codec {
251259
c := constructCodec(t, seen, canAddr)
252260
return codec{
253261
encode: constructStringEncodeFunc(c.encode),
@@ -273,7 +281,7 @@ func constructStringToIntDecodeFunc(t reflect.Type, decode decodeFunc) decodeFun
273281
}
274282
}
275283

276-
func constructArrayCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) codec {
284+
func constructArrayCodec(t reflect.Type, seen seenMap, canAddr bool) codec {
277285
e := t.Elem()
278286
c := constructCodec(e, seen, canAddr)
279287
s := alignedSize(e)
@@ -297,7 +305,7 @@ func constructArrayDecodeFunc(size uintptr, t reflect.Type, decode decodeFunc) d
297305
}
298306
}
299307

300-
func constructSliceCodec(t reflect.Type, seen map[reflect.Type]*structType) codec {
308+
func constructSliceCodec(t reflect.Type, seen seenMap) codec {
301309
e := t.Elem()
302310
s := alignedSize(e)
303311

@@ -364,7 +372,7 @@ func constructSliceDecodeFunc(size uintptr, t reflect.Type, decode decodeFunc) d
364372
}
365373
}
366374

367-
func constructMapCodec(t reflect.Type, seen map[reflect.Type]*structType) codec {
375+
func constructMapCodec(t reflect.Type, seen seenMap) codec {
368376
var sortKeys sortFunc
369377
k := t.Key()
370378
v := t.Elem()
@@ -482,18 +490,19 @@ func constructMapDecodeFunc(t reflect.Type, decodeKey, decodeValue decodeFunc) d
482490
}
483491
}
484492

485-
func constructStructCodec(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) codec {
493+
func constructStructCodec(t reflect.Type, seen seenMap, canAddr bool) codec {
486494
st := constructStructType(t, seen, canAddr)
487495
return codec{
488496
encode: constructStructEncodeFunc(st),
489497
decode: constructStructDecodeFunc(st),
490498
}
491499
}
492500

493-
func constructStructType(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) *structType {
501+
func constructStructType(t reflect.Type, seen seenMap, canAddr bool) *structType {
494502
// Used for preventing infinite recursion on types that have pointers to
495503
// themselves.
496-
st := seen[t]
504+
seenInfo := seen[t]
505+
st := seen[t].structType
497506

498507
if st == nil {
499508
st = &structType{
@@ -503,7 +512,9 @@ func constructStructType(t reflect.Type, seen map[reflect.Type]*structType, canA
503512
typ: t,
504513
}
505514

506-
seen[t] = st
515+
seenInfo.structType = st
516+
seen[t] = seenInfo
517+
507518
st.fields = appendStructFields(st.fields, t, 0, seen, canAddr)
508519

509520
for i := range st.fields {
@@ -563,7 +574,7 @@ func constructEmbeddedStructPointerDecodeFunc(t reflect.Type, unexported bool, o
563574
}
564575
}
565576

566-
func appendStructFields(fields []structField, t reflect.Type, offset uintptr, seen map[reflect.Type]*structType, canAddr bool) []structField {
577+
func appendStructFields(fields []structField, t reflect.Type, offset uintptr, seen seenMap, canAddr bool) []structField {
567578
type embeddedField struct {
568579
index int
569580
offset uintptr
@@ -764,7 +775,7 @@ func encodeKeyFragment(s string, flags AppendFlags) string {
764775
return *(*string)(unsafe.Pointer(&b))
765776
}
766777

767-
func constructPointerCodec(t reflect.Type, seen map[reflect.Type]*structType) codec {
778+
func constructPointerCodec(t reflect.Type, seen seenMap) codec {
768779
e := t.Elem()
769780
c := constructCodec(e, seen, true)
770781
return codec{

0 commit comments

Comments
 (0)