gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }