reflect_slice.go raw

   1  package jsoniter
   2  
   3  import (
   4  	"fmt"
   5  	"github.com/modern-go/reflect2"
   6  	"io"
   7  	"unsafe"
   8  )
   9  
  10  func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder {
  11  	sliceType := typ.(*reflect2.UnsafeSliceType)
  12  	decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
  13  	return &sliceDecoder{sliceType, decoder}
  14  }
  15  
  16  func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder {
  17  	sliceType := typ.(*reflect2.UnsafeSliceType)
  18  	encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
  19  	return &sliceEncoder{sliceType, encoder}
  20  }
  21  
  22  type sliceEncoder struct {
  23  	sliceType   *reflect2.UnsafeSliceType
  24  	elemEncoder ValEncoder
  25  }
  26  
  27  func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  28  	if encoder.sliceType.UnsafeIsNil(ptr) {
  29  		stream.WriteNil()
  30  		return
  31  	}
  32  	length := encoder.sliceType.UnsafeLengthOf(ptr)
  33  	if length == 0 {
  34  		stream.WriteEmptyArray()
  35  		return
  36  	}
  37  	stream.WriteArrayStart()
  38  	encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream)
  39  	for i := 1; i < length; i++ {
  40  		stream.WriteMore()
  41  		elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i)
  42  		encoder.elemEncoder.Encode(elemPtr, stream)
  43  	}
  44  	stream.WriteArrayEnd()
  45  	if stream.Error != nil && stream.Error != io.EOF {
  46  		stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
  47  	}
  48  }
  49  
  50  func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  51  	return encoder.sliceType.UnsafeLengthOf(ptr) == 0
  52  }
  53  
  54  type sliceDecoder struct {
  55  	sliceType   *reflect2.UnsafeSliceType
  56  	elemDecoder ValDecoder
  57  }
  58  
  59  func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
  60  	decoder.doDecode(ptr, iter)
  61  	if iter.Error != nil && iter.Error != io.EOF {
  62  		iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error())
  63  	}
  64  }
  65  
  66  func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
  67  	c := iter.nextToken()
  68  	sliceType := decoder.sliceType
  69  	if c == 'n' {
  70  		iter.skipThreeBytes('u', 'l', 'l')
  71  		sliceType.UnsafeSetNil(ptr)
  72  		return
  73  	}
  74  	if c != '[' {
  75  		iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c}))
  76  		return
  77  	}
  78  	c = iter.nextToken()
  79  	if c == ']' {
  80  		sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0))
  81  		return
  82  	}
  83  	iter.unreadByte()
  84  	sliceType.UnsafeGrow(ptr, 1)
  85  	elemPtr := sliceType.UnsafeGetIndex(ptr, 0)
  86  	decoder.elemDecoder.Decode(elemPtr, iter)
  87  	length := 1
  88  	for c = iter.nextToken(); c == ','; c = iter.nextToken() {
  89  		idx := length
  90  		length += 1
  91  		sliceType.UnsafeGrow(ptr, length)
  92  		elemPtr = sliceType.UnsafeGetIndex(ptr, idx)
  93  		decoder.elemDecoder.Decode(elemPtr, iter)
  94  	}
  95  	if c != ']' {
  96  		iter.ReportError("decode slice", "expect ], but found "+string([]byte{c}))
  97  		return
  98  	}
  99  }
 100