reflect_optional.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package jsoniter
  2. import (
  3. "github.com/modern-go/reflect2"
  4. "reflect"
  5. "unsafe"
  6. )
  7. func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder {
  8. ptrType := typ.(*reflect2.UnsafePtrType)
  9. elemType := ptrType.Elem()
  10. decoder := decoderOfType(ctx, elemType)
  11. if ctx.prefix == "" && elemType.Kind() == reflect.Ptr {
  12. return &dereferenceDecoder{elemType, decoder}
  13. }
  14. return &OptionalDecoder{elemType, decoder}
  15. }
  16. func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder {
  17. ptrType := typ.(*reflect2.UnsafePtrType)
  18. elemType := ptrType.Elem()
  19. elemEncoder := encoderOfType(ctx, elemType)
  20. encoder := &OptionalEncoder{elemEncoder}
  21. return encoder
  22. }
  23. type OptionalDecoder struct {
  24. ValueType reflect2.Type
  25. ValueDecoder ValDecoder
  26. }
  27. func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
  28. if iter.ReadNil() {
  29. *((*unsafe.Pointer)(ptr)) = nil
  30. } else {
  31. if *((*unsafe.Pointer)(ptr)) == nil {
  32. //pointer to null, we have to allocate memory to hold the value
  33. newPtr := decoder.ValueType.UnsafeNew()
  34. decoder.ValueDecoder.Decode(newPtr, iter)
  35. *((*unsafe.Pointer)(ptr)) = newPtr
  36. } else {
  37. //reuse existing instance
  38. decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
  39. }
  40. }
  41. }
  42. type dereferenceDecoder struct {
  43. // only to deference a pointer
  44. valueType reflect2.Type
  45. valueDecoder ValDecoder
  46. }
  47. func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
  48. if *((*unsafe.Pointer)(ptr)) == nil {
  49. //pointer to null, we have to allocate memory to hold the value
  50. newPtr := decoder.valueType.UnsafeNew()
  51. decoder.valueDecoder.Decode(newPtr, iter)
  52. *((*unsafe.Pointer)(ptr)) = newPtr
  53. } else {
  54. //reuse existing instance
  55. decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
  56. }
  57. }
  58. type OptionalEncoder struct {
  59. ValueEncoder ValEncoder
  60. }
  61. func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  62. if *((*unsafe.Pointer)(ptr)) == nil {
  63. stream.WriteNil()
  64. } else {
  65. encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
  66. }
  67. }
  68. func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  69. return *((*unsafe.Pointer)(ptr)) == nil
  70. }
  71. type dereferenceEncoder struct {
  72. ValueEncoder ValEncoder
  73. }
  74. func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  75. if *((*unsafe.Pointer)(ptr)) == nil {
  76. stream.WriteNil()
  77. } else {
  78. encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
  79. }
  80. }
  81. func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  82. dePtr := *((*unsafe.Pointer)(ptr))
  83. if dePtr == nil {
  84. return true
  85. }
  86. return encoder.ValueEncoder.IsEmpty(dePtr)
  87. }
  88. func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
  89. deReferenced := *((*unsafe.Pointer)(ptr))
  90. if deReferenced == nil {
  91. return true
  92. }
  93. isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil)
  94. if !converted {
  95. return false
  96. }
  97. fieldPtr := unsafe.Pointer(deReferenced)
  98. return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
  99. }
  100. type referenceEncoder struct {
  101. encoder ValEncoder
  102. }
  103. func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  104. encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
  105. }
  106. func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  107. return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
  108. }
  109. type referenceDecoder struct {
  110. decoder ValDecoder
  111. }
  112. func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
  113. decoder.decoder.Decode(unsafe.Pointer(&ptr), iter)
  114. }