123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- package jsoniter
- import (
- "github.com/modern-go/reflect2"
- "reflect"
- "unsafe"
- )
- func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder {
- ptrType := typ.(*reflect2.UnsafePtrType)
- elemType := ptrType.Elem()
- decoder := decoderOfType(ctx, elemType)
- if ctx.prefix == "" && elemType.Kind() == reflect.Ptr {
- return &dereferenceDecoder{elemType, decoder}
- }
- return &OptionalDecoder{elemType, decoder}
- }
- func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder {
- ptrType := typ.(*reflect2.UnsafePtrType)
- elemType := ptrType.Elem()
- elemEncoder := encoderOfType(ctx, elemType)
- encoder := &OptionalEncoder{elemEncoder}
- return encoder
- }
- type OptionalDecoder struct {
- ValueType reflect2.Type
- ValueDecoder ValDecoder
- }
- func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
- if iter.ReadNil() {
- *((*unsafe.Pointer)(ptr)) = nil
- } else {
- if *((*unsafe.Pointer)(ptr)) == nil {
- //pointer to null, we have to allocate memory to hold the value
- newPtr := decoder.ValueType.UnsafeNew()
- decoder.ValueDecoder.Decode(newPtr, iter)
- *((*unsafe.Pointer)(ptr)) = newPtr
- } else {
- //reuse existing instance
- decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
- }
- }
- }
- type dereferenceDecoder struct {
- // only to deference a pointer
- valueType reflect2.Type
- valueDecoder ValDecoder
- }
- func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
- if *((*unsafe.Pointer)(ptr)) == nil {
- //pointer to null, we have to allocate memory to hold the value
- newPtr := decoder.valueType.UnsafeNew()
- decoder.valueDecoder.Decode(newPtr, iter)
- *((*unsafe.Pointer)(ptr)) = newPtr
- } else {
- //reuse existing instance
- decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
- }
- }
- type OptionalEncoder struct {
- ValueEncoder ValEncoder
- }
- func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
- if *((*unsafe.Pointer)(ptr)) == nil {
- stream.WriteNil()
- } else {
- encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
- }
- }
- func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
- return *((*unsafe.Pointer)(ptr)) == nil
- }
- type dereferenceEncoder struct {
- ValueEncoder ValEncoder
- }
- func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
- if *((*unsafe.Pointer)(ptr)) == nil {
- stream.WriteNil()
- } else {
- encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
- }
- }
- func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
- dePtr := *((*unsafe.Pointer)(ptr))
- if dePtr == nil {
- return true
- }
- return encoder.ValueEncoder.IsEmpty(dePtr)
- }
- func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
- deReferenced := *((*unsafe.Pointer)(ptr))
- if deReferenced == nil {
- return true
- }
- isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil)
- if !converted {
- return false
- }
- fieldPtr := unsafe.Pointer(deReferenced)
- return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
- }
- type referenceEncoder struct {
- encoder ValEncoder
- }
- func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
- encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
- }
- func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
- return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
- }
- type referenceDecoder struct {
- decoder ValDecoder
- }
- func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
- decoder.decoder.Decode(unsafe.Pointer(&ptr), iter)
- }
|