...

Source file src/github.com/json-iterator/go/reflect_optional.go

Documentation: github.com/json-iterator/go

     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  

View as plain text