4 "github.com/modern-go/reflect2"
9 func 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}
16 return &OptionalDecoder{elemType, decoder}
19 func 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}
27 type OptionalDecoder struct {
28 ValueType reflect2.Type
29 ValueDecoder ValDecoder
32 func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
34 *((*unsafe.Pointer)(ptr)) = nil
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
42 //reuse existing instance
43 decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
48 type dereferenceDecoder struct {
49 // only to deference a pointer
50 valueType reflect2.Type
51 valueDecoder ValDecoder
54 func (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
61 //reuse existing instance
62 decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
66 type OptionalEncoder struct {
67 ValueEncoder ValEncoder
70 func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
71 if *((*unsafe.Pointer)(ptr)) == nil {
74 encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
78 func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
79 return *((*unsafe.Pointer)(ptr)) == nil
82 type dereferenceEncoder struct {
83 ValueEncoder ValEncoder
86 func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
87 if *((*unsafe.Pointer)(ptr)) == nil {
90 encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
94 func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
95 dePtr := *((*unsafe.Pointer)(ptr))
99 return encoder.ValueEncoder.IsEmpty(dePtr)
102 func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
103 deReferenced := *((*unsafe.Pointer)(ptr))
104 if deReferenced == nil {
107 isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil)
111 fieldPtr := unsafe.Pointer(deReferenced)
112 return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
115 type referenceEncoder struct {
119 func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
120 encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
123 func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
124 return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
127 type referenceDecoder struct {
131 func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
132 decoder.decoder.Decode(unsafe.Pointer(&ptr), iter)