ソースを参照

Forward oneof marshal/unmarshal funcs through public imports.

The collision of these two protocol buffer features does not work well in Go;
the best we can easily do is to handle the wire format. It'll operate poorly
when used with the text or JSON formats.
David Symonds 10 年 前
コミット
5baca1b631
2 ファイル変更37 行追加1 行削除
  1. 34 1
      protoc-gen-go/generator/generator.go
  2. 3 0
      protoc-gen-go/testdata/imp.proto

+ 34 - 1
protoc-gen-go/generator/generator.go

@@ -292,6 +292,7 @@ type symbol interface {
 type messageSymbol struct {
 	sym                         string
 	hasExtensions, isMessageSet bool
+	hasOneof                    bool
 	getters                     []getterSymbol
 }
 
@@ -321,6 +322,32 @@ func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) {
 				"{ return (*", remoteSym, ")(m).Unmarshal(buf) }")
 		}
 	}
+	if ms.hasOneof {
+		// Oneofs and public imports do not mix well.
+		// We can make them work okay for the binary format,
+		// but they're going to break weirdly for text/JSON.
+		enc := "_" + ms.sym + "_OneofMarshaler"
+		dec := "_" + ms.sym + "_OneofUnmarshaler"
+		encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error"
+		decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)"
+		g.P("func (m *", ms.sym, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", []interface{}) {")
+		g.P("return ", enc, ", ", dec, ", nil")
+		g.P("}")
+
+		g.P("func ", enc, encSig, " {")
+		g.P("m := msg.(*", ms.sym, ")")
+		g.P("m0 := (*", remoteSym, ")(m)")
+		g.P("enc, _, _ := m0.XXX_OneofFuncs()")
+		g.P("return enc(m0, b)")
+		g.P("}")
+
+		g.P("func ", dec, decSig, " {")
+		g.P("m := msg.(*", ms.sym, ")")
+		g.P("m0 := (*", remoteSym, ")(m)")
+		g.P("_, dec, _ := m0.XXX_OneofFuncs()")
+		g.P("return dec(m0, tag, wire, b)")
+		g.P("}")
+	}
 	for _, get := range ms.getters {
 
 		if get.typeName != "" {
@@ -2057,7 +2084,13 @@ func (g *Generator) generateMessage(message *Descriptor) {
 	}
 
 	if !message.group {
-		ms := &messageSymbol{sym: ccTypeName, hasExtensions: hasExtensions, isMessageSet: isMessageSet, getters: getters}
+		ms := &messageSymbol{
+			sym:           ccTypeName,
+			hasExtensions: hasExtensions,
+			isMessageSet:  isMessageSet,
+			hasOneof:      len(message.OneofDecl) > 0,
+			getters:       getters,
+		}
 		g.file.addExport(message, ms)
 	}
 

+ 3 - 0
protoc-gen-go/testdata/imp.proto

@@ -43,6 +43,9 @@ message ImportedMessage {
   optional ImportedMessage2 local_msg = 2;
   optional ForeignImportedMessage foreign_msg = 3;  // in imp3.proto
   optional Owner enum_field = 4;
+  oneof union {
+    int32 state = 9;
+  }
 
   repeated string name = 5;
   repeated Owner boss = 6;