From 535a10468679b4cf155f6a7afdf53b554633fc09 Mon Sep 17 00:00:00 2001 From: David Symonds Date: Fri, 11 Sep 2015 08:27:00 +1000 Subject: [PATCH] Fix size of oneof fields when they are set to their zero value. We use the proto3 sizers for oneof fields (because they don't have a pointer in the wrapper struct), but they are always encoded when set, so we should not skip their zero value. Fixes #74. --- .../jsonpb_test_proto/more_test_objects.pb.go | 5 ++ jsonpb/jsonpb_test_proto/test_objects.pb.go | 4 +- proto/encode.go | 14 ++-- proto/properties.go | 6 ++ proto/size_test.go | 1 + proto/testdata/test.pb.go | 74 +++++++++---------- protoc-gen-go/generator/generator.go | 48 ++++++++++-- protoc-gen-go/testdata/imp.proto | 2 + protoc-gen-go/testdata/my_test/test.pb.go | 20 ++--- .../testdata/my_test/test.pb.go.golden | 20 ++--- 10 files changed, 122 insertions(+), 72 deletions(-) diff --git a/jsonpb/jsonpb_test_proto/more_test_objects.pb.go b/jsonpb/jsonpb_test_proto/more_test_objects.pb.go index 263485309f..e9a09769aa 100644 --- a/jsonpb/jsonpb_test_proto/more_test_objects.pb.go +++ b/jsonpb/jsonpb_test_proto/more_test_objects.pb.go @@ -12,6 +12,11 @@ It is generated from these files: It has these top-level messages: Simple3 Mappy + Simple + Repeats + Widget + Maps + MsgWithOneof */ package jsonpb diff --git a/jsonpb/jsonpb_test_proto/test_objects.pb.go b/jsonpb/jsonpb_test_proto/test_objects.pb.go index 8c5b025aa8..fd45129728 100644 --- a/jsonpb/jsonpb_test_proto/test_objects.pb.go +++ b/jsonpb/jsonpb_test_proto/test_objects.pb.go @@ -341,10 +341,10 @@ type isMsgWithOneof_Union interface { } type MsgWithOneof_Title struct { - Title string `protobuf:"bytes,1,opt,name=title"` + Title string `protobuf:"bytes,1,opt,name=title,oneof"` } type MsgWithOneof_Salary struct { - Salary int64 `protobuf:"varint,2,opt,name=salary"` + Salary int64 `protobuf:"varint,2,opt,name=salary,oneof"` } func (*MsgWithOneof_Title) isMsgWithOneof_Union() {} diff --git a/proto/encode.go b/proto/encode.go index fe48cc743d..89d0caa826 100644 --- a/proto/encode.go +++ b/proto/encode.go @@ -332,7 +332,7 @@ func size_bool(p *Properties, base structPointer) int { func size_proto3_bool(p *Properties, base structPointer) int { v := *structPointer_BoolVal(base, p.field) - if !v { + if !v && !p.oneof { return 0 } return len(p.tagcode) + 1 // each bool takes exactly one byte @@ -375,7 +375,7 @@ func size_int32(p *Properties, base structPointer) (n int) { func size_proto3_int32(p *Properties, base structPointer) (n int) { v := structPointer_Word32Val(base, p.field) x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 { + if x == 0 && !p.oneof { return 0 } n += len(p.tagcode) @@ -421,7 +421,7 @@ func size_uint32(p *Properties, base structPointer) (n int) { func size_proto3_uint32(p *Properties, base structPointer) (n int) { v := structPointer_Word32Val(base, p.field) x := word32Val_Get(v) - if x == 0 { + if x == 0 && !p.oneof { return 0 } n += len(p.tagcode) @@ -466,7 +466,7 @@ func size_int64(p *Properties, base structPointer) (n int) { func size_proto3_int64(p *Properties, base structPointer) (n int) { v := structPointer_Word64Val(base, p.field) x := word64Val_Get(v) - if x == 0 { + if x == 0 && !p.oneof { return 0 } n += len(p.tagcode) @@ -509,7 +509,7 @@ func size_string(p *Properties, base structPointer) (n int) { func size_proto3_string(p *Properties, base structPointer) (n int) { v := *structPointer_StringVal(base, p.field) - if v == "" { + if v == "" && !p.oneof { return 0 } n += len(p.tagcode) @@ -681,7 +681,7 @@ func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error func size_slice_byte(p *Properties, base structPointer) (n int) { s := *structPointer_Bytes(base, p.field) - if s == nil { + if s == nil && !p.oneof { return 0 } n += len(p.tagcode) @@ -691,7 +691,7 @@ func size_slice_byte(p *Properties, base structPointer) (n int) { func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { s := *structPointer_Bytes(base, p.field) - if len(s) == 0 { + if len(s) == 0 && !p.oneof { return 0 } n += len(p.tagcode) diff --git a/proto/properties.go b/proto/properties.go index 692fe4310e..bbca4daf05 100644 --- a/proto/properties.go +++ b/proto/properties.go @@ -177,6 +177,7 @@ type Properties struct { Packed bool // relevant for repeated primitives only Enum string // set for enum types only proto3 bool // whether this is known to be a proto3 field; set for []byte only + oneof bool // whether this is a oneof field Default string // default value HasDefault bool // whether an explicit default was provided @@ -229,6 +230,9 @@ func (p *Properties) String() string { if p.proto3 { s += ",proto3" } + if p.oneof { + s += ",oneof" + } if len(p.Enum) > 0 { s += ",enum=" + p.Enum } @@ -305,6 +309,8 @@ func (p *Properties) Parse(s string) { p.Enum = f[5:] case f == "proto3": p.proto3 = true + case f == "oneof": + p.oneof = true case strings.HasPrefix(f, "def="): p.HasDefault = true p.Default = f[4:] // rest of string diff --git a/proto/size_test.go b/proto/size_test.go index 53806a37c3..40c393ff27 100644 --- a/proto/size_test.go +++ b/proto/size_test.go @@ -126,6 +126,7 @@ var SizeTests = []struct { {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, {"oneof not set", &pb.Communique{}}, + {"oneof zero int32", &pb.Communique{Union: &pb.Communique_Number{0}}}, {"oneof int32", &pb.Communique{Union: &pb.Communique_Number{3}}}, {"oneof string", &pb.Communique{Union: &pb.Communique_Name{"Rhythmic Fman"}}}, } diff --git a/proto/testdata/test.pb.go b/proto/testdata/test.pb.go index c22fe31239..7d308086ee 100644 --- a/proto/testdata/test.pb.go +++ b/proto/testdata/test.pb.go @@ -304,8 +304,8 @@ func (m *GoEnum) GetFoo() FOO { } type GoTestField struct { - Label *string `protobuf:"bytes,1,req" json:"Label,omitempty"` - Type *string `protobuf:"bytes,2,req" json:"Type,omitempty"` + Label *string `protobuf:"bytes,1,req,name=Label" json:"Label,omitempty"` + Type *string `protobuf:"bytes,2,req,name=Type" json:"Type,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -329,13 +329,13 @@ func (m *GoTestField) GetType() string { type GoTest struct { // Some typical parameters - Kind *GoTest_KIND `protobuf:"varint,1,req,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` - Table *string `protobuf:"bytes,2,opt" json:"Table,omitempty"` - Param *int32 `protobuf:"varint,3,opt" json:"Param,omitempty"` + Kind *GoTest_KIND `protobuf:"varint,1,req,name=Kind,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` + Table *string `protobuf:"bytes,2,opt,name=Table" json:"Table,omitempty"` + Param *int32 `protobuf:"varint,3,opt,name=Param" json:"Param,omitempty"` // Required, repeated and optional foreign fields. - RequiredField *GoTestField `protobuf:"bytes,4,req" json:"RequiredField,omitempty"` - RepeatedField []*GoTestField `protobuf:"bytes,5,rep" json:"RepeatedField,omitempty"` - OptionalField *GoTestField `protobuf:"bytes,6,opt" json:"OptionalField,omitempty"` + RequiredField *GoTestField `protobuf:"bytes,4,req,name=RequiredField" json:"RequiredField,omitempty"` + RepeatedField []*GoTestField `protobuf:"bytes,5,rep,name=RepeatedField" json:"RepeatedField,omitempty"` + OptionalField *GoTestField `protobuf:"bytes,6,opt,name=OptionalField" json:"OptionalField,omitempty"` // Required fields of all basic types F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required" json:"F_Bool_required,omitempty"` F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required" json:"F_Int32_required,omitempty"` @@ -936,7 +936,7 @@ func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup { // Required, repeated, and optional groups. type GoTest_RequiredGroup struct { - RequiredField *string `protobuf:"bytes,71,req" json:"RequiredField,omitempty"` + RequiredField *string `protobuf:"bytes,71,req,name=RequiredField" json:"RequiredField,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -952,7 +952,7 @@ func (m *GoTest_RequiredGroup) GetRequiredField() string { } type GoTest_RepeatedGroup struct { - RequiredField *string `protobuf:"bytes,81,req" json:"RequiredField,omitempty"` + RequiredField *string `protobuf:"bytes,81,req,name=RequiredField" json:"RequiredField,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -968,7 +968,7 @@ func (m *GoTest_RepeatedGroup) GetRequiredField() string { } type GoTest_OptionalGroup struct { - RequiredField *string `protobuf:"bytes,91,req" json:"RequiredField,omitempty"` + RequiredField *string `protobuf:"bytes,91,req,name=RequiredField" json:"RequiredField,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -1514,7 +1514,7 @@ func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} type MessageList struct { - Message []*MessageList_Message `protobuf:"group,1,rep" json:"message,omitempty"` + Message []*MessageList_Message `protobuf:"group,1,rep,name=Message" json:"message,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -1580,24 +1580,24 @@ func (m *Strings) GetBytesField() []byte { type Defaults struct { // Default-valued fields of all basic types. // Same as GoTest, but copied here to make testing easier. - F_Bool *bool `protobuf:"varint,1,opt,def=1" json:"F_Bool,omitempty"` - F_Int32 *int32 `protobuf:"varint,2,opt,def=32" json:"F_Int32,omitempty"` - F_Int64 *int64 `protobuf:"varint,3,opt,def=64" json:"F_Int64,omitempty"` - F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,def=320" json:"F_Fixed32,omitempty"` - F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,def=640" json:"F_Fixed64,omitempty"` - F_Uint32 *uint32 `protobuf:"varint,6,opt,def=3200" json:"F_Uint32,omitempty"` - F_Uint64 *uint64 `protobuf:"varint,7,opt,def=6400" json:"F_Uint64,omitempty"` - F_Float *float32 `protobuf:"fixed32,8,opt,def=314159" json:"F_Float,omitempty"` - F_Double *float64 `protobuf:"fixed64,9,opt,def=271828" json:"F_Double,omitempty"` - F_String *string `protobuf:"bytes,10,opt,def=hello, \"world!\"\n" json:"F_String,omitempty"` - F_Bytes []byte `protobuf:"bytes,11,opt,def=Bignose" json:"F_Bytes,omitempty"` - F_Sint32 *int32 `protobuf:"zigzag32,12,opt,def=-32" json:"F_Sint32,omitempty"` - F_Sint64 *int64 `protobuf:"zigzag64,13,opt,def=-64" json:"F_Sint64,omitempty"` - F_Enum *Defaults_Color `protobuf:"varint,14,opt,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` + F_Bool *bool `protobuf:"varint,1,opt,name=F_Bool,def=1" json:"F_Bool,omitempty"` + F_Int32 *int32 `protobuf:"varint,2,opt,name=F_Int32,def=32" json:"F_Int32,omitempty"` + F_Int64 *int64 `protobuf:"varint,3,opt,name=F_Int64,def=64" json:"F_Int64,omitempty"` + F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,def=320" json:"F_Fixed32,omitempty"` + F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,def=640" json:"F_Fixed64,omitempty"` + F_Uint32 *uint32 `protobuf:"varint,6,opt,name=F_Uint32,def=3200" json:"F_Uint32,omitempty"` + F_Uint64 *uint64 `protobuf:"varint,7,opt,name=F_Uint64,def=6400" json:"F_Uint64,omitempty"` + F_Float *float32 `protobuf:"fixed32,8,opt,name=F_Float,def=314159" json:"F_Float,omitempty"` + F_Double *float64 `protobuf:"fixed64,9,opt,name=F_Double,def=271828" json:"F_Double,omitempty"` + F_String *string `protobuf:"bytes,10,opt,name=F_String,def=hello, \"world!\"\n" json:"F_String,omitempty"` + F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,def=Bignose" json:"F_Bytes,omitempty"` + F_Sint32 *int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,def=-32" json:"F_Sint32,omitempty"` + F_Sint64 *int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,def=-64" json:"F_Sint64,omitempty"` + F_Enum *Defaults_Color `protobuf:"varint,14,opt,name=F_Enum,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` // More fields with crazy defaults. - F_Pinf *float32 `protobuf:"fixed32,15,opt,def=inf" json:"F_Pinf,omitempty"` - F_Ninf *float32 `protobuf:"fixed32,16,opt,def=-inf" json:"F_Ninf,omitempty"` - F_Nan *float32 `protobuf:"fixed32,17,opt,def=nan" json:"F_Nan,omitempty"` + F_Pinf *float32 `protobuf:"fixed32,15,opt,name=F_Pinf,def=inf" json:"F_Pinf,omitempty"` + F_Ninf *float32 `protobuf:"fixed32,16,opt,name=F_Ninf,def=-inf" json:"F_Ninf,omitempty"` + F_Nan *float32 `protobuf:"fixed32,17,opt,name=F_Nan,def=nan" json:"F_Nan,omitempty"` // Sub-message. Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"` // Redundant but explicit defaults. @@ -1862,7 +1862,7 @@ func (m *MoreRepeated) GetFixeds() []uint32 { } type GroupOld struct { - G *GroupOld_G `protobuf:"group,101,opt" json:"g,omitempty"` + G *GroupOld_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -1894,7 +1894,7 @@ func (m *GroupOld_G) GetX() int32 { } type GroupNew struct { - G *GroupNew_G `protobuf:"group,101,opt" json:"g,omitempty"` + G *GroupNew_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -2013,22 +2013,22 @@ type isCommunique_Union interface { } type Communique_Number struct { - Number int32 `protobuf:"varint,5,opt,name=number"` + Number int32 `protobuf:"varint,5,opt,name=number,oneof"` } type Communique_Name struct { - Name string `protobuf:"bytes,6,opt,name=name"` + Name string `protobuf:"bytes,6,opt,name=name,oneof"` } type Communique_Data struct { - Data []byte `protobuf:"bytes,7,opt,name=data"` + Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` } type Communique_TempC struct { - TempC float64 `protobuf:"fixed64,8,opt,name=temp_c"` + TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,oneof"` } type Communique_Col struct { - Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color"` + Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color,oneof"` } type Communique_Msg struct { - Msg *Strings `protobuf:"bytes,10,opt,name=msg"` + Msg *Strings `protobuf:"bytes,10,opt,name=msg,oneof"` } func (*Communique_Number) isCommunique_Union() {} diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go index fa1fcb9c21..182c2dbdae 100644 --- a/protoc-gen-go/generator/generator.go +++ b/protoc-gen-go/generator/generator.go @@ -303,7 +303,7 @@ type getterSymbol struct { name string typ string typeName string // canonical name in proto world; empty for proto.Message and similar - genType bool // whether typ is a generated type (message/group/enum) + genType bool // whether typ contains a generated type (message/group/enum) } func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) { @@ -333,15 +333,19 @@ func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) { typ := get.typ val := "(*" + remoteSym + ")(m)." + get.name + "()" if get.genType { - // typ will be "*pkg.T" (message/group) or "pkg.T" (enum). - // Either of those might have a "[]" prefix if it is repeated. - // Drop the package qualifier since we have hoisted the type into this package. + // typ will be "*pkg.T" (message/group) or "pkg.T" (enum) + // or "map[t]*pkg.T" (map to message/enum). + // The first two of those might have a "[]" prefix if it is repeated. + // Drop any package qualifier since we have hoisted the type into this package. rep := strings.HasPrefix(typ, "[]") if rep { typ = typ[2:] } + isMap := strings.HasPrefix(typ, "map[") star := typ[0] == '*' - typ = typ[strings.Index(typ, ".")+1:] + if !isMap { // map types handled lower down + typ = typ[strings.Index(typ, ".")+1:] + } if star { typ = "*" + typ } @@ -376,6 +380,30 @@ func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) { g.P("}") continue } + if isMap { + // Split map[keyTyp]valTyp. + bra, ket := strings.Index(typ, "["), strings.Index(typ, "]") + keyTyp, valTyp := typ[bra+1:ket], typ[ket+1:] + // Drop any package qualifier. + // Only the value type may be foreign. + star := valTyp[0] == '*' + valTyp = valTyp[strings.Index(valTyp, ".")+1:] + if star { + valTyp = "*" + valTyp + } + + typ := "map[" + keyTyp + "]" + valTyp + g.P("func (m *", ms.sym, ") ", get.name, "() ", typ, " {") + g.P("o := ", val) + g.P("if o == nil { return nil }") + g.P("s := make(", typ, ", len(o))") + g.P("for k, v := range o {") + g.P("s[k] = (", valTyp, ")(v)") + g.P("}") + g.P("return s") + g.P("}") + continue + } // Convert imported type into the forwarding type. val = "(" + typ + ")(" + val + ")" } @@ -863,6 +891,9 @@ func wrapImported(file *descriptor.FileDescriptorProto, g *Generator) (sl []*Imp for _, index := range file.PublicDependency { df := g.fileByName(file.Dependency[index]) for _, d := range df.desc { + if d.GetOptions().GetMapEntry() { + continue + } sl = append(sl, &ImportedDescriptor{common{file}, d}) } for _, e := range df.enum { @@ -1433,13 +1464,18 @@ func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptor name += ",proto3" } } - return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s", + oneof := "" + if field.OneofIndex != nil { + oneof = ",oneof" + } + return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s", wiretype, field.GetNumber(), optrepreq, packed, name, enum, + oneof, defaultValue)) } diff --git a/protoc-gen-go/testdata/imp.proto b/protoc-gen-go/testdata/imp.proto index 42f144e4dd..83f97d5a27 100644 --- a/protoc-gen-go/testdata/imp.proto +++ b/protoc-gen-go/testdata/imp.proto @@ -48,6 +48,8 @@ message ImportedMessage { repeated Owner boss = 6; repeated ImportedMessage2 memo = 7; + map msg_map = 8; + enum Owner { DAVE = 1; MIKE = 2; diff --git a/protoc-gen-go/testdata/my_test/test.pb.go b/protoc-gen-go/testdata/my_test/test.pb.go index d7ea8c8833..51acfaddf9 100644 --- a/protoc-gen-go/testdata/my_test/test.pb.go +++ b/protoc-gen-go/testdata/my_test/test.pb.go @@ -489,34 +489,34 @@ type isCommunique_Union interface { } type Communique_Number struct { - Number int32 `protobuf:"varint,5,opt,name=number"` + Number int32 `protobuf:"varint,5,opt,name=number,oneof"` } type Communique_Name struct { - Name string `protobuf:"bytes,6,opt,name=name"` + Name string `protobuf:"bytes,6,opt,name=name,oneof"` } type Communique_Data struct { - Data []byte `protobuf:"bytes,7,opt,name=data"` + Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` } type Communique_TempC struct { - TempC float64 `protobuf:"fixed64,8,opt,name=temp_c"` + TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,oneof"` } type Communique_Height struct { - Height float32 `protobuf:"fixed32,9,opt,name=height"` + Height float32 `protobuf:"fixed32,9,opt,name=height,oneof"` } type Communique_Today struct { - Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days"` + Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days,oneof"` } type Communique_Maybe struct { - Maybe bool `protobuf:"varint,11,opt,name=maybe"` + Maybe bool `protobuf:"varint,11,opt,name=maybe,oneof"` } type Communique_Delta_ struct { - Delta int32 `protobuf:"zigzag32,12,opt,name=delta"` + Delta int32 `protobuf:"zigzag32,12,opt,name=delta,oneof"` } type Communique_Msg struct { - Msg *Reply `protobuf:"bytes,13,opt,name=msg"` + Msg *Reply `protobuf:"bytes,13,opt,name=msg,oneof"` } type Communique_Somegroup struct { - Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup"` + Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup,oneof"` } func (*Communique_Number) isCommunique_Union() {} diff --git a/protoc-gen-go/testdata/my_test/test.pb.go.golden b/protoc-gen-go/testdata/my_test/test.pb.go.golden index d7ea8c8833..51acfaddf9 100644 --- a/protoc-gen-go/testdata/my_test/test.pb.go.golden +++ b/protoc-gen-go/testdata/my_test/test.pb.go.golden @@ -489,34 +489,34 @@ type isCommunique_Union interface { } type Communique_Number struct { - Number int32 `protobuf:"varint,5,opt,name=number"` + Number int32 `protobuf:"varint,5,opt,name=number,oneof"` } type Communique_Name struct { - Name string `protobuf:"bytes,6,opt,name=name"` + Name string `protobuf:"bytes,6,opt,name=name,oneof"` } type Communique_Data struct { - Data []byte `protobuf:"bytes,7,opt,name=data"` + Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` } type Communique_TempC struct { - TempC float64 `protobuf:"fixed64,8,opt,name=temp_c"` + TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,oneof"` } type Communique_Height struct { - Height float32 `protobuf:"fixed32,9,opt,name=height"` + Height float32 `protobuf:"fixed32,9,opt,name=height,oneof"` } type Communique_Today struct { - Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days"` + Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days,oneof"` } type Communique_Maybe struct { - Maybe bool `protobuf:"varint,11,opt,name=maybe"` + Maybe bool `protobuf:"varint,11,opt,name=maybe,oneof"` } type Communique_Delta_ struct { - Delta int32 `protobuf:"zigzag32,12,opt,name=delta"` + Delta int32 `protobuf:"zigzag32,12,opt,name=delta,oneof"` } type Communique_Msg struct { - Msg *Reply `protobuf:"bytes,13,opt,name=msg"` + Msg *Reply `protobuf:"bytes,13,opt,name=msg,oneof"` } type Communique_Somegroup struct { - Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup"` + Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup,oneof"` } func (*Communique_Number) isCommunique_Union() {}