reflect_optional.go raw

   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  }
 130