1
1
package jsoniter
2
2
3
3
import (
4
- "github.com/modern-go/reflect2"
5
4
"unsafe"
5
+
6
+ "github.com/modern-go/reflect2"
6
7
)
7
8
8
9
func decoderOfOptional (ctx * ctx , typ reflect2.Type ) ValDecoder {
@@ -16,7 +17,7 @@ func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder {
16
17
ptrType := typ .(* reflect2.UnsafePtrType )
17
18
elemType := ptrType .Elem ()
18
19
elemEncoder := encoderOfType (ctx , elemType )
19
- encoder := & OptionalEncoder {elemEncoder }
20
+ encoder := & OptionalEncoder {ValueEncoder : elemEncoder , seen : make ( map [unsafe. Pointer ] bool , 1 ) }
20
21
return encoder
21
22
}
22
23
@@ -61,13 +62,22 @@ func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
61
62
62
63
type OptionalEncoder struct {
63
64
ValueEncoder ValEncoder
65
+ seen map [unsafe.Pointer ]bool
64
66
}
65
67
66
68
func (encoder * OptionalEncoder ) Encode (ptr unsafe.Pointer , stream * Stream ) {
67
- if * ((* unsafe .Pointer )(ptr )) == nil {
69
+ ptr = * ((* unsafe .Pointer )(ptr ))
70
+ if encoder .seen [ptr ] {
71
+ stream .Error = ErrEncounterCycle
72
+ return
73
+ }
74
+ encoder .seen [ptr ] = true
75
+ defer delete (encoder .seen , ptr )
76
+
77
+ if ptr == nil {
68
78
stream .WriteNil ()
69
79
} else {
70
- encoder .ValueEncoder .Encode (* (( * unsafe . Pointer )( ptr )) , stream )
80
+ encoder .ValueEncoder .Encode (ptr , stream )
71
81
}
72
82
}
73
83
0 commit comments