Skip to content

Commit dbe715a

Browse files
committed
Create 0 size byte slices
As with other types, create a 0 size byte slice when the serialized data says so. This is a functional change, and will require the use of `allownil` to retain the existing behaviour (ie no allocs on nil/zero length slices). Fixes tinylib#362
1 parent be78ef3 commit dbe715a

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed

_generated/def.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,24 @@ type NonMsgStructTags struct {
278278
}
279279

280280
type EmptyStruct struct{}
281+
282+
type StructByteSlice struct {
283+
ABytes []byte `msg:",allownil"`
284+
AString []string `msg:",allownil"`
285+
ABool []bool `msg:",allownil"`
286+
AInt []int `msg:",allownil"`
287+
AInt8 []int8 `msg:",allownil"`
288+
AInt16 []int16 `msg:",allownil"`
289+
AInt32 []int32 `msg:",allownil"`
290+
AInt64 []int64 `msg:",allownil"`
291+
AUint []uint `msg:",allownil"`
292+
AUint8 []uint8 `msg:",allownil"`
293+
AUint16 []uint16 `msg:",allownil"`
294+
AUint32 []uint32 `msg:",allownil"`
295+
AUint64 []uint64 `msg:",allownil"`
296+
AFloat32 []float32 `msg:",allownil"`
297+
AFloat64 []float64 `msg:",allownil"`
298+
AComplex64 []complex64 `msg:",allownil"`
299+
AComplex128 []complex128 `msg:",allownil"`
300+
AStruct []Fixed `msg:",allownil"`
301+
}

_generated/gen_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,73 @@ func TestIssue168(t *testing.T) {
165165
t.Fatalf("got back %+v", test)
166166
}
167167
}
168+
169+
func TestIssue362(t *testing.T) {
170+
in := StructByteSlice{
171+
ABytes: make([]byte, 0),
172+
AString: make([]string, 0),
173+
ABool: make([]bool, 0),
174+
AInt: make([]int, 0),
175+
AInt8: make([]int8, 0),
176+
AInt16: make([]int16, 0),
177+
AInt32: make([]int32, 0),
178+
AInt64: make([]int64, 0),
179+
AUint: make([]uint, 0),
180+
AUint8: make([]uint8, 0),
181+
AUint16: make([]uint16, 0),
182+
AUint32: make([]uint32, 0),
183+
AUint64: make([]uint64, 0),
184+
AFloat32: make([]float32, 0),
185+
AFloat64: make([]float64, 0),
186+
AComplex64: make([]complex64, 0),
187+
AComplex128: make([]complex128, 0),
188+
AStruct: make([]Fixed, 0),
189+
}
190+
191+
b, err := in.MarshalMsg(nil)
192+
if err != nil {
193+
t.Fatal(err)
194+
}
195+
196+
var dst StructByteSlice
197+
_, err = dst.UnmarshalMsg(b)
198+
if err != nil {
199+
t.Fatal(err)
200+
}
201+
if !reflect.DeepEqual(in, dst) {
202+
t.Fatalf("mismatch %#v != %#v", in, dst)
203+
}
204+
dst2 := StructByteSlice{}
205+
dec := msgp.NewReader(bytes.NewReader(b))
206+
err = dst2.DecodeMsg(dec)
207+
if err != nil {
208+
t.Fatal(err)
209+
}
210+
if !reflect.DeepEqual(in, dst2) {
211+
t.Fatalf("mismatch %#v != %#v", in, dst2)
212+
}
213+
214+
// Encode with nil
215+
zero := StructByteSlice{}
216+
b, err = zero.MarshalMsg(nil)
217+
if err != nil {
218+
t.Fatal(err)
219+
}
220+
// Decode into dst that now has values...
221+
_, err = dst.UnmarshalMsg(b)
222+
if err != nil {
223+
t.Fatal(err)
224+
}
225+
// All should be nil now.
226+
if !reflect.DeepEqual(zero, dst) {
227+
t.Fatalf("mismatch %#v != %#v", zero, dst)
228+
}
229+
dec = msgp.NewReader(bytes.NewReader(b))
230+
err = dst2.DecodeMsg(dec)
231+
if err != nil {
232+
t.Fatal(err)
233+
}
234+
if !reflect.DeepEqual(zero, dst2) {
235+
t.Fatalf("mismatch %#v != %#v", zero, dst2)
236+
}
237+
}

msgp/read.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ func (m *Reader) ReadBytes(scratch []byte) (b []byte, err error) {
934934
err = badPrefix(BinType, lead)
935935
return
936936
}
937-
if int64(cap(scratch)) < read {
937+
if int64(cap(scratch)) < read || scratch == nil {
938938
b = make([]byte, read)
939939
} else {
940940
b = scratch[0:read]

msgp/read_bytes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ func readBytesBytes(b []byte, scratch []byte, zc bool) (v []byte, o []byte, err
843843
return
844844
}
845845

846-
if cap(scratch) >= read {
846+
if cap(scratch) >= read && scratch != nil {
847847
v = scratch[0:read]
848848
} else {
849849
v = make([]byte, read)

0 commit comments

Comments
 (0)