Skip to content

Commit 5190536

Browse files
authored
Merge pull request #200 from IncSW/slice-decoding-compatibility
when cap is enough, reuse slice data for compatibility with encoding/json
2 parents ac15996 + c7747ba commit 5190536

File tree

2 files changed

+30
-32
lines changed

2 files changed

+30
-32
lines changed

decode_slice.go

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,11 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
101101
s.cursor++
102102
s.skipWhiteSpace()
103103
if s.char() == ']' {
104-
*(*sliceHeader)(p) = sliceHeader{
105-
data: newArray(d.elemType, 0),
106-
len: 0,
107-
cap: 0,
104+
dst := (*sliceHeader)(p)
105+
if dst.data == nil {
106+
dst.data = newArray(d.elemType, 0)
107+
} else {
108+
dst.len = 0
108109
}
109110
s.cursor++
110111
return nil
@@ -138,18 +139,13 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
138139
slice.cap = capacity
139140
slice.len = idx + 1
140141
slice.data = data
141-
dstCap := idx + 1
142-
dst := sliceHeader{
143-
data: newArray(d.elemType, dstCap),
144-
len: idx + 1,
145-
cap: dstCap,
142+
dst := (*sliceHeader)(p)
143+
dst.len = idx + 1
144+
if dst.len > dst.cap {
145+
dst.data = newArray(d.elemType, dst.len)
146+
dst.cap = dst.len
146147
}
147-
copySlice(d.elemType, dst, sliceHeader{
148-
data: slice.data,
149-
len: slice.len,
150-
cap: slice.cap,
151-
})
152-
*(*sliceHeader)(p) = dst
148+
copySlice(d.elemType, *dst, *slice)
153149
d.releaseSlice(slice)
154150
s.cursor++
155151
return nil
@@ -218,10 +214,11 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
218214
cursor++
219215
cursor = skipWhiteSpace(buf, cursor)
220216
if buf[cursor] == ']' {
221-
**(**sliceHeader)(unsafe.Pointer(&p)) = sliceHeader{
222-
data: newArray(d.elemType, 0),
223-
len: 0,
224-
cap: 0,
217+
dst := (*sliceHeader)(p)
218+
if dst.data == nil {
219+
dst.data = newArray(d.elemType, 0)
220+
} else {
221+
dst.len = 0
225222
}
226223
cursor++
227224
return cursor, nil
@@ -256,18 +253,13 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
256253
slice.cap = capacity
257254
slice.len = idx + 1
258255
slice.data = data
259-
dstCap := idx + 1
260-
dst := sliceHeader{
261-
data: newArray(d.elemType, dstCap),
262-
len: idx + 1,
263-
cap: dstCap,
256+
dst := (*sliceHeader)(p)
257+
dst.len = idx + 1
258+
if dst.len > dst.cap {
259+
dst.data = newArray(d.elemType, dst.len)
260+
dst.cap = dst.len
264261
}
265-
copySlice(d.elemType, dst, sliceHeader{
266-
data: slice.data,
267-
len: slice.len,
268-
cap: slice.cap,
269-
})
270-
**(**sliceHeader)(unsafe.Pointer(&p)) = dst
262+
copySlice(d.elemType, *dst, *slice)
271263
d.releaseSlice(slice)
272264
cursor++
273265
return cursor, nil

decode_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ func Test_Decoder(t *testing.T) {
103103
assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v))
104104
assertEq(t, "slice", fmt.Sprint([]int{1, 2, 3, 4}), fmt.Sprint(v))
105105
})
106+
t.Run("slice_reuse_data", func(t *testing.T) {
107+
v := make([]int, 0, 10)
108+
assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v))
109+
assertEq(t, "slice", fmt.Sprint([]int{1, 2, 3, 4}), fmt.Sprint(v))
110+
assertEq(t, "cap", 10, cap(v))
111+
})
106112
t.Run("array", func(t *testing.T) {
107113
var v [4]int
108114
assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v))
@@ -121,10 +127,10 @@ func Test_Decoder(t *testing.T) {
121127
{
122128
"a": {
123129
"nestedA": "value of nested a"
124-
},
130+
},
125131
"b": {
126132
"nestedB": "value of nested b"
127-
},
133+
},
128134
"c": {
129135
"nestedC": "value of nested c"
130136
}

0 commit comments

Comments
 (0)