Skip to content

Commit fa12de2

Browse files
authored
[Go] Fix for decoding into a struct with pre-allocated slices. (#825)
* [Go] Fix for decoding into a struct with pre-allocated slices. This change allows you to call `Decode()` on an sbe struct where the struct has pre-allocated slices. Before, the code would allocate a new slice if the capacity on the existing slice was less than the number of groups in the message. If the old slice had a greater capacity, it wouldn't truncate the number of elements to the new length. * [Go] Add test for decoding groups onto a pre-populated message. * [Go] Add test for decoding when existing vardata values are shorter. This tests that if the existing decoded struct has a vardata value with length = 5, and the message to decode has length = 4, then the vardata value is truncated to length 4.
1 parent cd9c39e commit fa12de2

File tree

3 files changed

+161
-4
lines changed

3 files changed

+161
-4
lines changed

gocode/src/group_with_data/TestMessages_test.go

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestEncodeDecodeTestMessage1(t *testing.T) {
2323
t.Fail()
2424
}
2525

26-
var out TestMessage1 = *new(TestMessage1)
26+
var out = *new(TestMessage1)
2727
if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
2828
t.Log("Decoding Error", err)
2929
t.Fail()
@@ -71,7 +71,7 @@ func TestEncodeDecodeTestMessage2(t *testing.T) {
7171
t.Fail()
7272
}
7373

74-
var out TestMessage2 = *new(TestMessage2)
74+
var out = *new(TestMessage2)
7575
if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
7676
t.Log("Decoding Error", err)
7777
t.Fail()
@@ -129,7 +129,7 @@ func TestEncodeDecodeTestMessage3(t *testing.T) {
129129
t.Fail()
130130
}
131131

132-
var out TestMessage3 = *new(TestMessage3)
132+
var out = *new(TestMessage3)
133133
if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
134134
t.Log("Decoding Error", err)
135135
t.Fail()
@@ -186,7 +186,7 @@ func TestEncodeDecodeTestMessage4(t *testing.T) {
186186
t.Fail()
187187
}
188188

189-
var out TestMessage4 = *new(TestMessage4)
189+
var out = *new(TestMessage4)
190190
if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
191191
t.Log("Decoding Error", err)
192192
t.Fail()
@@ -212,3 +212,89 @@ func TestEncodeDecodeTestMessage4(t *testing.T) {
212212
}
213213
return
214214
}
215+
216+
func TestEncodeDecodeTestPreAlloc(t *testing.T) {
217+
m := NewSbeGoMarshaller()
218+
219+
in := TestMessage4{
220+
Tag1: 9876,
221+
Entries: []TestMessage4Entries{
222+
{
223+
VarDataField1: []byte("abcdef"),
224+
VarDataField2: []byte("ghij"),
225+
},
226+
{
227+
VarDataField1: []byte("abc"),
228+
VarDataField2: []byte("gh"),
229+
},
230+
},
231+
}
232+
233+
var buf = new(bytes.Buffer)
234+
if err := in.Encode(m, buf, true); err != nil {
235+
t.Log("Encoding Error", err)
236+
t.Fail()
237+
}
238+
239+
var out = *new(TestMessage4)
240+
if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
241+
t.Log("Decoding Error", err)
242+
t.Fail()
243+
}
244+
245+
if in.Tag1 != out.Tag1 {
246+
t.Logf("in.Tag1 != out.Tag1")
247+
t.Fail()
248+
}
249+
250+
for i := 0; i < len(in.Entries); i++ {
251+
if !bytes.Equal(in.Entries[i].VarDataField1, out.Entries[i].VarDataField1) {
252+
t.Logf("in.Entries[%d].VarDataField (%v)!= out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField1, out.Entries[i].VarDataField1)
253+
t.Fail()
254+
}
255+
if !bytes.Equal(in.Entries[i].VarDataField2, out.Entries[i].VarDataField2) {
256+
t.Logf("in.Entries[%d].VarDataField (%v) != out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField2, out.Entries[i].VarDataField2)
257+
t.Fail()
258+
}
259+
}
260+
261+
// new messages with newer group elements, shorter vardata
262+
in = TestMessage4{
263+
Tag1: 9876,
264+
Entries: []TestMessage4Entries{
265+
{
266+
VarDataField1: []byte("abc"),
267+
VarDataField2: []byte("ghijk"),
268+
},
269+
},
270+
}
271+
272+
buf.Reset()
273+
if err := in.Encode(m, buf, true); err != nil {
274+
t.Log("Encoding Error", err)
275+
t.Fail()
276+
}
277+
278+
if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
279+
t.Log("Decoding Error", err)
280+
t.Fail()
281+
}
282+
283+
if in.Tag1 != out.Tag1 {
284+
t.Logf("in.Tag1 != out.Tag1")
285+
t.Fail()
286+
}
287+
288+
for i := 0; i < len(in.Entries); i++ {
289+
if !bytes.Equal(in.Entries[i].VarDataField1, out.Entries[i].VarDataField1) {
290+
t.Logf("in.Entries[%d].VarDataField (%v)!= out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField1, out.Entries[i].VarDataField1)
291+
t.Fail()
292+
}
293+
if !bytes.Equal(in.Entries[i].VarDataField2, out.Entries[i].VarDataField2) {
294+
t.Logf("in.Entries[%d].VarDataField (%v) != out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField2, out.Entries[i].VarDataField2)
295+
t.Fail()
296+
}
297+
}
298+
299+
return
300+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package mktdata
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os"
7+
"testing"
8+
)
9+
10+
func TestPreallocated(t *testing.T) {
11+
in := &MDIncrementalRefreshBook32{
12+
TransactTime: 1,
13+
NoMDEntries: []MDIncrementalRefreshBook32NoMDEntries{
14+
{
15+
MDEntryPx: PRICENULL{},
16+
MDEntrySize: 5,
17+
SecurityID: 1,
18+
},
19+
{
20+
MDEntryPx: PRICENULL{},
21+
MDEntrySize: 6,
22+
SecurityID: 1,
23+
},
24+
},
25+
}
26+
min := NewSbeGoMarshaller()
27+
28+
buf := &bytes.Buffer{}
29+
if err := in.Encode(min, buf, true); err != nil {
30+
fmt.Println("Encoding Error", err)
31+
os.Exit(1)
32+
}
33+
34+
out := &MDIncrementalRefreshBook32{}
35+
if err := out.Decode(min, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
36+
fmt.Println("Decoding Error", err)
37+
os.Exit(1)
38+
}
39+
if len(out.NoMDEntries) != len(in.NoMDEntries) {
40+
fmt.Printf("expected %d entries, got %d\n", len(in.NoMDEntries), len(out.NoMDEntries))
41+
os.Exit(1)
42+
}
43+
44+
// decode a message with fewer entries on top of existing message
45+
in = &MDIncrementalRefreshBook32{
46+
TransactTime: 1,
47+
NoMDEntries: []MDIncrementalRefreshBook32NoMDEntries{
48+
{
49+
MDEntryPx: PRICENULL{},
50+
MDEntrySize: 5,
51+
SecurityID: 1,
52+
},
53+
},
54+
}
55+
buf.Reset()
56+
if err := in.Encode(min, buf, true); err != nil {
57+
fmt.Println("Encoding Error", err)
58+
os.Exit(1)
59+
}
60+
61+
if err := out.Decode(min, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil {
62+
fmt.Println("Decoding Error", err)
63+
os.Exit(1)
64+
}
65+
if len(out.NoMDEntries) != len(in.NoMDEntries) {
66+
fmt.Printf("expected %d entries, got %d\n", len(in.NoMDEntries), len(out.NoMDEntries))
67+
os.Exit(1)
68+
}
69+
}

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,7 @@ private int generateVarDataEncodeDecode(
11641164
"\t\tif cap(%1$c.%2$s) < int(%2$sLength) {\n" +
11651165
"\t\t\t%1$s.%2$s = make([]%5$s, %2$sLength)\n" +
11661166
"\t\t}\n" +
1167+
"\t\t%1$c.%2$s = %1$c.%2$s[:%2$sLength]\n" +
11671168
"\t\tif err := _m.ReadBytes(_r, %1$c.%2$s); err != nil {\n" +
11681169
"\t\t\treturn err\n" +
11691170
"\t\t}\n" +
@@ -1271,6 +1272,7 @@ private int generateGroupEncodeDecode(
12711272
"\t\tif cap(%1$c.%2$s) < int(%2$sNumInGroup) {\n" +
12721273
"\t\t\t%1$s.%2$s = make([]%3$s%2$s, %2$sNumInGroup)\n" +
12731274
"\t\t}\n" +
1275+
"\t\t%1$c.%2$s = %1$c.%2$s[:%2$sNumInGroup]\n" +
12741276
"\t\tfor i, _ := range %1$s.%2$s {\n" +
12751277
"\t\t\tif err := %1$s.%2$s[i].Decode(_m, _r, actingVersion, uint(%4$sBlockLength)); err != nil {\n" +
12761278
"\t\t\t\treturn err\n" +

0 commit comments

Comments
 (0)