@@ -59,7 +59,7 @@ func typeid(t reflect.Type) unsafe.Pointer {
59
59
}
60
60
61
61
func constructCachedCodec (t reflect.Type , cache map [unsafe.Pointer ]codec ) codec {
62
- c := constructCodec (t , map [reflect.Type ]* structType {})
62
+ c := constructCodec (t , map [reflect.Type ]* structType {}, t . Kind () == reflect . Ptr )
63
63
64
64
if inlined (t ) {
65
65
c .encode = constructInlineValueEncodeFunc (c .encode )
@@ -69,7 +69,7 @@ func constructCachedCodec(t reflect.Type, cache map[unsafe.Pointer]codec) codec
69
69
return c
70
70
}
71
71
72
- func constructCodec (t reflect.Type , seen map [reflect.Type ]* structType ) (c codec ) {
72
+ func constructCodec (t reflect.Type , seen map [reflect.Type ]* structType , canAddr bool ) (c codec ) {
73
73
switch t {
74
74
case nullType , nil :
75
75
c = codec {encode : encoder .encodeNull , decode : decoder .decodeNull }
@@ -159,7 +159,7 @@ func constructCodec(t reflect.Type, seen map[reflect.Type]*structType) (c codec)
159
159
c = codec {encode : encoder .encodeInterface , decode : constructNonEmptyInterfaceDecoderFunc (t )}
160
160
161
161
case reflect .Array :
162
- c = constructArrayCodec (t , seen )
162
+ c = constructArrayCodec (t , seen , canAddr )
163
163
164
164
case reflect .Slice :
165
165
c = constructSliceCodec (t , seen )
@@ -168,7 +168,7 @@ func constructCodec(t reflect.Type, seen map[reflect.Type]*structType) (c codec)
168
168
c = constructMapCodec (t , seen )
169
169
170
170
case reflect .Struct :
171
- c = constructStructCodec (t , seen )
171
+ c = constructStructCodec (t , seen , canAddr )
172
172
173
173
case reflect .Ptr :
174
174
c = constructPointerCodec (t , seen )
@@ -179,27 +179,34 @@ func constructCodec(t reflect.Type, seen map[reflect.Type]*structType) (c codec)
179
179
180
180
p := reflect .PtrTo (t )
181
181
182
+ if canAddr {
183
+ switch {
184
+ case p .Implements (jsonMarshalerType ):
185
+ c .encode = constructJSONMarshalerEncodeFunc (t , true )
186
+ case p .Implements (textMarshalerType ):
187
+ c .encode = constructTextMarshalerEncodeFunc (t , true )
188
+ }
189
+ }
190
+
182
191
switch {
183
192
case t .Implements (jsonMarshalerType ):
184
193
c .encode = constructJSONMarshalerEncodeFunc (t , false )
185
-
186
194
case t .Implements (textMarshalerType ):
187
195
c .encode = constructTextMarshalerEncodeFunc (t , false )
188
196
}
189
197
190
198
switch {
191
199
case p .Implements (jsonUnmarshalerType ):
192
200
c .decode = constructJSONUnmarshalerDecodeFunc (t , true )
193
-
194
201
case p .Implements (textUnmarshalerType ):
195
202
c .decode = constructTextUnmarshalerDecodeFunc (t , true )
196
203
}
197
204
198
205
return
199
206
}
200
207
201
- func constructStringCodec (t reflect.Type , seen map [reflect.Type ]* structType ) codec {
202
- c := constructCodec (t , seen )
208
+ func constructStringCodec (t reflect.Type , seen map [reflect.Type ]* structType , canAddr bool ) codec {
209
+ c := constructCodec (t , seen , canAddr )
203
210
return codec {
204
211
encode : constructStringEncodeFunc (c .encode ),
205
212
decode : constructStringDecodeFunc (c .decode ),
@@ -224,9 +231,9 @@ func constructStringToIntDecodeFunc(t reflect.Type, decode decodeFunc) decodeFun
224
231
}
225
232
}
226
233
227
- func constructArrayCodec (t reflect.Type , seen map [reflect.Type ]* structType ) codec {
234
+ func constructArrayCodec (t reflect.Type , seen map [reflect.Type ]* structType , canAddr bool ) codec {
228
235
e := t .Elem ()
229
- c := constructCodec (e , seen )
236
+ c := constructCodec (e , seen , canAddr )
230
237
s := alignedSize (e )
231
238
return codec {
232
239
encode : constructArrayEncodeFunc (s , t , c .encode ),
@@ -253,12 +260,12 @@ func constructSliceCodec(t reflect.Type, seen map[reflect.Type]*structType) code
253
260
s := alignedSize (e )
254
261
255
262
if e .Kind () == reflect .Uint8 {
256
- p := reflect .PtrTo (e )
257
- c := codec {}
258
-
259
263
// Go 1.7+ behavior: slices of byte types (and aliases) may override the
260
264
// default encoding and decoding behaviors by implementing marshaler and
261
265
// unmarshaler interfaces.
266
+ p := reflect .PtrTo (e )
267
+ c := codec {}
268
+
262
269
switch {
263
270
case e .Implements (jsonMarshalerType ):
264
271
c .encode = constructJSONMarshalerEncodeFunc (e , false )
@@ -296,7 +303,7 @@ func constructSliceCodec(t reflect.Type, seen map[reflect.Type]*structType) code
296
303
return c
297
304
}
298
305
299
- c := constructCodec (e , seen )
306
+ c := constructCodec (e , seen , true )
300
307
return codec {
301
308
encode : constructSliceEncodeFunc (s , t , c .encode ),
302
309
decode : constructSliceDecodeFunc (s , t , c .decode ),
@@ -336,7 +343,7 @@ func constructMapCodec(t reflect.Type, seen map[reflect.Type]*structType) codec
336
343
}
337
344
338
345
kc := codec {}
339
- vc := constructCodec (v , seen )
346
+ vc := constructCodec (v , seen , false )
340
347
341
348
if k .Implements (textMarshalerType ) || reflect .PtrTo (k ).Implements (textUnmarshalerType ) {
342
349
kc .encode = constructTextMarshalerEncodeFunc (k , false )
@@ -366,7 +373,7 @@ func constructMapCodec(t reflect.Type, seen map[reflect.Type]*structType) codec
366
373
reflect .Int16 ,
367
374
reflect .Int32 ,
368
375
reflect .Int64 :
369
- kc = constructStringCodec (k , seen )
376
+ kc = constructStringCodec (k , seen , false )
370
377
371
378
sortKeys = func (keys []reflect.Value ) {
372
379
sort .Slice (keys , func (i , j int ) bool { return keys [i ].Int () < keys [j ].Int () })
@@ -378,7 +385,7 @@ func constructMapCodec(t reflect.Type, seen map[reflect.Type]*structType) codec
378
385
reflect .Uint16 ,
379
386
reflect .Uint32 ,
380
387
reflect .Uint64 :
381
- kc = constructStringCodec (k , seen )
388
+ kc = constructStringCodec (k , seen , false )
382
389
383
390
sortKeys = func (keys []reflect.Value ) {
384
391
sort .Slice (keys , func (i , j int ) bool { return keys [i ].Uint () < keys [j ].Uint () })
@@ -416,15 +423,15 @@ func constructMapDecodeFunc(t reflect.Type, decodeKey, decodeValue decodeFunc) d
416
423
}
417
424
}
418
425
419
- func constructStructCodec (t reflect.Type , seen map [reflect.Type ]* structType ) codec {
420
- st := constructStructType (t , seen )
426
+ func constructStructCodec (t reflect.Type , seen map [reflect.Type ]* structType , canAddr bool ) codec {
427
+ st := constructStructType (t , seen , canAddr )
421
428
return codec {
422
429
encode : constructStructEncodeFunc (st ),
423
430
decode : constructStructDecodeFunc (st ),
424
431
}
425
432
}
426
433
427
- func constructStructType (t reflect.Type , seen map [reflect.Type ]* structType ) * structType {
434
+ func constructStructType (t reflect.Type , seen map [reflect.Type ]* structType , canAddr bool ) * structType {
428
435
// Used for preventing infinite recursion on types that have pointers to
429
436
// themselves.
430
437
st := seen [t ]
@@ -438,7 +445,7 @@ func constructStructType(t reflect.Type, seen map[reflect.Type]*structType) *str
438
445
}
439
446
440
447
seen [t ] = st
441
- st .fields = appendStructFields (st .fields , t , 0 , seen )
448
+ st .fields = appendStructFields (st .fields , t , 0 , seen , canAddr )
442
449
443
450
for i := range st .fields {
444
451
f := & st .fields [i ]
@@ -486,7 +493,7 @@ func constructEmbeddedStructPointerDecodeFunc(t reflect.Type, unexported bool, o
486
493
}
487
494
}
488
495
489
- func appendStructFields (fields []structField , t reflect.Type , offset uintptr , seen map [reflect.Type ]* structType ) []structField {
496
+ func appendStructFields (fields []structField , t reflect.Type , offset uintptr , seen map [reflect.Type ]* structType , canAddr bool ) []structField {
490
497
type embeddedField struct {
491
498
index int
492
499
offset uintptr
@@ -551,7 +558,7 @@ func appendStructFields(fields []structField, t reflect.Type, offset uintptr, se
551
558
// up by offset from the address of the wrapping object, so we
552
559
// simply add the embedded struct fields to the list of fields
553
560
// of the current struct type.
554
- subtype := constructStructType (typ , seen )
561
+ subtype := constructStructType (typ , seen , canAddr )
555
562
556
563
for j := range subtype .fields {
557
564
embedded = append (embedded , embeddedField {
@@ -572,7 +579,7 @@ func appendStructFields(fields []structField, t reflect.Type, offset uintptr, se
572
579
}
573
580
}
574
581
575
- codec := constructCodec (f .Type , seen )
582
+ codec := constructCodec (f .Type , seen , canAddr )
576
583
577
584
if stringify {
578
585
// https://golang.org/pkg/encoding/json/#Marshal
@@ -686,7 +693,7 @@ func encodeString(s string, flags AppendFlags) string {
686
693
687
694
func constructPointerCodec (t reflect.Type , seen map [reflect.Type ]* structType ) codec {
688
695
e := t .Elem ()
689
- c := constructCodec (e , seen )
696
+ c := constructCodec (e , seen , true )
690
697
return codec {
691
698
encode : constructPointerEncodeFunc (e , c .encode ),
692
699
decode : constructPointerDecodeFunc (e , c .decode ),
0 commit comments