reflect/protoregistry: add Types registry

The first commit of protoregistry only added a registry for files.
However, a separate type of registry is needed to provide a mapping between
protobuf names and actual Go types representing those names.

Additional high-level API:
    var GlobalTypes = new(Types)
    type Type interface{ ... }
    type Types struct{ ... }
        func NewTypes(...Type) *Types
        func (*Types) Register(...Type) error
        func (*Types) FindEnumByName(pref.FullName) (pref.EnumType, error)
        func (*Types) FindMessageByName(pref.FullName) (pref.MessageType, error)
        func (*Types) FindMessageByURL(string) (pref.MessageType, error)
        func (*Types) FindExtensionByName(pref.FullName) (pref.ExtensionType, error)
        func (*Types) FindExtensionByNumber(pref.FullName, pref.FieldNumber) (pref.ExtensionType, error)
        func (*Types) RangeEnums(func(pref.EnumType) bool)
        func (*Types) RangeMessages(func(pref.MessageType) bool)
        func (*Types) RangeExtensions(func(pref.ExtensionType) bool)
        func (*Types) RangeExtensionsByMessage(pref.FullName, func(pref.ExtensionType) bool)

Change-Id: I0d07705801684a1eb5853bcd05fcce12598a0047
Reviewed-on: https://go-review.googlesource.com/c/131345
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Herbie Ong 2018-12-26 15:57:16 -08:00
parent cf25308dea
commit 6e67a1d614
5 changed files with 1339 additions and 26 deletions

View File

@ -4,9 +4,20 @@
// Package protoregistry provides data structures to register and lookup
// protobuf descriptor types.
//
// The Files registry contains file descriptors and provides the ability
// to iterate over the files or lookup a specific descriptor within the files.
// Files only contains protobuf descriptors and has no understanding of Go
// type information that may be associated with each descriptor.
//
// The Types registry contains descriptor types for which there is a known
// Go type associated with that descriptor. It provides the ability to iterate
// over the registered types or lookup a type by name.
package protoregistry
import (
"fmt"
"reflect"
"sort"
"strings"
@ -19,33 +30,12 @@ import (
// registration issues. This presumes that we provide a way to disable automatic
// registration in generated code.
// TODO: Add a type registry:
/*
var GlobalTypes = new(Types)
type Type interface {
protoreflect.Descriptor
GoType() reflect.Type
}
type Types struct {
Parent *Types
Resolver func(url string) (Type, error)
}
func NewTypes(typs ...Type) *Types
func (*Types) Register(typs ...Type) error
func (*Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error)
func (*Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error)
func (*Types) FindMessageByURL(url string) (protoreflect.MessageType, error)
func (*Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
func (*Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
func (*Types) RangeEnums(f func(protoreflect.EnumType) bool)
func (*Types) RangeMessages(f func(protoreflect.MessageType) bool)
func (*Types) RangeExtensions(f func(protoreflect.ExtensionType) bool)
func (*Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
*/
// GlobalFiles is a global registry of file descriptors.
var GlobalFiles = new(Files)
var GlobalFiles *Files = new(Files)
// GlobalTypes is the registry used by default for type lookups
// unless a local registry is provided by the user.
var GlobalTypes *Types = new(Types)
// NotFound is a sentinel error value to indicate that the type was not found.
var NotFound = errors.New("not found")
@ -298,3 +288,337 @@ func rangeTopLevelDeclarations(fd protoreflect.FileDescriptor, f func(protorefle
f(fd.Services().Get(i).Name())
}
}
// Type is an interface satisfied by protoreflect.EnumType,
// protoreflect.MessageType, or protoreflect.ExtensionType.
type Type interface {
protoreflect.Descriptor
GoType() reflect.Type
}
var (
_ Type = protoreflect.EnumType(nil)
_ Type = protoreflect.MessageType(nil)
_ Type = protoreflect.ExtensionType(nil)
)
// Types is a registry for looking up or iterating over descriptor types.
// The Find and Range methods are safe for concurrent use.
type Types struct {
// Parent sets the parent registry to consult if a find operation
// could not locate the appropriate entry.
//
// Setting a parent results in each Range operation also iterating over the
// entries contained within the parent. In such a case, it is possible for
// Range to emit duplicates (since they may exist in both child and parent).
// Range iteration is guaranteed to iterate over local entries before
// iterating over parent entries.
Parent *Types
// Resolver sets the local resolver to consult if the local registry does
// not contain an entry. The resolver takes precedence over the parent.
//
// The url is a URL where the full name of the type is the last segment
// of the path (i.e. string following the last '/' character).
// When missing a '/' character, the URL is the full name of the type.
// See documentation on the google.protobuf.Any.type_url field for details.
//
// If the resolver returns a result, it is not automatically registered
// into the local registry. Thus, a resolver function should cache results
// such that it deterministically returns the same result given the
// same URL assuming the error returned is nil or NotFound.
//
// If the resolver returns the NotFound error, the registry will consult the
// parent registry if it is set.
//
// Setting a resolver has no effect on the result of each Range operation.
Resolver func(url string) (Type, error)
// TODO: The syntax of the URL is ill-defined and the protobuf team recently
// changed the documented semantics in a way that breaks prior usages.
// I do not believe they can do this and need to sync up with the
// protobuf team again to hash out what the proper syntax of the URL is.
// TODO: Should we separate this out as a registry for each type?
//
// In Java, the extension and message registry are distinct classes.
// Their extension registry has knowledge of distinct Java types,
// while their message registry only contains descriptor information.
//
// In Go, we have always registered messages, enums, and extensions.
// Messages and extensions are registered with Go information, while enums
// are only registered with descriptor information. We cannot drop Go type
// information for messages otherwise we would be unable to implement
// portions of the v1 API such as ptypes.DynamicAny.
//
// There is no enum registry in Java. In v1, we used the enum registry
// because enum types provided no reflective methods. The addition of
// ProtoReflect removes that need.
typesByName typesByName
extensionsByMessage extensionsByMessage
}
type (
typesByName map[protoreflect.FullName]Type
extensionsByMessage map[protoreflect.FullName]extensionsByNumber
extensionsByNumber map[protoreflect.FieldNumber]protoreflect.ExtensionType
)
// NewTypes returns a registry initialized with the provided set of types.
// If there are conflicts, the first one takes precedence.
func NewTypes(typs ...Type) *Types {
// TODO: Allow setting resolver and parent via constructor?
r := new(Types)
r.Register(typs...) // ignore errors; first takes precedence
return r
}
// Register registers the provided list of descriptor types.
//
// If a registration conflict occurs for enum, message, or extension types
// (e.g., two different types have the same full name),
// then the first type takes precedence and an error is returned.
func (r *Types) Register(typs ...Type) error {
var firstErr error
typeLoop:
for _, typ := range typs {
switch typ.(type) {
case protoreflect.EnumType, protoreflect.MessageType, protoreflect.ExtensionType:
// Check for conflicts in typesByName.
name := typ.FullName()
if r.typesByName[name] != nil {
if firstErr == nil {
firstErr = errors.New("%v %v is already registered", typeName(typ), name)
}
continue typeLoop
}
// Check for conflicts in extensionsByMessage.
if xt, _ := typ.(protoreflect.ExtensionType); xt != nil {
field := xt.Number()
message := xt.ExtendedType().FullName()
if r.extensionsByMessage[message][field] != nil {
if firstErr == nil {
firstErr = errors.New("extension %v is already registered on message %v", name, message)
}
continue typeLoop
}
// Update extensionsByMessage.
if r.extensionsByMessage == nil {
r.extensionsByMessage = make(extensionsByMessage)
}
if r.extensionsByMessage[message] == nil {
r.extensionsByMessage[message] = make(extensionsByNumber)
}
r.extensionsByMessage[message][field] = xt
}
// Update typesByName.
if r.typesByName == nil {
r.typesByName = make(typesByName)
}
r.typesByName[name] = typ
default:
if firstErr == nil {
firstErr = errors.New("invalid type: %v", typeName(typ))
}
}
}
return firstErr
}
// FindEnumByName looks up an enum by its full name.
// E.g., "google.protobuf.Field.Kind".
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) {
r.globalCheck()
if r == nil {
return nil, NotFound
}
v, _ := r.typesByName[enum]
if v == nil && r.Resolver != nil {
var err error
v, err = r.Resolver(string(enum))
if err != nil && err != NotFound {
return nil, err
}
}
if v != nil {
if et, _ := v.(protoreflect.EnumType); et != nil {
return et, nil
}
return nil, errors.New("found wrong type: got %v, want enum", typeName(v))
}
return r.Parent.FindEnumByName(enum)
}
// FindMessageByName looks up a message by its full name.
// E.g., "google.protobuf.Any"
//
// This return (nil, NotFound) if not found.
func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
// The full name by itself is a valid URL.
return r.FindMessageByURL(string(message))
}
// FindMessageByURL looks up a message by a URL identifier.
// See Resolver for the format of the URL.
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
r.globalCheck()
if r == nil {
return nil, NotFound
}
message := protoreflect.FullName(url)
if i := strings.LastIndexByte(url, '/'); i >= 0 {
message = message[i+len("/"):]
}
v, _ := r.typesByName[message]
if v == nil && r.Resolver != nil {
var err error
v, err = r.Resolver(url)
if err != nil && err != NotFound {
return nil, err
}
}
if v != nil {
if mt, _ := v.(protoreflect.MessageType); mt != nil {
return mt, nil
}
return nil, errors.New("found wrong type: got %v, want message", typeName(v))
}
return r.Parent.FindMessageByURL(url)
}
// FindExtensionByName looks up a extension field by the field's full name.
// Note that this is the full name of the field as determined by
// where the extension is declared and is unrelated to the full name of the
// message being extended.
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
r.globalCheck()
if r == nil {
return nil, NotFound
}
v, _ := r.typesByName[field]
if v == nil && r.Resolver != nil {
var err error
v, err = r.Resolver(string(field))
if err != nil && err != NotFound {
return nil, err
}
}
if v != nil {
if xt, _ := v.(protoreflect.ExtensionType); xt != nil {
return xt, nil
}
return nil, errors.New("found wrong type: got %v, want extension", typeName(v))
}
return r.Parent.FindExtensionByName(field)
}
// FindExtensionByNumber looks up a extension field by the field number
// within some parent message, identified by full name.
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
r.globalCheck()
if r == nil {
return nil, NotFound
}
if xt, ok := r.extensionsByMessage[message][field]; ok {
return xt, nil
}
return r.Parent.FindExtensionByNumber(message, field)
}
// RangeEnums iterates over all registered enums.
// Iteration order is undefined.
func (r *Types) RangeEnums(f func(protoreflect.EnumType) bool) {
r.globalCheck()
if r == nil {
return
}
for _, typ := range r.typesByName {
if et, ok := typ.(protoreflect.EnumType); ok {
if !f(et) {
return
}
}
}
r.Parent.RangeEnums(f)
}
// RangeMessages iterates over all registered messages.
// Iteration order is undefined.
func (r *Types) RangeMessages(f func(protoreflect.MessageType) bool) {
r.globalCheck()
if r == nil {
return
}
for _, typ := range r.typesByName {
if mt, ok := typ.(protoreflect.MessageType); ok {
if !f(mt) {
return
}
}
}
r.Parent.RangeMessages(f)
}
// RangeExtensions iterates over all registered extensions.
// Iteration order is undefined.
func (r *Types) RangeExtensions(f func(protoreflect.ExtensionType) bool) {
r.globalCheck()
if r == nil {
return
}
for _, typ := range r.typesByName {
if xt, ok := typ.(protoreflect.ExtensionType); ok {
if !f(xt) {
return
}
}
}
r.Parent.RangeExtensions(f)
}
// RangeExtensionsByMessage iterates over all registered extensions filtered
// by a given message type. Iteration order is undefined.
func (r *Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) {
r.globalCheck()
if r == nil {
return
}
for _, xt := range r.extensionsByMessage[message] {
if !f(xt) {
return
}
}
r.Parent.RangeExtensionsByMessage(message, f)
}
func (r *Types) globalCheck() {
if r == GlobalTypes && (r.Parent != nil || r.Resolver != nil) {
panic("GlobalTypes.Parent and GlobalTypes.Resolver cannot be set")
}
}
func typeName(t Type) string {
switch t.(type) {
case protoreflect.EnumType:
return "enum"
case protoreflect.MessageType:
return "message"
case protoreflect.ExtensionType:
return "extension"
default:
return fmt.Sprintf("%T", t)
}
}

View File

@ -12,9 +12,13 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/golang/protobuf/protoapi"
"github.com/golang/protobuf/v2/internal/legacy"
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
preg "github.com/golang/protobuf/v2/reflect/protoregistry"
ptype "github.com/golang/protobuf/v2/reflect/prototype"
testpb "github.com/golang/protobuf/v2/reflect/protoregistry/testprotos"
)
func TestFiles(t *testing.T) {
@ -312,3 +316,357 @@ func TestFiles(t *testing.T) {
})
}
}
func extensionType(xd *protoapi.ExtensionDesc) pref.ExtensionType {
return legacy.Export{}.ExtensionTypeFromDesc(xd)
}
func TestTypes(t *testing.T) {
// Suffix 1 in registry, 2 in parent, 3 in resolver.
mt1 := (&testpb.Message1{}).ProtoReflect().Type()
mt2 := (&testpb.Message2{}).ProtoReflect().Type()
mt3 := (&testpb.Message3{}).ProtoReflect().Type()
et1 := testpb.Enum1_ONE.ProtoReflect().Type()
et2 := testpb.Enum2_UNO.ProtoReflect().Type()
et3 := testpb.Enum3_YI.ProtoReflect().Type()
// Suffix indicates field number.
xt11 := extensionType(testpb.E_StringField)
xt12 := extensionType(testpb.E_EnumField)
xt13 := extensionType(testpb.E_MessageField)
xt21 := extensionType(testpb.E_Message4_MessageField)
xt22 := extensionType(testpb.E_Message4_EnumField)
xt23 := extensionType(testpb.E_Message4_StringField)
parent := &preg.Types{}
if err := parent.Register(mt2, et2, xt12, xt22); err != nil {
t.Fatalf("parent.Register() returns unexpected error: %v", err)
}
registry := &preg.Types{
Parent: parent,
Resolver: func(url string) (preg.Type, error) {
switch {
case strings.HasSuffix(url, "testprotos.Message3"):
return mt3, nil
case strings.HasSuffix(url, "testprotos.Enum3"):
return et3, nil
case strings.HasSuffix(url, "testprotos.message_field"):
return xt13, nil
case strings.HasSuffix(url, "testprotos.Message4.string_field"):
return xt23, nil
}
return nil, preg.NotFound
},
}
if err := registry.Register(mt1, et1, xt11, xt21); err != nil {
t.Fatalf("registry.Register() returns unexpected error: %v", err)
}
t.Run("FindMessageByName", func(t *testing.T) {
tests := []struct {
name string
messageType pref.MessageType
wantErr bool
wantNotFound bool
}{{
name: "testprotos.Message1",
messageType: mt1,
}, {
name: "testprotos.Message2",
messageType: mt2,
}, {
name: "testprotos.Message3",
messageType: mt3,
}, {
name: "testprotos.NoSuchMessage",
wantErr: true,
wantNotFound: true,
}, {
name: "testprotos.Enum1",
wantErr: true,
}, {
name: "testprotos.Enum2",
wantErr: true,
}, {
name: "testprotos.Enum3",
wantErr: true,
}}
for _, tc := range tests {
got, err := registry.FindMessageByName(pref.FullName(tc.name))
gotErr := err != nil
if gotErr != tc.wantErr {
t.Errorf("FindMessageByName(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
continue
}
if tc.wantNotFound && err != preg.NotFound {
t.Errorf("FindMessageByName(%v) got error: %v, want NotFound error", tc.name, err)
continue
}
if got != tc.messageType {
t.Errorf("FindMessageByName(%v) got wrong value: %v", tc.name, got)
}
}
})
t.Run("FindMessageByURL", func(t *testing.T) {
tests := []struct {
name string
messageType pref.MessageType
wantErr bool
wantNotFound bool
}{{
name: "testprotos.Message1",
messageType: mt1,
}, {
name: "foo.com/testprotos.Message2",
messageType: mt2,
}, {
name: "/testprotos.Message3",
messageType: mt3,
}, {
name: "type.googleapis.com/testprotos.Nada",
wantErr: true,
wantNotFound: true,
}, {
name: "testprotos.Enum1",
wantErr: true,
}}
for _, tc := range tests {
got, err := registry.FindMessageByURL(tc.name)
gotErr := err != nil
if gotErr != tc.wantErr {
t.Errorf("FindMessageByURL(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
continue
}
if tc.wantNotFound && err != preg.NotFound {
t.Errorf("FindMessageByURL(%v) got error: %v, want NotFound error", tc.name, err)
continue
}
if got != tc.messageType {
t.Errorf("FindMessageByURL(%v) got wrong value: %v", tc.name, got)
}
}
})
t.Run("FindEnumByName", func(t *testing.T) {
tests := []struct {
name string
enumType pref.EnumType
wantErr bool
wantNotFound bool
}{{
name: "testprotos.Enum1",
enumType: et1,
}, {
name: "testprotos.Enum2",
enumType: et2,
}, {
name: "testprotos.Enum3",
enumType: et3,
}, {
name: "testprotos.None",
wantErr: true,
wantNotFound: true,
}, {
name: "testprotos.Message1",
wantErr: true,
}}
for _, tc := range tests {
got, err := registry.FindEnumByName(pref.FullName(tc.name))
gotErr := err != nil
if gotErr != tc.wantErr {
t.Errorf("FindEnumByName(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
continue
}
if tc.wantNotFound && err != preg.NotFound {
t.Errorf("FindEnumByName(%v) got error: %v, want NotFound error", tc.name, err)
continue
}
if got != tc.enumType {
t.Errorf("FindEnumByName(%v) got wrong value: %v", tc.name, got)
}
}
})
t.Run("FindExtensionByName", func(t *testing.T) {
tests := []struct {
name string
extensionType pref.ExtensionType
wantErr bool
wantNotFound bool
}{{
name: "testprotos.string_field",
extensionType: xt11,
}, {
name: "testprotos.enum_field",
extensionType: xt12,
}, {
name: "testprotos.message_field",
extensionType: xt13,
}, {
name: "testprotos.Message4.message_field",
extensionType: xt21,
}, {
name: "testprotos.Message4.enum_field",
extensionType: xt22,
}, {
name: "testprotos.Message4.string_field",
extensionType: xt23,
}, {
name: "testprotos.None",
wantErr: true,
wantNotFound: true,
}, {
name: "testprotos.Message1",
wantErr: true,
}}
for _, tc := range tests {
got, err := registry.FindExtensionByName(pref.FullName(tc.name))
gotErr := err != nil
if gotErr != tc.wantErr {
t.Errorf("FindExtensionByName(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
continue
}
if tc.wantNotFound && err != preg.NotFound {
t.Errorf("FindExtensionByName(%v) got error: %v, want NotFound error", tc.name, err)
continue
}
if got != tc.extensionType {
t.Errorf("FindExtensionByName(%v) got wrong value: %v", tc.name, got)
}
}
})
t.Run("FindExtensionByNumber", func(t *testing.T) {
tests := []struct {
parent string
number int32
extensionType pref.ExtensionType
wantErr bool
wantNotFound bool
}{{
parent: "testprotos.Message1",
number: 11,
extensionType: xt11,
}, {
parent: "testprotos.Message1",
number: 12,
extensionType: xt12,
}, {
// FindExtensionByNumber does not use Resolver.
parent: "testprotos.Message1",
number: 13,
wantErr: true,
wantNotFound: true,
}, {
parent: "testprotos.Message1",
number: 21,
extensionType: xt21,
}, {
parent: "testprotos.Message1",
number: 22,
extensionType: xt22,
}, {
// FindExtensionByNumber does not use Resolver.
parent: "testprotos.Message1",
number: 23,
wantErr: true,
wantNotFound: true,
}, {
parent: "testprotos.NoSuchMessage",
number: 11,
wantErr: true,
wantNotFound: true,
}, {
parent: "testprotos.Message1",
number: 30,
wantErr: true,
wantNotFound: true,
}, {
parent: "testprotos.Message1",
number: 99,
wantErr: true,
wantNotFound: true,
}}
for _, tc := range tests {
got, err := registry.FindExtensionByNumber(pref.FullName(tc.parent), pref.FieldNumber(tc.number))
gotErr := err != nil
if gotErr != tc.wantErr {
t.Errorf("FindExtensionByNumber(%v, %d) = (_, %v), want error? %t", tc.parent, tc.number, err, tc.wantErr)
continue
}
if tc.wantNotFound && err != preg.NotFound {
t.Errorf("FindExtensionByNumber(%v, %d) got error %v, want NotFound error", tc.parent, tc.number, err)
continue
}
if got != tc.extensionType {
t.Errorf("FindExtensionByNumber(%v, %d) got wrong value: %v", tc.parent, tc.number, got)
}
}
})
sortTypes := cmpopts.SortSlices(func(x, y preg.Type) bool {
return x.FullName() < y.FullName()
})
compare := cmp.Comparer(func(x, y preg.Type) bool {
return x == y
})
t.Run("RangeMessages", func(t *testing.T) {
// RangeMessages do not include messages from Resolver.
want := []preg.Type{mt1, mt2}
var got []preg.Type
registry.RangeMessages(func(mt pref.MessageType) bool {
got = append(got, mt)
return true
})
diff := cmp.Diff(want, got, sortTypes, compare)
if diff != "" {
t.Errorf("RangeMessages() mismatch (-want +got):\n%v", diff)
}
})
t.Run("RangeEnums", func(t *testing.T) {
// RangeEnums do not include enums from Resolver.
want := []preg.Type{et1, et2}
var got []preg.Type
registry.RangeEnums(func(et pref.EnumType) bool {
got = append(got, et)
return true
})
diff := cmp.Diff(want, got, sortTypes, compare)
if diff != "" {
t.Errorf("RangeEnums() mismatch (-want +got):\n%v", diff)
}
})
t.Run("RangeExtensions", func(t *testing.T) {
// RangeExtensions do not include messages from Resolver.
want := []preg.Type{xt11, xt12, xt21, xt22}
var got []preg.Type
registry.RangeExtensions(func(xt pref.ExtensionType) bool {
got = append(got, xt)
return true
})
diff := cmp.Diff(want, got, sortTypes, compare)
if diff != "" {
t.Errorf("RangeExtensions() mismatch (-want +got):\n%v", diff)
}
})
t.Run("RangeExtensionsByMessage", func(t *testing.T) {
// RangeExtensions do not include messages from Resolver.
want := []preg.Type{xt11, xt12, xt21, xt22}
var got []preg.Type
registry.RangeExtensionsByMessage(pref.FullName("testprotos.Message1"), func(xt pref.ExtensionType) bool {
got = append(got, xt)
return true
})
diff := cmp.Diff(want, got, sortTypes, compare)
if diff != "" {
t.Errorf("RangeExtensionsByMessage() mismatch (-want +got):\n%v", diff)
}
})
}

View File

@ -0,0 +1,582 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: reflect/protoregistry/testprotos/test.proto
package testprotos
import (
proto "github.com/golang/protobuf/proto"
protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
prototype "github.com/golang/protobuf/v2/reflect/prototype"
protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Enum1 int32
const (
Enum1_ONE Enum1 = 1
)
type xxx_Enum1 Enum1
func (e Enum1) ProtoReflect() protoreflect.Enum {
return (xxx_Enum1)(e)
}
func (e xxx_Enum1) Type() protoreflect.EnumType {
return xxx_Test_ProtoFile_EnumTypes[0]
}
func (e xxx_Enum1) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(e)
}
var Enum1_name = map[int32]string{
1: "ONE",
}
var Enum1_value = map[string]int32{
"ONE": 1,
}
func (x Enum1) Enum() *Enum1 {
p := new(Enum1)
*p = x
return p
}
func (x Enum1) String() string {
return proto.EnumName(Enum1_name, int32(x))
}
func (x *Enum1) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(Enum1_value, data, "Enum1")
if err != nil {
return err
}
*x = Enum1(value)
return nil
}
func (Enum1) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_3628d63611f7063d, []int{0}
}
type Enum2 int32
const (
Enum2_UNO Enum2 = 1
)
type xxx_Enum2 Enum2
func (e Enum2) ProtoReflect() protoreflect.Enum {
return (xxx_Enum2)(e)
}
func (e xxx_Enum2) Type() protoreflect.EnumType {
return xxx_Test_ProtoFile_EnumTypes[1]
}
func (e xxx_Enum2) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(e)
}
var Enum2_name = map[int32]string{
1: "UNO",
}
var Enum2_value = map[string]int32{
"UNO": 1,
}
func (x Enum2) Enum() *Enum2 {
p := new(Enum2)
*p = x
return p
}
func (x Enum2) String() string {
return proto.EnumName(Enum2_name, int32(x))
}
func (x *Enum2) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(Enum2_value, data, "Enum2")
if err != nil {
return err
}
*x = Enum2(value)
return nil
}
func (Enum2) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_3628d63611f7063d, []int{1}
}
type Enum3 int32
const (
Enum3_YI Enum3 = 1
)
type xxx_Enum3 Enum3
func (e Enum3) ProtoReflect() protoreflect.Enum {
return (xxx_Enum3)(e)
}
func (e xxx_Enum3) Type() protoreflect.EnumType {
return xxx_Test_ProtoFile_EnumTypes[2]
}
func (e xxx_Enum3) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(e)
}
var Enum3_name = map[int32]string{
1: "YI",
}
var Enum3_value = map[string]int32{
"YI": 1,
}
func (x Enum3) Enum() *Enum3 {
p := new(Enum3)
*p = x
return p
}
func (x Enum3) String() string {
return proto.EnumName(Enum3_name, int32(x))
}
func (x *Enum3) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(Enum3_value, data, "Enum3")
if err != nil {
return err
}
*x = Enum3(value)
return nil
}
func (Enum3) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_3628d63611f7063d, []int{2}
}
type Message1 struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type xxx_Message1 struct{ m *Message1 }
func (m *Message1) ProtoReflect() protoreflect.Message {
return xxx_Message1{m}
}
func (m xxx_Message1) Type() protoreflect.MessageType {
return xxx_Test_ProtoFile_MessageTypes[0].Type
}
func (m xxx_Message1) KnownFields() protoreflect.KnownFields {
return xxx_Test_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
}
func (m xxx_Message1) UnknownFields() protoreflect.UnknownFields {
return xxx_Test_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
}
func (m xxx_Message1) Interface() protoreflect.ProtoMessage {
return m.m
}
func (m *Message1) Reset() { *m = Message1{} }
func (m *Message1) String() string { return proto.CompactTextString(m) }
func (*Message1) ProtoMessage() {}
func (*Message1) Descriptor() ([]byte, []int) {
return fileDescriptor_3628d63611f7063d, []int{0}
}
var extRange_Message1 = []proto.ExtensionRange{
{Start: 10, End: 536870911},
}
func (*Message1) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_Message1
}
func (m *Message1) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message1.Unmarshal(m, b)
}
func (m *Message1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message1.Marshal(b, m, deterministic)
}
func (m *Message1) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message1.Merge(m, src)
}
func (m *Message1) XXX_Size() int {
return xxx_messageInfo_Message1.Size(m)
}
func (m *Message1) XXX_DiscardUnknown() {
xxx_messageInfo_Message1.DiscardUnknown(m)
}
var xxx_messageInfo_Message1 proto.InternalMessageInfo
type Message2 struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type xxx_Message2 struct{ m *Message2 }
func (m *Message2) ProtoReflect() protoreflect.Message {
return xxx_Message2{m}
}
func (m xxx_Message2) Type() protoreflect.MessageType {
return xxx_Test_ProtoFile_MessageTypes[1].Type
}
func (m xxx_Message2) KnownFields() protoreflect.KnownFields {
return xxx_Test_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
}
func (m xxx_Message2) UnknownFields() protoreflect.UnknownFields {
return xxx_Test_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
}
func (m xxx_Message2) Interface() protoreflect.ProtoMessage {
return m.m
}
func (m *Message2) Reset() { *m = Message2{} }
func (m *Message2) String() string { return proto.CompactTextString(m) }
func (*Message2) ProtoMessage() {}
func (*Message2) Descriptor() ([]byte, []int) {
return fileDescriptor_3628d63611f7063d, []int{1}
}
func (m *Message2) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message2.Unmarshal(m, b)
}
func (m *Message2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message2.Marshal(b, m, deterministic)
}
func (m *Message2) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message2.Merge(m, src)
}
func (m *Message2) XXX_Size() int {
return xxx_messageInfo_Message2.Size(m)
}
func (m *Message2) XXX_DiscardUnknown() {
xxx_messageInfo_Message2.DiscardUnknown(m)
}
var xxx_messageInfo_Message2 proto.InternalMessageInfo
type Message3 struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type xxx_Message3 struct{ m *Message3 }
func (m *Message3) ProtoReflect() protoreflect.Message {
return xxx_Message3{m}
}
func (m xxx_Message3) Type() protoreflect.MessageType {
return xxx_Test_ProtoFile_MessageTypes[2].Type
}
func (m xxx_Message3) KnownFields() protoreflect.KnownFields {
return xxx_Test_ProtoFile_MessageTypes[2].KnownFieldsOf(m.m)
}
func (m xxx_Message3) UnknownFields() protoreflect.UnknownFields {
return xxx_Test_ProtoFile_MessageTypes[2].UnknownFieldsOf(m.m)
}
func (m xxx_Message3) Interface() protoreflect.ProtoMessage {
return m.m
}
func (m *Message3) Reset() { *m = Message3{} }
func (m *Message3) String() string { return proto.CompactTextString(m) }
func (*Message3) ProtoMessage() {}
func (*Message3) Descriptor() ([]byte, []int) {
return fileDescriptor_3628d63611f7063d, []int{2}
}
func (m *Message3) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message3.Unmarshal(m, b)
}
func (m *Message3) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message3.Marshal(b, m, deterministic)
}
func (m *Message3) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message3.Merge(m, src)
}
func (m *Message3) XXX_Size() int {
return xxx_messageInfo_Message3.Size(m)
}
func (m *Message3) XXX_DiscardUnknown() {
xxx_messageInfo_Message3.DiscardUnknown(m)
}
var xxx_messageInfo_Message3 proto.InternalMessageInfo
type Message4 struct {
BoolField *bool `protobuf:"varint,30,opt,name=bool_field,json=boolField" json:"bool_field,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type xxx_Message4 struct{ m *Message4 }
func (m *Message4) ProtoReflect() protoreflect.Message {
return xxx_Message4{m}
}
func (m xxx_Message4) Type() protoreflect.MessageType {
return xxx_Test_ProtoFile_MessageTypes[3].Type
}
func (m xxx_Message4) KnownFields() protoreflect.KnownFields {
return xxx_Test_ProtoFile_MessageTypes[3].KnownFieldsOf(m.m)
}
func (m xxx_Message4) UnknownFields() protoreflect.UnknownFields {
return xxx_Test_ProtoFile_MessageTypes[3].UnknownFieldsOf(m.m)
}
func (m xxx_Message4) Interface() protoreflect.ProtoMessage {
return m.m
}
func (m *Message4) Reset() { *m = Message4{} }
func (m *Message4) String() string { return proto.CompactTextString(m) }
func (*Message4) ProtoMessage() {}
func (*Message4) Descriptor() ([]byte, []int) {
return fileDescriptor_3628d63611f7063d, []int{3}
}
func (m *Message4) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message4.Unmarshal(m, b)
}
func (m *Message4) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message4.Marshal(b, m, deterministic)
}
func (m *Message4) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message4.Merge(m, src)
}
func (m *Message4) XXX_Size() int {
return xxx_messageInfo_Message4.Size(m)
}
func (m *Message4) XXX_DiscardUnknown() {
xxx_messageInfo_Message4.DiscardUnknown(m)
}
var xxx_messageInfo_Message4 proto.InternalMessageInfo
func (m *Message4) GetBoolField() bool {
if m != nil && m.BoolField != nil {
return *m.BoolField
}
return false
}
var E_StringField = &proto.ExtensionDesc{
ExtendedType: (*Message1)(nil),
ExtensionType: (*string)(nil),
Field: 11,
Name: "testprotos.string_field",
Tag: "bytes,11,opt,name=string_field",
Filename: "reflect/protoregistry/testprotos/test.proto",
}
var E_EnumField = &proto.ExtensionDesc{
ExtendedType: (*Message1)(nil),
ExtensionType: (*Enum1)(nil),
Field: 12,
Name: "testprotos.enum_field",
Tag: "varint,12,opt,name=enum_field,enum=testprotos.Enum1",
Filename: "reflect/protoregistry/testprotos/test.proto",
}
var E_MessageField = &proto.ExtensionDesc{
ExtendedType: (*Message1)(nil),
ExtensionType: (*Message2)(nil),
Field: 13,
Name: "testprotos.message_field",
Tag: "bytes,13,opt,name=message_field",
Filename: "reflect/protoregistry/testprotos/test.proto",
}
var E_Message4_MessageField = &proto.ExtensionDesc{
ExtendedType: (*Message1)(nil),
ExtensionType: (*Message2)(nil),
Field: 21,
Name: "testprotos.Message4.message_field",
Tag: "bytes,21,opt,name=message_field",
Filename: "reflect/protoregistry/testprotos/test.proto",
}
var E_Message4_EnumField = &proto.ExtensionDesc{
ExtendedType: (*Message1)(nil),
ExtensionType: (*Enum1)(nil),
Field: 22,
Name: "testprotos.Message4.enum_field",
Tag: "varint,22,opt,name=enum_field,enum=testprotos.Enum1",
Filename: "reflect/protoregistry/testprotos/test.proto",
}
var E_Message4_StringField = &proto.ExtensionDesc{
ExtendedType: (*Message1)(nil),
ExtensionType: (*string)(nil),
Field: 23,
Name: "testprotos.Message4.string_field",
Tag: "bytes,23,opt,name=string_field",
Filename: "reflect/protoregistry/testprotos/test.proto",
}
func init() {
proto.RegisterFile("reflect/protoregistry/testprotos/test.proto", fileDescriptor_3628d63611f7063d)
proto.RegisterEnum("testprotos.Enum1", Enum1_name, Enum1_value)
proto.RegisterEnum("testprotos.Enum2", Enum2_name, Enum2_value)
proto.RegisterEnum("testprotos.Enum3", Enum3_name, Enum3_value)
proto.RegisterType((*Message1)(nil), "testprotos.Message1")
proto.RegisterType((*Message2)(nil), "testprotos.Message2")
proto.RegisterType((*Message3)(nil), "testprotos.Message3")
proto.RegisterType((*Message4)(nil), "testprotos.Message4")
proto.RegisterExtension(E_StringField)
proto.RegisterExtension(E_EnumField)
proto.RegisterExtension(E_MessageField)
proto.RegisterExtension(E_Message4_MessageField)
proto.RegisterExtension(E_Message4_EnumField)
proto.RegisterExtension(E_Message4_StringField)
}
var fileDescriptor_3628d63611f7063d = []byte{
// 304 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2e, 0x4a, 0x4d, 0xcb,
0x49, 0x4d, 0x2e, 0xd1, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x2f, 0x4a, 0x4d, 0xcf, 0x2c, 0x2e, 0x29,
0xaa, 0xd4, 0x2f, 0x49, 0x2d, 0x2e, 0x01, 0x8b, 0x14, 0x83, 0x99, 0x7a, 0x60, 0xb6, 0x10, 0x17,
0x42, 0x58, 0x49, 0x84, 0x8b, 0xc3, 0x37, 0xb5, 0xb8, 0x38, 0x31, 0x3d, 0xd5, 0x50, 0x8b, 0x83,
0x83, 0x4b, 0xa0, 0xa1, 0xa1, 0xa1, 0x81, 0x49, 0x89, 0x0b, 0x2e, 0x6a, 0x84, 0xc4, 0x36, 0x56,
0xfa, 0xcd, 0x08, 0xe7, 0x98, 0x08, 0xc9, 0x72, 0x71, 0x25, 0xe5, 0xe7, 0xe7, 0xc4, 0xa7, 0x65,
0xa6, 0xe6, 0xa4, 0x48, 0xc8, 0x29, 0x30, 0x6a, 0x70, 0x04, 0x71, 0x82, 0x44, 0xdc, 0x40, 0x02,
0x46, 0xfe, 0x5c, 0xbc, 0xb9, 0x10, 0xa5, 0x10, 0x15, 0x42, 0x22, 0x7a, 0x08, 0x7b, 0xf5, 0x60,
0x96, 0x4a, 0x88, 0x2a, 0x30, 0x6a, 0x70, 0x1b, 0x61, 0x93, 0x33, 0x0a, 0xe2, 0x81, 0x1a, 0x00,
0x31, 0xd0, 0x8d, 0x8b, 0x2b, 0x35, 0xaf, 0x34, 0x17, 0xaf, 0x69, 0x62, 0x0a, 0x8c, 0x1a, 0x7c,
0x46, 0x82, 0xc8, 0x72, 0xae, 0x79, 0xa5, 0xb9, 0x86, 0x41, 0x9c, 0x20, 0xad, 0x10, 0x73, 0xcc,
0xb9, 0x78, 0x8a, 0x4b, 0x8a, 0x32, 0xf3, 0xd2, 0xf1, 0x9a, 0x24, 0xae, 0xc0, 0xa8, 0xc1, 0x19,
0xc4, 0x0d, 0x51, 0x09, 0xd6, 0xa8, 0x25, 0xc0, 0xc5, 0x0a, 0x36, 0x4c, 0x88, 0x9d, 0x8b, 0xd9,
0xdf, 0xcf, 0x55, 0x80, 0x11, 0x26, 0x62, 0x04, 0x12, 0x09, 0xf5, 0xf3, 0x17, 0x60, 0xd4, 0xe2,
0x87, 0x88, 0x18, 0x0b, 0xb1, 0x71, 0x31, 0x45, 0x7a, 0x0a, 0x30, 0x5a, 0x11, 0x67, 0x1b, 0x37,
0x86, 0x6d, 0x56, 0xc4, 0x78, 0x97, 0x87, 0xb0, 0x77, 0xad, 0x88, 0x8c, 0x07, 0x5e, 0x62, 0xe3,
0xc1, 0xc9, 0x21, 0xca, 0x2e, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x3f,
0x3d, 0x3f, 0x27, 0x31, 0x2f, 0x1d, 0x92, 0xee, 0x92, 0x4a, 0xd3, 0xf4, 0xcb, 0x8c, 0xf4, 0x09,
0xa5, 0x45, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x76, 0x64, 0x81, 0x59, 0xae, 0x02, 0x00, 0x00,
}
func init() {
xxx_Test_ProtoFile_FileDesc.Enums = xxx_Test_ProtoFile_EnumDescs[0:3]
xxx_Test_ProtoFile_FileDesc.Messages = xxx_Test_ProtoFile_MessageDescs[0:4]
var err error
Test_ProtoFile, err = prototype.NewFile(&xxx_Test_ProtoFile_FileDesc)
if err != nil {
panic(err)
}
}
const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
var Test_ProtoFile protoreflect.FileDescriptor
var xxx_Test_ProtoFile_FileDesc = prototype.File{
Syntax: protoreflect.Proto2,
Path: "reflect/protoregistry/testprotos/test.proto",
Package: "testprotos",
}
var xxx_Test_ProtoFile_EnumTypes = [3]protoreflect.EnumType{
prototype.GoEnum(
xxx_Test_ProtoFile_EnumDescs[0].Reference(),
func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
return Enum1(n)
},
),
prototype.GoEnum(
xxx_Test_ProtoFile_EnumDescs[1].Reference(),
func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
return Enum2(n)
},
),
prototype.GoEnum(
xxx_Test_ProtoFile_EnumDescs[2].Reference(),
func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
return Enum3(n)
},
),
}
var xxx_Test_ProtoFile_EnumDescs = [3]prototype.Enum{
{
Name: "Enum1",
Values: []prototype.EnumValue{
{Name: "ONE", Number: 1},
},
},
{
Name: "Enum2",
Values: []prototype.EnumValue{
{Name: "UNO", Number: 1},
},
},
{
Name: "Enum3",
Values: []prototype.EnumValue{
{Name: "YI", Number: 1},
},
},
}
var xxx_Test_ProtoFile_MessageTypes = [4]protoimpl.MessageType{
{Type: prototype.GoMessage(
xxx_Test_ProtoFile_MessageDescs[0].Reference(),
func(protoreflect.MessageType) protoreflect.ProtoMessage {
return new(Message1)
},
)},
{Type: prototype.GoMessage(
xxx_Test_ProtoFile_MessageDescs[1].Reference(),
func(protoreflect.MessageType) protoreflect.ProtoMessage {
return new(Message2)
},
)},
{Type: prototype.GoMessage(
xxx_Test_ProtoFile_MessageDescs[2].Reference(),
func(protoreflect.MessageType) protoreflect.ProtoMessage {
return new(Message3)
},
)},
{Type: prototype.GoMessage(
xxx_Test_ProtoFile_MessageDescs[3].Reference(),
func(protoreflect.MessageType) protoreflect.ProtoMessage {
return new(Message4)
},
)},
}
var xxx_Test_ProtoFile_MessageDescs = [4]prototype.Message{
{
Name: "Message1",
ExtensionRanges: [][2]protoreflect.FieldNumber{{10, 536870912}},
},
{
Name: "Message2",
},
{
Name: "Message3",
},
{
Name: "Message4",
Fields: []prototype.Field{
{
Name: "bool_field",
Number: 30,
Cardinality: protoreflect.Optional,
Kind: protoreflect.BoolKind,
JSONName: "boolField",
IsPacked: prototype.False,
},
},
},
}

View File

@ -0,0 +1,45 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Different proto type definitions for testing the Types registry.
syntax = "proto2";
package testprotos;
option go_package = "github.com/golang/protobuf/v2/reflect/protoregistry/testprotos";
message Message1 {
extensions 10 to max;
}
message Message2 {}
message Message3 {}
enum Enum1 {
ONE = 1;
}
enum Enum2 {
UNO = 1;
}
enum Enum3 {
YI = 1;
}
extend Message1 {
optional string string_field = 11;
optional Enum1 enum_field = 12;
optional Message2 message_field = 13;
}
message Message4 {
optional bool bool_field = 30;
extend Message1 {
optional Message2 message_field = 21;
optional Enum1 enum_field = 22;
optional string string_field = 23;
}
}

View File

@ -53,3 +53,7 @@ cp $tmpdir/src/google/protobuf/compiler/plugin.pb.go ./types/plugin/plugin.pb.go
echo "# encoding/textpb/testprotos/pb?/test.proto"
PROTOC_GEN_GO_ENABLE_REFLECT=1 protoc --go_out=paths=source_relative:. \
encoding/textpb/testprotos/pb?/test.proto
echo "# reflect/protoregistry/testprotos/test.proto"
PROTOC_GEN_GO_ENABLE_REFLECT=1 protoc --go_out=paths=source_relative:. \
reflect/protoregistry/testprotos/test.proto