gtsocial-umbx

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

reflect_slice.go (2662B)


      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 }