Просмотр исходного кода

Register all proto message types with a centralised registry.

This will be exposed by a future API.

This has a small but negligible effect on binary sizes
(under 1% for average binaries; ~2.5% for the worst case I found),
but it'll make it more practical to support more dynamic proto use cases.
David Symonds 10 лет назад
Родитель
Сommit
a7f1e751cd

+ 16 - 0
proto/properties.go

@@ -37,6 +37,7 @@ package proto
 
 import (
 	"fmt"
+	"log"
 	"os"
 	"reflect"
 	"sort"
@@ -809,3 +810,18 @@ func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[
 func EnumValueMap(enumType string) map[string]int32 {
 	return enumValueMaps[enumType]
 }
+
+// A registry of all linked message types.
+// The key is a fully-qualified proto name ("pkg.Message").
+var protoTypes = make(map[string]reflect.Type)
+
+// RegisterType is called from generated code and maps from the fully qualified
+// proto name to the type (pointer to struct) of the protocol buffer.
+func RegisterType(x interface{}, name string) {
+	if _, ok := protoTypes[name]; ok {
+		// TODO: Some day, make this a panic.
+		log.Printf("proto: duplicate proto type registered: %s", name)
+		return
+	}
+	protoTypes[name] = reflect.TypeOf(x)
+}

+ 6 - 0
protoc-gen-go/generator/generator.go

@@ -2304,6 +2304,12 @@ func (g *Generator) generateMessage(message *Descriptor) {
 		g.generateExtension(ext)
 	}
 
+	fullName := strings.Join(message.TypeName(), ".")
+	if g.file.Package != nil {
+		fullName = *g.file.Package + "." + fullName
+	}
+
+	g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], ccTypeName, fullName)
 }
 
 func (g *Generator) generateExtension(ext *ExtensionDescriptor) {

+ 11 - 0
protoc-gen-go/testdata/my_test/test.pb.go

@@ -810,6 +810,17 @@ var E_Donut = &proto.ExtensionDesc{
 }
 
 func init() {
+	proto.RegisterType((*Request)(nil), "my.test.Request")
+	proto.RegisterType((*Request_SomeGroup)(nil), "my.test.Request.SomeGroup")
+	proto.RegisterType((*Reply)(nil), "my.test.Reply")
+	proto.RegisterType((*Reply_Entry)(nil), "my.test.Reply.Entry")
+	proto.RegisterType((*OtherBase)(nil), "my.test.OtherBase")
+	proto.RegisterType((*ReplyExtensions)(nil), "my.test.ReplyExtensions")
+	proto.RegisterType((*OtherReplyExtensions)(nil), "my.test.OtherReplyExtensions")
+	proto.RegisterType((*OldReply)(nil), "my.test.OldReply")
+	proto.RegisterType((*Communique)(nil), "my.test.Communique")
+	proto.RegisterType((*Communique_SomeGroup)(nil), "my.test.Communique.SomeGroup")
+	proto.RegisterType((*Communique_Delta)(nil), "my.test.Communique.Delta")
 	proto.RegisterEnum("my.test.HatType", HatType_name, HatType_value)
 	proto.RegisterEnum("my.test.Days", Days_name, Days_value)
 	proto.RegisterEnum("my.test.Request_Color", Request_Color_name, Request_Color_value)

+ 11 - 0
protoc-gen-go/testdata/my_test/test.pb.go.golden

@@ -810,6 +810,17 @@ var E_Donut = &proto.ExtensionDesc{
 }
 
 func init() {
+	proto.RegisterType((*Request)(nil), "my.test.Request")
+	proto.RegisterType((*Request_SomeGroup)(nil), "my.test.Request.SomeGroup")
+	proto.RegisterType((*Reply)(nil), "my.test.Reply")
+	proto.RegisterType((*Reply_Entry)(nil), "my.test.Reply.Entry")
+	proto.RegisterType((*OtherBase)(nil), "my.test.OtherBase")
+	proto.RegisterType((*ReplyExtensions)(nil), "my.test.ReplyExtensions")
+	proto.RegisterType((*OtherReplyExtensions)(nil), "my.test.OtherReplyExtensions")
+	proto.RegisterType((*OldReply)(nil), "my.test.OldReply")
+	proto.RegisterType((*Communique)(nil), "my.test.Communique")
+	proto.RegisterType((*Communique_SomeGroup)(nil), "my.test.Communique.SomeGroup")
+	proto.RegisterType((*Communique_Delta)(nil), "my.test.Communique.Delta")
 	proto.RegisterEnum("my.test.HatType", HatType_name, HatType_value)
 	proto.RegisterEnum("my.test.Days", Days_name, Days_value)
 	proto.RegisterEnum("my.test.Request_Color", Request_Color_name, Request_Color_value)