@@ -49,9 +49,20 @@ func newSliceDecoder(dec decoder, elemType *rtype, size uintptr, structName, fie
49
49
}
50
50
}
51
51
52
- func (d * sliceDecoder ) newSlice () * sliceHeader {
52
+ func (d * sliceDecoder ) newSlice (src * sliceHeader ) * sliceHeader {
53
53
slice := d .arrayPool .Get ().(* sliceHeader )
54
- slice .len = 0
54
+ if src .len > 0 {
55
+ // copy original elem
56
+ if slice .cap < src .cap {
57
+ data := newArray (d .elemType , src .cap )
58
+ slice = & sliceHeader {data : data , len : src .len , cap : src .cap }
59
+ } else {
60
+ slice .len = src .len
61
+ }
62
+ copySlice (d .elemType , * slice , * src )
63
+ } else {
64
+ slice .len = 0
65
+ }
55
66
return slice
56
67
}
57
68
@@ -109,7 +120,8 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
109
120
return nil
110
121
}
111
122
idx := 0
112
- slice := d .newSlice ()
123
+ slice := d .newSlice ((* sliceHeader )(p ))
124
+ srcLen := slice .len
113
125
capacity := slice .cap
114
126
data := slice .data
115
127
for {
@@ -121,12 +133,17 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
121
133
copySlice (d .elemType , dst , src )
122
134
}
123
135
ep := unsafe .Pointer (uintptr (data ) + uintptr (idx )* d .size )
124
- if d .isElemPointerType {
125
- * * (* * unsafe .Pointer )(unsafe .Pointer (& ep )) = nil // initialize elem pointer
126
- } else {
127
- // assign new element to the slice
128
- typedmemmove (d .elemType , ep , unsafe_New (d .elemType ))
136
+
137
+ // if srcLen is greater than idx, keep the original reference
138
+ if srcLen <= idx {
139
+ if d .isElemPointerType {
140
+ * * (* * unsafe .Pointer )(unsafe .Pointer (& ep )) = nil // initialize elem pointer
141
+ } else {
142
+ // assign new element to the slice
143
+ typedmemmove (d .elemType , ep , unsafe_New (d .elemType ))
144
+ }
129
145
}
146
+
130
147
if err := d .valueDecoder .decodeStream (s , depth , ep ); err != nil {
131
148
return err
132
149
}
@@ -212,7 +229,8 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
212
229
return cursor , nil
213
230
}
214
231
idx := 0
215
- slice := d .newSlice ()
232
+ slice := d .newSlice ((* sliceHeader )(p ))
233
+ srcLen := slice .len
216
234
capacity := slice .cap
217
235
data := slice .data
218
236
for {
@@ -224,11 +242,14 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
224
242
copySlice (d .elemType , dst , src )
225
243
}
226
244
ep := unsafe .Pointer (uintptr (data ) + uintptr (idx )* d .size )
227
- if d .isElemPointerType {
228
- * * (* * unsafe .Pointer )(unsafe .Pointer (& ep )) = nil // initialize elem pointer
229
- } else {
230
- // assign new element to the slice
231
- typedmemmove (d .elemType , ep , unsafe_New (d .elemType ))
245
+ // if srcLen is greater than idx, keep the original reference
246
+ if srcLen <= idx {
247
+ if d .isElemPointerType {
248
+ * * (* * unsafe .Pointer )(unsafe .Pointer (& ep )) = nil // initialize elem pointer
249
+ } else {
250
+ // assign new element to the slice
251
+ typedmemmove (d .elemType , ep , unsafe_New (d .elemType ))
252
+ }
232
253
}
233
254
c , err := d .valueDecoder .decode (buf , cursor , depth , ep )
234
255
if err != nil {
0 commit comments