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>
diff --git a/reflect/protoregistry/registry.go b/reflect/protoregistry/registry.go
index e190bda..5524452 100644
--- a/reflect/protoregistry/registry.go
+++ b/reflect/protoregistry/registry.go
@@ -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 @@
// 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 @@
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)
+ }
+}
diff --git a/reflect/protoregistry/registry_test.go b/reflect/protoregistry/registry_test.go
index 73a73a0..5be19b1 100644
--- a/reflect/protoregistry/registry_test.go
+++ b/reflect/protoregistry/registry_test.go
@@ -12,9 +12,13 @@
"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 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)
+ }
+ })
+}
diff --git a/reflect/protoregistry/testprotos/test.pb.go b/reflect/protoregistry/testprotos/test.pb.go
new file mode 100644
index 0000000..94362b3
--- /dev/null
+++ b/reflect/protoregistry/testprotos/test.pb.go
@@ -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,
+ },
+ },
+ },
+}
diff --git a/reflect/protoregistry/testprotos/test.proto b/reflect/protoregistry/testprotos/test.proto
new file mode 100644
index 0000000..5a4c77b
--- /dev/null
+++ b/reflect/protoregistry/testprotos/test.proto
@@ -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;
+ }
+}
diff --git a/regenerate.bash b/regenerate.bash
index d5ae4d8..534def4 100755
--- a/regenerate.bash
+++ b/regenerate.bash
@@ -53,3 +53,7 @@
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