Skip to content

Commit 54814e4

Browse files
authored
Merge pull request #130 from howardjohn/oneof/fix
Fix marshalling of empty oneOf messages
2 parents ec98e72 + d579c53 commit 54814e4

File tree

8 files changed

+160
-9
lines changed

8 files changed

+160
-9
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package conformance
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
"google.golang.org/protobuf/proto"
8+
)
9+
10+
func TestEmptyOneoff(t *testing.T) {
11+
// Regression test for https://github.com/planetscale/vtprotobuf/issues/61
12+
msg := &TestAllTypesProto3{OneofField: &TestAllTypesProto3_OneofNestedMessage{}}
13+
upstream, _ := proto.Marshal(msg)
14+
vt, _ := msg.MarshalVTStrict()
15+
require.Equal(t, upstream, vt)
16+
}

conformance/internal/conformance/test_messages_proto2_vtproto.pb.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

conformance/internal/conformance/test_messages_proto3_vtproto.pb.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

features/marshal/marshalto.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"strings"
1313

1414
"github.com/planetscale/vtprotobuf/generator"
15-
1615
"google.golang.org/protobuf/compiler/protogen"
1716
"google.golang.org/protobuf/encoding/protowire"
1817
"google.golang.org/protobuf/reflect/protoreflect"
@@ -520,7 +519,14 @@ func (p *marshal) field(oneof bool, numGen *counter, field *protogen.Field) {
520519
default:
521520
panic("not implemented")
522521
}
523-
if repeated || nullable {
522+
// Empty protobufs should emit a message or compatibility with Golang protobuf;
523+
// See https://github.com/planetscale/vtprotobuf/issues/61
524+
if oneof && field.Desc.Kind() == protoreflect.MessageKind && !field.Desc.IsMap() && !field.Desc.IsList() {
525+
p.P("} else {")
526+
p.P("i = protohelpers.EncodeVarint(dAtA, i, 0)")
527+
p.encodeKey(fieldNumber, wireType)
528+
p.P("}")
529+
} else if repeated || nullable {
524530
p.P(`}`)
525531
}
526532
}
@@ -676,7 +682,7 @@ func (p *marshal) message(message *protogen.Message) {
676682
p.P(`}`)
677683
p.P()
678684

679-
//Generate MarshalToVT methods for oneof fields
685+
// Generate MarshalToVT methods for oneof fields
680686
for _, field := range message.Fields {
681687
if field.Oneof == nil || field.Oneof.Desc.IsSynthetic() {
682688
continue
@@ -709,7 +715,6 @@ func (p *marshal) marshalBackwardSize(varInt bool) {
709715
if varInt {
710716
p.encodeVarint(`size`)
711717
}
712-
713718
}
714719

715720
func (p *marshal) marshalBackward(varName string, varInt bool, message *protogen.Message) {

features/size/size.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ package size
88
import (
99
"strconv"
1010

11+
"github.com/planetscale/vtprotobuf/generator"
1112
"google.golang.org/protobuf/compiler/protogen"
1213
"google.golang.org/protobuf/encoding/protowire"
1314
"google.golang.org/protobuf/reflect/protoreflect"
14-
15-
"github.com/planetscale/vtprotobuf/generator"
1615
)
1716

1817
func init() {
@@ -266,7 +265,12 @@ func (p *size) field(oneof bool, field *protogen.Field, sizeName string) {
266265
default:
267266
panic("not implemented")
268267
}
269-
if repeated || nullable {
268+
// Empty protobufs should emit a message or compatibility with Golang protobuf;
269+
// See https://github.com/planetscale/vtprotobuf/issues/61
270+
// Size is always 3 so just hardcode that here
271+
if oneof && field.Desc.Kind() == protoreflect.MessageKind && !field.Desc.IsMap() && !field.Desc.IsList() {
272+
p.P("} else { n += 3 }")
273+
} else if repeated || nullable {
270274
p.P(`}`)
271275
}
272276
}
@@ -310,8 +314,6 @@ func (p *size) message(message *protogen.Message) {
310314
}
311315
p.P(`}`)
312316
} else {
313-
//if _, ok := oneofs[fieldname]; !ok {
314-
//oneofs[fieldname] = struct{}{}
315317
p.P(`if vtmsg, ok := m.`, fieldname, `.(interface{ SizeVT() int }); ok {`)
316318
p.P(`n+=vtmsg.`, sizeName, `()`)
317319
p.P(`}`)

testproto/pool/pool_with_oneof_vtproto.pb.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)