package jsoniter import ( "fmt" "github.com/modern-go/reflect2" "io" "unsafe" ) func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder { sliceType := typ.(*reflect2.UnsafeSliceType) decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) return &sliceDecoder{sliceType, decoder} } func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder { sliceType := typ.(*reflect2.UnsafeSliceType) encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) return &sliceEncoder{sliceType, encoder} } type sliceEncoder struct { sliceType *reflect2.UnsafeSliceType elemEncoder ValEncoder } func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { if encoder.sliceType.UnsafeIsNil(ptr) { stream.WriteNil() return } length := encoder.sliceType.UnsafeLengthOf(ptr) if length == 0 { stream.WriteEmptyArray() return } stream.WriteArrayStart() encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream) for i := 1; i < length; i++ { stream.WriteMore() elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i) encoder.elemEncoder.Encode(elemPtr, stream) } stream.WriteArrayEnd() if stream.Error != nil && stream.Error != io.EOF { stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error()) } } func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.sliceType.UnsafeLengthOf(ptr) == 0 } type sliceDecoder struct { sliceType *reflect2.UnsafeSliceType elemDecoder ValDecoder } func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { decoder.doDecode(ptr, iter) if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error()) } } func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { c := iter.nextToken() sliceType := decoder.sliceType if c == 'n' { iter.skipThreeBytes('u', 'l', 'l') sliceType.UnsafeSetNil(ptr) return } if c != '[' { iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c})) return } c = iter.nextToken() if c == ']' { sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0)) return } iter.unreadByte() sliceType.UnsafeGrow(ptr, 1) elemPtr := sliceType.UnsafeGetIndex(ptr, 0) decoder.elemDecoder.Decode(elemPtr, iter) length := 1 for c = iter.nextToken(); c == ','; c = iter.nextToken() { idx := length length += 1 sliceType.UnsafeGrow(ptr, length) elemPtr = sliceType.UnsafeGetIndex(ptr, idx) decoder.elemDecoder.Decode(elemPtr, iter) } if c != ']' { iter.ReportError("decode slice", "expect ], but found "+string([]byte{c})) return } }