package jsoniter import ( "fmt" "io" "reflect" "unsafe" ) func decoderOfSlice(typ reflect.Type) (Decoder, error) { decoder, err := decoderOfType(typ.Elem()) if err != nil { return nil, err } return &sliceDecoder{typ, typ.Elem(), decoder}, nil } func encoderOfSlice(typ reflect.Type) (Encoder, error) { encoder, err := encoderOfType(typ.Elem()) if err != nil { return nil, err } if typ.Elem().Kind() == reflect.Map { encoder = &optionalEncoder{encoder} } return &sliceEncoder{typ, typ.Elem(), encoder}, nil } type sliceEncoder struct { sliceType reflect.Type elemType reflect.Type elemEncoder Encoder } func (encoder *sliceEncoder) encode(ptr unsafe.Pointer, stream *Stream) { slice := (*sliceHeader)(ptr) if slice.Len == 0 { stream.WriteEmptyArray() return } stream.WriteArrayStart() elemPtr := uintptr(slice.Data) encoder.elemEncoder.encode(unsafe.Pointer(elemPtr), stream) for i := 1; i < slice.Len; i++ { stream.WriteMore() elemPtr += encoder.elemType.Size() encoder.elemEncoder.encode(unsafe.Pointer(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) encodeInterface(val interface{}, stream *Stream) { writeToStream(val, stream, encoder) } func (encoder *sliceEncoder) isEmpty(ptr unsafe.Pointer) bool { slice := (*sliceHeader)(ptr) return slice.Len == 0 } type sliceDecoder struct { sliceType reflect.Type elemType reflect.Type elemDecoder Decoder } // sliceHeader is a safe version of SliceHeader used within this package. type sliceHeader struct { Data unsafe.Pointer Len int Cap int } 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) { slice := (*sliceHeader)(ptr) reuseSlice(slice, decoder.sliceType, 4) if !iter.ReadArray() { return } offset := uintptr(0) decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) if !iter.ReadArray() { slice.Len = 1 return } offset += decoder.elemType.Size() decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) if !iter.ReadArray() { slice.Len = 2 return } offset += decoder.elemType.Size() decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) if !iter.ReadArray() { slice.Len = 3 return } offset += decoder.elemType.Size() decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) slice.Len = 4 for iter.ReadArray() { growOne(slice, decoder.sliceType, decoder.elemType) offset += decoder.elemType.Size() decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) } } // grow grows the slice s so that it can hold extra more values, allocating // more capacity if needed. It also returns the old and new slice lengths. func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Type) { newLen := slice.Len + 1 if newLen <= slice.Cap { slice.Len = newLen return } newCap := slice.Cap if newCap == 0 { newCap = 1 } else { for newCap < newLen { if slice.Len < 1024 { newCap += newCap } else { newCap += newCap / 4 } } } dst := unsafe.Pointer(reflect.MakeSlice(sliceType, newLen, newCap).Pointer()) // copy old array into new array originalBytesCount := uintptr(slice.Len) * elementType.Size() srcPtr := (*[1 << 30]byte)(slice.Data) dstPtr := (*[1 << 30]byte)(dst) for i := uintptr(0); i < originalBytesCount; i++ { dstPtr[i] = srcPtr[i] } slice.Len = newLen slice.Cap = newCap slice.Data = dst } func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) { if expectedCap <= slice.Cap { return } dst := unsafe.Pointer(reflect.MakeSlice(sliceType, 0, expectedCap).Pointer()) slice.Cap = expectedCap slice.Data = dst }