reflect_optional.go (3373B)
1 package jsoniter 2 3 import ( 4 "github.com/modern-go/reflect2" 5 "unsafe" 6 ) 7 8 func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder { 9 ptrType := typ.(*reflect2.UnsafePtrType) 10 elemType := ptrType.Elem() 11 decoder := decoderOfType(ctx, elemType) 12 return &OptionalDecoder{elemType, decoder} 13 } 14 15 func 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 23 type OptionalDecoder struct { 24 ValueType reflect2.Type 25 ValueDecoder ValDecoder 26 } 27 28 func (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 44 type dereferenceDecoder struct { 45 // only to deference a pointer 46 valueType reflect2.Type 47 valueDecoder ValDecoder 48 } 49 50 func (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 62 type OptionalEncoder struct { 63 ValueEncoder ValEncoder 64 } 65 66 func (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 74 func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { 75 return *((*unsafe.Pointer)(ptr)) == nil 76 } 77 78 type dereferenceEncoder struct { 79 ValueEncoder ValEncoder 80 } 81 82 func (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 90 func (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 98 func (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 111 type referenceEncoder struct { 112 encoder ValEncoder 113 } 114 115 func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { 116 encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) 117 } 118 119 func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { 120 return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) 121 } 122 123 type referenceDecoder struct { 124 decoder ValDecoder 125 } 126 127 func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { 128 decoder.decoder.Decode(unsafe.Pointer(&ptr), iter) 129 }