Patch for concurrent iterator & others (onto v1.11.6) #386
@ -379,7 +379,7 @@ func decodeByteArray(s *Stream, val reflect.Value) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slice := byteArrayBytes(val)
|
slice := byteArrayBytes(val, val.Len())
|
||||||
switch kind {
|
switch kind {
|
||||||
case Byte:
|
case Byte:
|
||||||
if len(slice) == 0 {
|
if len(slice) == 0 {
|
||||||
|
@ -432,7 +432,20 @@ func makeByteArrayWriter(typ reflect.Type) writer {
|
|||||||
case 1:
|
case 1:
|
||||||
return writeLengthOneByteArray
|
return writeLengthOneByteArray
|
||||||
default:
|
default:
|
||||||
return writeByteArray
|
length := typ.Len()
|
||||||
|
return func(val reflect.Value, w *encbuf) error {
|
||||||
|
if !val.CanAddr() {
|
||||||
|
// Getting the byte slice of val requires it to be addressable. Make it
|
||||||
|
// addressable by copying.
|
||||||
|
copy := reflect.New(val.Type()).Elem()
|
||||||
|
copy.Set(val)
|
||||||
|
val = copy
|
||||||
|
}
|
||||||
|
slice := byteArrayBytes(val, length)
|
||||||
|
w.encodeStringHeader(len(slice))
|
||||||
|
w.str = append(w.str, slice...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,21 +464,6 @@ func writeLengthOneByteArray(val reflect.Value, w *encbuf) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeByteArray(val reflect.Value, w *encbuf) error {
|
|
||||||
if !val.CanAddr() {
|
|
||||||
// Getting the byte slice of val requires it to be addressable. Make it
|
|
||||||
// addressable by copying.
|
|
||||||
copy := reflect.New(val.Type()).Elem()
|
|
||||||
copy.Set(val)
|
|
||||||
val = copy
|
|
||||||
}
|
|
||||||
|
|
||||||
slice := byteArrayBytes(val)
|
|
||||||
w.encodeStringHeader(len(slice))
|
|
||||||
w.str = append(w.str, slice...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeString(val reflect.Value, w *encbuf) error {
|
func writeString(val reflect.Value, w *encbuf) error {
|
||||||
s := val.String()
|
s := val.String()
|
||||||
if len(s) == 1 && s[0] <= 0x7f {
|
if len(s) == 1 && s[0] <= 0x7f {
|
||||||
@ -499,10 +497,12 @@ func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) {
|
|||||||
if etypeinfo.writerErr != nil {
|
if etypeinfo.writerErr != nil {
|
||||||
return nil, etypeinfo.writerErr
|
return nil, etypeinfo.writerErr
|
||||||
}
|
}
|
||||||
writer := func(val reflect.Value, w *encbuf) error {
|
|
||||||
if !ts.tail {
|
var wfn writer
|
||||||
defer w.listEnd(w.list())
|
if ts.tail {
|
||||||
}
|
// This is for struct tail slices.
|
||||||
|
// w.list is not called for them.
|
||||||
|
wfn = func(val reflect.Value, w *encbuf) error {
|
||||||
vlen := val.Len()
|
vlen := val.Len()
|
||||||
for i := 0; i < vlen; i++ {
|
for i := 0; i < vlen; i++ {
|
||||||
if err := etypeinfo.writer(val.Index(i), w); err != nil {
|
if err := etypeinfo.writer(val.Index(i), w); err != nil {
|
||||||
@ -511,7 +511,25 @@ func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return writer, nil
|
} else {
|
||||||
|
// This is for regular slices and arrays.
|
||||||
|
wfn = func(val reflect.Value, w *encbuf) error {
|
||||||
|
vlen := val.Len()
|
||||||
|
if vlen == 0 {
|
||||||
|
w.str = append(w.str, 0xC0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listOffset := w.list()
|
||||||
|
for i := 0; i < vlen; i++ {
|
||||||
|
if err := etypeinfo.writer(val.Index(i), w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.listEnd(listOffset)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wfn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeStructWriter(typ reflect.Type) (writer, error) {
|
func makeStructWriter(typ reflect.Type) (writer, error) {
|
||||||
@ -562,12 +580,8 @@ func makeStructWriter(typ reflect.Type) (writer, error) {
|
|||||||
return writer, nil
|
return writer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makePtrWriter(typ reflect.Type, ts tags) (writer, error) {
|
// nilEncoding returns the encoded value of a nil pointer.
|
||||||
etypeinfo := theTC.infoWhileGenerating(typ.Elem(), tags{})
|
func nilEncoding(typ reflect.Type, ts tags) uint8 {
|
||||||
if etypeinfo.writerErr != nil {
|
|
||||||
return nil, etypeinfo.writerErr
|
|
||||||
}
|
|
||||||
// Determine how to encode nil pointers.
|
|
||||||
var nilKind Kind
|
var nilKind Kind
|
||||||
if ts.nilOK {
|
if ts.nilOK {
|
||||||
nilKind = ts.nilKind // use struct tag if provided
|
nilKind = ts.nilKind // use struct tag if provided
|
||||||
@ -575,17 +589,30 @@ func makePtrWriter(typ reflect.Type, ts tags) (writer, error) {
|
|||||||
nilKind = defaultNilKind(typ.Elem())
|
nilKind = defaultNilKind(typ.Elem())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch nilKind {
|
||||||
|
case String:
|
||||||
|
return 0x80
|
||||||
|
case List:
|
||||||
|
return 0xC0
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("rlp: invalid nil kind %d", nilKind))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePtrWriter(typ reflect.Type, ts tags) (writer, error) {
|
||||||
|
etypeinfo := theTC.infoWhileGenerating(typ.Elem(), tags{})
|
||||||
|
if etypeinfo.writerErr != nil {
|
||||||
|
return nil, etypeinfo.writerErr
|
||||||
|
}
|
||||||
|
nilEncoding := nilEncoding(typ, ts)
|
||||||
|
|
||||||
writer := func(val reflect.Value, w *encbuf) error {
|
writer := func(val reflect.Value, w *encbuf) error {
|
||||||
if val.IsNil() {
|
if ev := val.Elem(); ev.IsValid() {
|
||||||
if nilKind == String {
|
return etypeinfo.writer(ev, w)
|
||||||
w.str = append(w.str, 0x80)
|
|
||||||
} else {
|
|
||||||
w.listEnd(w.list())
|
|
||||||
}
|
}
|
||||||
|
w.str = append(w.str, nilEncoding)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return etypeinfo.writer(val.Elem(), w)
|
|
||||||
}
|
|
||||||
return writer, nil
|
return writer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,3 +540,31 @@ func BenchmarkEncodeByteArrayStruct(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type structSliceElem struct {
|
||||||
|
X uint64
|
||||||
|
Y uint64
|
||||||
|
Z uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type structPtrSlice []*structSliceElem
|
||||||
|
|
||||||
|
func BenchmarkEncodeStructPtrSlice(b *testing.B) {
|
||||||
|
var out bytes.Buffer
|
||||||
|
var value = structPtrSlice{
|
||||||
|
&structSliceElem{1, 1, 1},
|
||||||
|
&structSliceElem{2, 2, 2},
|
||||||
|
&structSliceElem{3, 3, 3},
|
||||||
|
&structSliceElem{5, 5, 5},
|
||||||
|
&structSliceElem{6, 6, 6},
|
||||||
|
&structSliceElem{7, 7, 7},
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
out.Reset()
|
||||||
|
if err := Encode(&out, &value); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,6 @@ package rlp
|
|||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
// byteArrayBytes returns a slice of the byte array v.
|
// byteArrayBytes returns a slice of the byte array v.
|
||||||
func byteArrayBytes(v reflect.Value) []byte {
|
func byteArrayBytes(v reflect.Value, length int) []byte {
|
||||||
return v.Slice(0, v.Len()).Bytes()
|
return v.Slice(0, length).Bytes()
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// byteArrayBytes returns a slice of the byte array v.
|
// byteArrayBytes returns a slice of the byte array v.
|
||||||
func byteArrayBytes(v reflect.Value) []byte {
|
func byteArrayBytes(v reflect.Value, length int) []byte {
|
||||||
len := v.Len()
|
|
||||||
var s []byte
|
var s []byte
|
||||||
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s))
|
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s))
|
||||||
hdr.Data = v.UnsafeAddr()
|
hdr.Data = v.UnsafeAddr()
|
||||||
hdr.Cap = len
|
hdr.Cap = length
|
||||||
hdr.Len = len
|
hdr.Len = length
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user