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 }