blob: 43ec71d6dadf3b2bb42158eaf5387b838124dde9 [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001package jsoniter
2
3import (
4 "github.com/modern-go/reflect2"
5 "reflect"
6 "unsafe"
7)
8
9func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder {
10 ptrType := typ.(*reflect2.UnsafePtrType)
11 elemType := ptrType.Elem()
12 decoder := decoderOfType(ctx, elemType)
13 if ctx.prefix == "" && elemType.Kind() == reflect.Ptr {
14 return &dereferenceDecoder{elemType, decoder}
15 }
16 return &OptionalDecoder{elemType, decoder}
17}
18
19func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder {
20 ptrType := typ.(*reflect2.UnsafePtrType)
21 elemType := ptrType.Elem()
22 elemEncoder := encoderOfType(ctx, elemType)
23 encoder := &OptionalEncoder{elemEncoder}
24 return encoder
25}
26
27type OptionalDecoder struct {
28 ValueType reflect2.Type
29 ValueDecoder ValDecoder
30}
31
32func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
33 if iter.ReadNil() {
34 *((*unsafe.Pointer)(ptr)) = nil
35 } else {
36 if *((*unsafe.Pointer)(ptr)) == nil {
37 //pointer to null, we have to allocate memory to hold the value
38 newPtr := decoder.ValueType.UnsafeNew()
39 decoder.ValueDecoder.Decode(newPtr, iter)
40 *((*unsafe.Pointer)(ptr)) = newPtr
41 } else {
42 //reuse existing instance
43 decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
44 }
45 }
46}
47
48type dereferenceDecoder struct {
49 // only to deference a pointer
50 valueType reflect2.Type
51 valueDecoder ValDecoder
52}
53
54func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
55 if *((*unsafe.Pointer)(ptr)) == nil {
56 //pointer to null, we have to allocate memory to hold the value
57 newPtr := decoder.valueType.UnsafeNew()
58 decoder.valueDecoder.Decode(newPtr, iter)
59 *((*unsafe.Pointer)(ptr)) = newPtr
60 } else {
61 //reuse existing instance
62 decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
63 }
64}
65
66type OptionalEncoder struct {
67 ValueEncoder ValEncoder
68}
69
70func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
71 if *((*unsafe.Pointer)(ptr)) == nil {
72 stream.WriteNil()
73 } else {
74 encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
75 }
76}
77
78func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
79 return *((*unsafe.Pointer)(ptr)) == nil
80}
81
82type dereferenceEncoder struct {
83 ValueEncoder ValEncoder
84}
85
86func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
87 if *((*unsafe.Pointer)(ptr)) == nil {
88 stream.WriteNil()
89 } else {
90 encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
91 }
92}
93
94func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
95 dePtr := *((*unsafe.Pointer)(ptr))
96 if dePtr == nil {
97 return true
98 }
99 return encoder.ValueEncoder.IsEmpty(dePtr)
100}
101
102func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
103 deReferenced := *((*unsafe.Pointer)(ptr))
104 if deReferenced == nil {
105 return true
106 }
107 isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil)
108 if !converted {
109 return false
110 }
111 fieldPtr := unsafe.Pointer(deReferenced)
112 return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
113}
114
115type referenceEncoder struct {
116 encoder ValEncoder
117}
118
119func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
120 encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
121}
122
123func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
124 return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
125}
126
127type referenceDecoder struct {
128 decoder ValDecoder
129}
130
131func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
132 decoder.decoder.Decode(unsafe.Pointer(&ptr), iter)
133}