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