[VOL-5486] Upgrade library versions
Change-Id: I8b4e88699e03f44ee13e467867f45ae3f0a63c4b
Signed-off-by: Abhay Kumar <abhay.kumar@radisys.com>
diff --git a/vendor/github.com/jhump/protoreflect/desc/cache.go b/vendor/github.com/jhump/protoreflect/desc/cache.go
new file mode 100644
index 0000000..418632b
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/cache.go
@@ -0,0 +1,48 @@
+package desc
+
+import (
+ "sync"
+
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+type descriptorCache interface {
+ get(protoreflect.Descriptor) Descriptor
+ put(protoreflect.Descriptor, Descriptor)
+}
+
+type lockingCache struct {
+ cacheMu sync.RWMutex
+ cache mapCache
+}
+
+func (c *lockingCache) get(d protoreflect.Descriptor) Descriptor {
+ c.cacheMu.RLock()
+ defer c.cacheMu.RUnlock()
+ return c.cache.get(d)
+}
+
+func (c *lockingCache) put(key protoreflect.Descriptor, val Descriptor) {
+ c.cacheMu.Lock()
+ defer c.cacheMu.Unlock()
+ c.cache.put(key, val)
+}
+
+func (c *lockingCache) withLock(fn func(descriptorCache)) {
+ c.cacheMu.Lock()
+ defer c.cacheMu.Unlock()
+ // Pass the underlying mapCache. We don't want fn to use
+ // c.get or c.put sine we already have the lock. So those
+ // methods would try to re-acquire and then deadlock!
+ fn(c.cache)
+}
+
+type mapCache map[protoreflect.Descriptor]Descriptor
+
+func (c mapCache) get(d protoreflect.Descriptor) Descriptor {
+ return c[d]
+}
+
+func (c mapCache) put(key protoreflect.Descriptor, val Descriptor) {
+ c[key] = val
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/convert.go b/vendor/github.com/jhump/protoreflect/desc/convert.go
index 538820c..01a6e9e 100644
--- a/vendor/github.com/jhump/protoreflect/desc/convert.go
+++ b/vendor/github.com/jhump/protoreflect/desc/convert.go
@@ -5,7 +5,10 @@
"fmt"
"strings"
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/reflect/protodesc"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+ "google.golang.org/protobuf/types/descriptorpb"
"github.com/jhump/protoreflect/desc/internal"
intn "github.com/jhump/protoreflect/internal"
@@ -15,34 +18,87 @@
// The file's direct dependencies must be provided. If the given dependencies do not include
// all of the file's dependencies or if the contents of the descriptors are internally
// inconsistent (e.g. contain unresolvable symbols) then an error is returned.
-func CreateFileDescriptor(fd *dpb.FileDescriptorProto, deps ...*FileDescriptor) (*FileDescriptor, error) {
+func CreateFileDescriptor(fd *descriptorpb.FileDescriptorProto, deps ...*FileDescriptor) (*FileDescriptor, error) {
return createFileDescriptor(fd, deps, nil)
}
-func createFileDescriptor(fd *dpb.FileDescriptorProto, deps []*FileDescriptor, r *ImportResolver) (*FileDescriptor, error) {
+type descResolver struct {
+ files []*FileDescriptor
+ importResolver *ImportResolver
+ fromPath string
+}
+
+func (r *descResolver) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
+ resolvedPath := r.importResolver.ResolveImport(r.fromPath, path)
+ d := r.findFileByPath(resolvedPath)
+ if d != nil {
+ return d, nil
+ }
+ if resolvedPath != path {
+ d := r.findFileByPath(path)
+ if d != nil {
+ return d, nil
+ }
+ }
+ return nil, protoregistry.NotFound
+}
+
+func (r *descResolver) findFileByPath(path string) protoreflect.FileDescriptor {
+ for _, fd := range r.files {
+ if fd.GetName() == path {
+ return fd.UnwrapFile()
+ }
+ }
+ return nil
+}
+
+func (r *descResolver) FindDescriptorByName(n protoreflect.FullName) (protoreflect.Descriptor, error) {
+ for _, fd := range r.files {
+ d := fd.FindSymbol(string(n))
+ if d != nil {
+ return d.(DescriptorWrapper).Unwrap(), nil
+ }
+ }
+ return nil, protoregistry.NotFound
+}
+
+func createFileDescriptor(fd *descriptorpb.FileDescriptorProto, deps []*FileDescriptor, r *ImportResolver) (*FileDescriptor, error) {
+ dr := &descResolver{files: deps, importResolver: r, fromPath: fd.GetName()}
+ d, err := protodesc.NewFile(fd, dr)
+ if err != nil {
+ return nil, err
+ }
+
+ // make sure cache has dependencies populated
+ cache := mapCache{}
+ for _, dep := range deps {
+ fd, err := dr.FindFileByPath(dep.GetName())
+ if err != nil {
+ return nil, err
+ }
+ cache.put(fd, dep)
+ }
+
+ return convertFile(d, fd, cache)
+}
+
+func convertFile(d protoreflect.FileDescriptor, fd *descriptorpb.FileDescriptorProto, cache descriptorCache) (*FileDescriptor, error) {
ret := &FileDescriptor{
+ wrapped: d,
proto: fd,
symbols: map[string]Descriptor{},
fieldIndex: map[string]map[int32]*FieldDescriptor{},
}
- pkg := fd.GetPackage()
+ cache.put(d, ret)
// populate references to file descriptor dependencies
- files := map[string]*FileDescriptor{}
- for _, f := range deps {
- files[f.proto.GetName()] = f
- }
ret.deps = make([]*FileDescriptor, len(fd.GetDependency()))
- for i, d := range fd.GetDependency() {
- resolved := r.ResolveImport(fd.GetName(), d)
- ret.deps[i] = files[resolved]
- if ret.deps[i] == nil {
- if resolved != d {
- ret.deps[i] = files[d]
- }
- if ret.deps[i] == nil {
- return nil, intn.ErrNoSuchFile(d)
- }
+ for i := 0; i < d.Imports().Len(); i++ {
+ f := d.Imports().Get(i).FileDescriptor
+ if c, err := wrapFile(f, cache); err != nil {
+ return nil, err
+ } else {
+ ret.deps[i] = c
}
}
ret.publicDeps = make([]*FileDescriptor, len(fd.GetPublicDependency()))
@@ -53,27 +109,39 @@
for i, wd := range fd.GetWeakDependency() {
ret.weakDeps[i] = ret.deps[wd]
}
- ret.isProto3 = fd.GetSyntax() == "proto3"
// populate all tables of child descriptors
- for _, m := range fd.GetMessageType() {
- md, n := createMessageDescriptor(ret, ret, pkg, m, ret.symbols)
- ret.symbols[n] = md
+ path := make([]int32, 1, 8)
+ path[0] = internal.File_messagesTag
+ for i := 0; i < d.Messages().Len(); i++ {
+ src := d.Messages().Get(i)
+ srcProto := fd.GetMessageType()[src.Index()]
+ md := createMessageDescriptor(ret, ret, src, srcProto, ret.symbols, cache, append(path, int32(i)))
+ ret.symbols[string(src.FullName())] = md
ret.messages = append(ret.messages, md)
}
- for _, e := range fd.GetEnumType() {
- ed, n := createEnumDescriptor(ret, ret, pkg, e, ret.symbols)
- ret.symbols[n] = ed
+ path[0] = internal.File_enumsTag
+ for i := 0; i < d.Enums().Len(); i++ {
+ src := d.Enums().Get(i)
+ srcProto := fd.GetEnumType()[src.Index()]
+ ed := createEnumDescriptor(ret, ret, src, srcProto, ret.symbols, cache, append(path, int32(i)))
+ ret.symbols[string(src.FullName())] = ed
ret.enums = append(ret.enums, ed)
}
- for _, ex := range fd.GetExtension() {
- exd, n := createFieldDescriptor(ret, ret, pkg, ex)
- ret.symbols[n] = exd
+ path[0] = internal.File_extensionsTag
+ for i := 0; i < d.Extensions().Len(); i++ {
+ src := d.Extensions().Get(i)
+ srcProto := fd.GetExtension()[src.Index()]
+ exd := createFieldDescriptor(ret, ret, src, srcProto, cache, append(path, int32(i)))
+ ret.symbols[string(src.FullName())] = exd
ret.extensions = append(ret.extensions, exd)
}
- for _, s := range fd.GetService() {
- sd, n := createServiceDescriptor(ret, pkg, s, ret.symbols)
- ret.symbols[n] = sd
+ path[0] = internal.File_servicesTag
+ for i := 0; i < d.Services().Len(); i++ {
+ src := d.Services().Get(i)
+ srcProto := fd.GetService()[src.Index()]
+ sd := createServiceDescriptor(ret, src, srcProto, ret.symbols, append(path, int32(i)))
+ ret.symbols[string(src.FullName())] = sd
ret.services = append(ret.services, sd)
}
@@ -81,27 +149,20 @@
ret.sourceInfoRecomputeFunc = ret.recomputeSourceInfo
// now we can resolve all type references and source code info
- scopes := []scope{fileScope(ret)}
- path := make([]int32, 1, 8)
- path[0] = internal.File_messagesTag
- for i, md := range ret.messages {
- if err := md.resolve(append(path, int32(i)), scopes); err != nil {
+ for _, md := range ret.messages {
+ if err := md.resolve(cache); err != nil {
return nil, err
}
}
- path[0] = internal.File_enumsTag
- for i, ed := range ret.enums {
- ed.resolve(append(path, int32(i)))
- }
path[0] = internal.File_extensionsTag
- for i, exd := range ret.extensions {
- if err := exd.resolve(append(path, int32(i)), scopes); err != nil {
+ for _, exd := range ret.extensions {
+ if err := exd.resolve(cache); err != nil {
return nil, err
}
}
path[0] = internal.File_servicesTag
- for i, sd := range ret.services {
- if err := sd.resolve(append(path, int32(i)), scopes); err != nil {
+ for _, sd := range ret.services {
+ if err := sd.resolve(cache); err != nil {
return nil, err
}
}
@@ -112,15 +173,15 @@
// CreateFileDescriptors constructs a set of descriptors, one for each of the
// given descriptor protos. The given set of descriptor protos must include all
// transitive dependencies for every file.
-func CreateFileDescriptors(fds []*dpb.FileDescriptorProto) (map[string]*FileDescriptor, error) {
+func CreateFileDescriptors(fds []*descriptorpb.FileDescriptorProto) (map[string]*FileDescriptor, error) {
return createFileDescriptors(fds, nil)
}
-func createFileDescriptors(fds []*dpb.FileDescriptorProto, r *ImportResolver) (map[string]*FileDescriptor, error) {
+func createFileDescriptors(fds []*descriptorpb.FileDescriptorProto, r *ImportResolver) (map[string]*FileDescriptor, error) {
if len(fds) == 0 {
return nil, nil
}
- files := map[string]*dpb.FileDescriptorProto{}
+ files := map[string]*descriptorpb.FileDescriptorProto{}
resolved := map[string]*FileDescriptor{}
var name string
for _, fd := range fds {
@@ -139,13 +200,13 @@
// ToFileDescriptorSet creates a FileDescriptorSet proto that contains all of the given
// file descriptors and their transitive dependencies. The files are topologically sorted
// so that a file will always appear after its dependencies.
-func ToFileDescriptorSet(fds ...*FileDescriptor) *dpb.FileDescriptorSet {
- var fdps []*dpb.FileDescriptorProto
+func ToFileDescriptorSet(fds ...*FileDescriptor) *descriptorpb.FileDescriptorSet {
+ var fdps []*descriptorpb.FileDescriptorProto
addAllFiles(fds, &fdps, map[string]struct{}{})
- return &dpb.FileDescriptorSet{File: fdps}
+ return &descriptorpb.FileDescriptorSet{File: fdps}
}
-func addAllFiles(src []*FileDescriptor, results *[]*dpb.FileDescriptorProto, seen map[string]struct{}) {
+func addAllFiles(src []*FileDescriptor, results *[]*descriptorpb.FileDescriptorProto, seen map[string]struct{}) {
for _, fd := range src {
if _, ok := seen[fd.GetName()]; ok {
continue
@@ -160,12 +221,13 @@
// set's *last* file will be the returned descriptor. The set's remaining files must comprise
// the full set of transitive dependencies of that last file. This is the same format and
// order used by protoc when emitting a FileDescriptorSet file with an invocation like so:
-// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
-func CreateFileDescriptorFromSet(fds *dpb.FileDescriptorSet) (*FileDescriptor, error) {
+//
+// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
+func CreateFileDescriptorFromSet(fds *descriptorpb.FileDescriptorSet) (*FileDescriptor, error) {
return createFileDescriptorFromSet(fds, nil)
}
-func createFileDescriptorFromSet(fds *dpb.FileDescriptorSet, r *ImportResolver) (*FileDescriptor, error) {
+func createFileDescriptorFromSet(fds *descriptorpb.FileDescriptorSet, r *ImportResolver) (*FileDescriptor, error) {
result, err := createFileDescriptorsFromSet(fds, r)
if err != nil {
return nil, err
@@ -180,12 +242,13 @@
// full set of transitive dependencies for all files therein or else a link error will occur
// and be returned instead of the slice of descriptors. This is the same format used by
// protoc when a FileDescriptorSet file with an invocation like so:
-// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
-func CreateFileDescriptorsFromSet(fds *dpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
+//
+// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
+func CreateFileDescriptorsFromSet(fds *descriptorpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
return createFileDescriptorsFromSet(fds, nil)
}
-func createFileDescriptorsFromSet(fds *dpb.FileDescriptorSet, r *ImportResolver) (map[string]*FileDescriptor, error) {
+func createFileDescriptorsFromSet(fds *descriptorpb.FileDescriptorSet, r *ImportResolver) (map[string]*FileDescriptor, error) {
files := fds.GetFile()
if len(files) == 0 {
return nil, errors.New("file descriptor set is empty")
@@ -195,7 +258,7 @@
// createFromSet creates a descriptor for the given filename. It recursively
// creates descriptors for the given file's dependencies.
-func createFromSet(filename string, r *ImportResolver, seen []string, files map[string]*dpb.FileDescriptorProto, resolved map[string]*FileDescriptor) (*FileDescriptor, error) {
+func createFromSet(filename string, r *ImportResolver, seen []string, files map[string]*descriptorpb.FileDescriptorProto, resolved map[string]*FileDescriptor) (*FileDescriptor, error) {
for _, s := range seen {
if filename == s {
return nil, fmt.Errorf("cycle in imports: %s", strings.Join(append(seen, filename), " -> "))
diff --git a/vendor/github.com/jhump/protoreflect/desc/descriptor.go b/vendor/github.com/jhump/protoreflect/desc/descriptor.go
index 42f0f8e..68eb252 100644
--- a/vendor/github.com/jhump/protoreflect/desc/descriptor.go
+++ b/vendor/github.com/jhump/protoreflect/desc/descriptor.go
@@ -5,12 +5,12 @@
"fmt"
"sort"
"strconv"
- "strings"
"unicode"
"unicode/utf8"
"github.com/golang/protobuf/proto"
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/types/descriptorpb"
"github.com/jhump/protoreflect/desc/internal"
)
@@ -40,7 +40,7 @@
// descriptor. Source code info is optional. If no source code info is available for
// the element (including if there is none at all in the file descriptor) then this
// returns nil
- GetSourceInfo() *dpb.SourceCodeInfo_Location
+ GetSourceInfo() *descriptorpb.SourceCodeInfo_Location
// AsProto returns the underlying descriptor proto for this descriptor.
AsProto() proto.Message
}
@@ -49,7 +49,8 @@
// FileDescriptor describes a proto source file.
type FileDescriptor struct {
- proto *dpb.FileDescriptorProto
+ wrapped protoreflect.FileDescriptor
+ proto *descriptorpb.FileDescriptorProto
symbols map[string]Descriptor
deps []*FileDescriptor
publicDeps []*FileDescriptor
@@ -59,11 +60,22 @@
extensions []*FieldDescriptor
services []*ServiceDescriptor
fieldIndex map[string]map[int32]*FieldDescriptor
- isProto3 bool
sourceInfo internal.SourceInfoMap
sourceInfoRecomputeFunc
}
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapFile, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (fd *FileDescriptor) Unwrap() protoreflect.Descriptor {
+ return fd.wrapped
+}
+
+// UnwrapFile returns the underlying protoreflect.FileDescriptor.
+func (fd *FileDescriptor) UnwrapFile() protoreflect.FileDescriptor {
+ return fd.wrapped
+}
+
func (fd *FileDescriptor) recomputeSourceInfo() {
internal.PopulateSourceInfoMap(fd.proto, fd.sourceInfo)
}
@@ -81,18 +93,18 @@
// to compile it, possibly including path (relative to a directory in the proto
// import path).
func (fd *FileDescriptor) GetName() string {
- return fd.proto.GetName()
+ return fd.wrapped.Path()
}
// GetFullyQualifiedName returns the name of the file, same as GetName. It is
// present to satisfy the Descriptor interface.
func (fd *FileDescriptor) GetFullyQualifiedName() string {
- return fd.proto.GetName()
+ return fd.wrapped.Path()
}
// GetPackage returns the name of the package declared in the file.
func (fd *FileDescriptor) GetPackage() string {
- return fd.proto.GetPackage()
+ return string(fd.wrapped.Package())
}
// GetParent always returns nil: files are the root of descriptor hierarchies.
@@ -115,13 +127,13 @@
}
// GetFileOptions returns the file's options.
-func (fd *FileDescriptor) GetFileOptions() *dpb.FileOptions {
+func (fd *FileDescriptor) GetFileOptions() *descriptorpb.FileOptions {
return fd.proto.GetOptions()
}
// GetSourceInfo returns nil for files. It is present to satisfy the Descriptor
// interface.
-func (fd *FileDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (fd *FileDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return nil
}
@@ -133,7 +145,7 @@
}
// AsFileDescriptorProto returns the underlying descriptor proto.
-func (fd *FileDescriptor) AsFileDescriptorProto() *dpb.FileDescriptorProto {
+func (fd *FileDescriptor) AsFileDescriptorProto() *descriptorpb.FileDescriptorProto {
return fd.proto
}
@@ -143,8 +155,20 @@
}
// IsProto3 returns true if the file declares a syntax of "proto3".
+//
+// When this returns false, the file is either syntax "proto2" (if
+// Edition() returns zero) or the file uses editions.
func (fd *FileDescriptor) IsProto3() bool {
- return fd.isProto3
+ return fd.wrapped.Syntax() == protoreflect.Proto3
+}
+
+// Edition returns the edition of the file. If the file does not
+// use editions syntax, zero is returned.
+func (fd *FileDescriptor) Edition() descriptorpb.Edition {
+ if fd.wrapped.Syntax() == protoreflect.Editions {
+ return fd.proto.GetEdition()
+ }
+ return 0
}
// GetDependencies returns all of this file's dependencies. These correspond to
@@ -189,6 +213,9 @@
// element with the given fully-qualified symbol name. If no such element
// exists then this method returns nil.
func (fd *FileDescriptor) FindSymbol(symbol string) Descriptor {
+ if len(symbol) == 0 {
+ return nil
+ }
if symbol[0] == '.' {
symbol = symbol[1:]
}
@@ -259,7 +286,8 @@
// MessageDescriptor describes a protocol buffer message.
type MessageDescriptor struct {
- proto *dpb.DescriptorProto
+ wrapped protoreflect.MessageDescriptor
+ proto *descriptorpb.DescriptorProto
parent Descriptor
file *FileDescriptor
fields []*FieldDescriptor
@@ -268,42 +296,72 @@
extensions []*FieldDescriptor
oneOfs []*OneOfDescriptor
extRanges extRanges
- fqn string
sourceInfoPath []int32
jsonNames jsonNameMap
- isProto3 bool
- isMapEntry bool
}
-func createMessageDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, md *dpb.DescriptorProto, symbols map[string]Descriptor) (*MessageDescriptor, string) {
- msgName := merge(enclosing, md.GetName())
- ret := &MessageDescriptor{proto: md, parent: parent, file: fd, fqn: msgName}
- for _, f := range md.GetField() {
- fld, n := createFieldDescriptor(fd, ret, msgName, f)
- symbols[n] = fld
- ret.fields = append(ret.fields, fld)
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapMessage, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (md *MessageDescriptor) Unwrap() protoreflect.Descriptor {
+ return md.wrapped
+}
+
+// UnwrapMessage returns the underlying protoreflect.MessageDescriptor.
+func (md *MessageDescriptor) UnwrapMessage() protoreflect.MessageDescriptor {
+ return md.wrapped
+}
+
+func createMessageDescriptor(fd *FileDescriptor, parent Descriptor, md protoreflect.MessageDescriptor, mdp *descriptorpb.DescriptorProto, symbols map[string]Descriptor, cache descriptorCache, path []int32) *MessageDescriptor {
+ ret := &MessageDescriptor{
+ wrapped: md,
+ proto: mdp,
+ parent: parent,
+ file: fd,
+ sourceInfoPath: append([]int32(nil), path...), // defensive copy
}
- for _, nm := range md.NestedType {
- nmd, n := createMessageDescriptor(fd, ret, msgName, nm, symbols)
- symbols[n] = nmd
+ cache.put(md, ret)
+ path = append(path, internal.Message_nestedMessagesTag)
+ for i := 0; i < md.Messages().Len(); i++ {
+ src := md.Messages().Get(i)
+ srcProto := mdp.GetNestedType()[src.Index()]
+ nmd := createMessageDescriptor(fd, ret, src, srcProto, symbols, cache, append(path, int32(i)))
+ symbols[string(src.FullName())] = nmd
ret.nested = append(ret.nested, nmd)
}
- for _, e := range md.EnumType {
- ed, n := createEnumDescriptor(fd, ret, msgName, e, symbols)
- symbols[n] = ed
+ path[len(path)-1] = internal.Message_enumsTag
+ for i := 0; i < md.Enums().Len(); i++ {
+ src := md.Enums().Get(i)
+ srcProto := mdp.GetEnumType()[src.Index()]
+ ed := createEnumDescriptor(fd, ret, src, srcProto, symbols, cache, append(path, int32(i)))
+ symbols[string(src.FullName())] = ed
ret.enums = append(ret.enums, ed)
}
- for _, ex := range md.GetExtension() {
- exd, n := createFieldDescriptor(fd, ret, msgName, ex)
- symbols[n] = exd
+ path[len(path)-1] = internal.Message_fieldsTag
+ for i := 0; i < md.Fields().Len(); i++ {
+ src := md.Fields().Get(i)
+ srcProto := mdp.GetField()[src.Index()]
+ fld := createFieldDescriptor(fd, ret, src, srcProto, cache, append(path, int32(i)))
+ symbols[string(src.FullName())] = fld
+ ret.fields = append(ret.fields, fld)
+ }
+ path[len(path)-1] = internal.Message_extensionsTag
+ for i := 0; i < md.Extensions().Len(); i++ {
+ src := md.Extensions().Get(i)
+ srcProto := mdp.GetExtension()[src.Index()]
+ exd := createFieldDescriptor(fd, ret, src, srcProto, cache, append(path, int32(i)))
+ symbols[string(src.FullName())] = exd
ret.extensions = append(ret.extensions, exd)
}
- for i, o := range md.GetOneofDecl() {
- od, n := createOneOfDescriptor(fd, ret, i, msgName, o)
- symbols[n] = od
+ path[len(path)-1] = internal.Message_oneOfsTag
+ for i := 0; i < md.Oneofs().Len(); i++ {
+ src := md.Oneofs().Get(i)
+ srcProto := mdp.GetOneofDecl()[src.Index()]
+ od := createOneOfDescriptor(fd, ret, i, src, srcProto, append(path, int32(i)))
+ symbols[string(src.FullName())] = od
ret.oneOfs = append(ret.oneOfs, od)
}
- for _, r := range md.GetExtensionRange() {
+ for _, r := range mdp.GetExtensionRange() {
// proto.ExtensionRange is inclusive (and that's how extension ranges are defined in code).
// but protoc converts range to exclusive end in descriptor, so we must convert back
end := r.GetEnd() - 1
@@ -312,57 +370,39 @@
End: end})
}
sort.Sort(ret.extRanges)
- ret.isProto3 = fd.isProto3
- ret.isMapEntry = md.GetOptions().GetMapEntry() &&
- len(ret.fields) == 2 &&
- ret.fields[0].GetNumber() == 1 &&
- ret.fields[1].GetNumber() == 2
- return ret, msgName
+ return ret
}
-func (md *MessageDescriptor) resolve(path []int32, scopes []scope) error {
- md.sourceInfoPath = append([]int32(nil), path...) // defensive copy
- path = append(path, internal.Message_nestedMessagesTag)
- scopes = append(scopes, messageScope(md))
- for i, nmd := range md.nested {
- if err := nmd.resolve(append(path, int32(i)), scopes); err != nil {
+func (md *MessageDescriptor) resolve(cache descriptorCache) error {
+ for _, nmd := range md.nested {
+ if err := nmd.resolve(cache); err != nil {
return err
}
}
- path[len(path)-1] = internal.Message_enumsTag
- for i, ed := range md.enums {
- ed.resolve(append(path, int32(i)))
- }
- path[len(path)-1] = internal.Message_fieldsTag
- for i, fld := range md.fields {
- if err := fld.resolve(append(path, int32(i)), scopes); err != nil {
+ for _, fld := range md.fields {
+ if err := fld.resolve(cache); err != nil {
return err
}
}
- path[len(path)-1] = internal.Message_extensionsTag
- for i, exd := range md.extensions {
- if err := exd.resolve(append(path, int32(i)), scopes); err != nil {
+ for _, exd := range md.extensions {
+ if err := exd.resolve(cache); err != nil {
return err
}
}
- path[len(path)-1] = internal.Message_oneOfsTag
- for i, od := range md.oneOfs {
- od.resolve(append(path, int32(i)))
- }
return nil
}
// GetName returns the simple (unqualified) name of the message.
func (md *MessageDescriptor) GetName() string {
- return md.proto.GetName()
+ return string(md.wrapped.Name())
}
// GetFullyQualifiedName returns the fully qualified name of the message. This
// includes the package name (if there is one) as well as the names of any
// enclosing messages.
func (md *MessageDescriptor) GetFullyQualifiedName() string {
- return md.fqn
+ return string(md.wrapped.FullName())
}
// GetParent returns the message's enclosing descriptor. For top-level messages,
@@ -385,7 +425,7 @@
}
// GetMessageOptions returns the message's options.
-func (md *MessageDescriptor) GetMessageOptions() *dpb.MessageOptions {
+func (md *MessageDescriptor) GetMessageOptions() *descriptorpb.MessageOptions {
return md.proto.GetOptions()
}
@@ -394,7 +434,7 @@
// returned info contains information about the location in the file where the
// message was defined and also contains comments associated with the message
// definition.
-func (md *MessageDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (md *MessageDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return md.file.sourceInfo.Get(md.sourceInfoPath)
}
@@ -406,7 +446,7 @@
}
// AsDescriptorProto returns the underlying descriptor proto.
-func (md *MessageDescriptor) AsDescriptorProto() *dpb.DescriptorProto {
+func (md *MessageDescriptor) AsDescriptorProto() *descriptorpb.DescriptorProto {
return md.proto
}
@@ -418,7 +458,7 @@
// IsMapEntry returns true if this is a synthetic message type that represents an entry
// in a map field.
func (md *MessageDescriptor) IsMapEntry() bool {
- return md.isMapEntry
+ return md.wrapped.IsMapEntry()
}
// GetFields returns all of the fields for this message.
@@ -448,7 +488,7 @@
// IsProto3 returns true if the file in which this message is defined declares a syntax of "proto3".
func (md *MessageDescriptor) IsProto3() bool {
- return md.isProto3
+ return md.file.IsProto3()
}
// GetExtensionRanges returns the ranges of extension field numbers for this message.
@@ -503,7 +543,7 @@
// FindFieldByName finds the field with the given name. If no such field exists
// then nil is returned. Only regular fields are returned, not extensions.
func (md *MessageDescriptor) FindFieldByName(fieldName string) *FieldDescriptor {
- fqn := fmt.Sprintf("%s.%s", md.fqn, fieldName)
+ fqn := md.GetFullyQualifiedName() + "." + fieldName
if fd, ok := md.file.symbols[fqn].(*FieldDescriptor); ok && !fd.IsExtension() {
return fd
} else {
@@ -514,7 +554,7 @@
// FindFieldByNumber finds the field with the given tag number. If no such field
// exists then nil is returned. Only regular fields are returned, not extensions.
func (md *MessageDescriptor) FindFieldByNumber(tagNumber int32) *FieldDescriptor {
- if fd, ok := md.file.fieldIndex[md.fqn][tagNumber]; ok && !fd.IsExtension() {
+ if fd, ok := md.file.fieldIndex[md.GetFullyQualifiedName()][tagNumber]; ok && !fd.IsExtension() {
return fd
} else {
return nil
@@ -523,59 +563,110 @@
// FieldDescriptor describes a field of a protocol buffer message.
type FieldDescriptor struct {
- proto *dpb.FieldDescriptorProto
+ wrapped protoreflect.FieldDescriptor
+ proto *descriptorpb.FieldDescriptorProto
parent Descriptor
owner *MessageDescriptor
file *FileDescriptor
oneOf *OneOfDescriptor
msgType *MessageDescriptor
enumType *EnumDescriptor
- fqn string
sourceInfoPath []int32
def memoizedDefault
- isMap bool
}
-func createFieldDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, fld *dpb.FieldDescriptorProto) (*FieldDescriptor, string) {
- fldName := merge(enclosing, fld.GetName())
- ret := &FieldDescriptor{proto: fld, parent: parent, file: fd, fqn: fldName}
- if fld.GetExtendee() == "" {
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapField, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (fd *FieldDescriptor) Unwrap() protoreflect.Descriptor {
+ return fd.wrapped
+}
+
+// UnwrapField returns the underlying protoreflect.FieldDescriptor.
+func (fd *FieldDescriptor) UnwrapField() protoreflect.FieldDescriptor {
+ return fd.wrapped
+}
+
+func createFieldDescriptor(fd *FileDescriptor, parent Descriptor, fld protoreflect.FieldDescriptor, fldp *descriptorpb.FieldDescriptorProto, cache descriptorCache, path []int32) *FieldDescriptor {
+ ret := &FieldDescriptor{
+ wrapped: fld,
+ proto: fldp,
+ parent: parent,
+ file: fd,
+ sourceInfoPath: append([]int32(nil), path...), // defensive copy
+ }
+ cache.put(fld, ret)
+ if !fld.IsExtension() {
ret.owner = parent.(*MessageDescriptor)
}
// owner for extensions, field type (be it message or enum), and one-ofs get resolved later
- return ret, fldName
+ return ret
}
-func (fd *FieldDescriptor) resolve(path []int32, scopes []scope) error {
+func descriptorType(d Descriptor) string {
+ switch d := d.(type) {
+ case *FileDescriptor:
+ return "a file"
+ case *MessageDescriptor:
+ return "a message"
+ case *FieldDescriptor:
+ if d.IsExtension() {
+ return "an extension"
+ }
+ return "a field"
+ case *OneOfDescriptor:
+ return "a oneof"
+ case *EnumDescriptor:
+ return "an enum"
+ case *EnumValueDescriptor:
+ return "an enum value"
+ case *ServiceDescriptor:
+ return "a service"
+ case *MethodDescriptor:
+ return "a method"
+ default:
+ return fmt.Sprintf("a %T", d)
+ }
+}
+
+func (fd *FieldDescriptor) resolve(cache descriptorCache) error {
if fd.proto.OneofIndex != nil && fd.oneOf == nil {
- return fmt.Errorf("could not link field %s to one-of index %d", fd.fqn, *fd.proto.OneofIndex)
+ return fmt.Errorf("could not link field %s to one-of index %d", fd.GetFullyQualifiedName(), *fd.proto.OneofIndex)
}
- fd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
- if fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_ENUM {
- if desc, err := resolve(fd.file, fd.proto.GetTypeName(), scopes); err != nil {
+ if fd.proto.GetType() == descriptorpb.FieldDescriptorProto_TYPE_ENUM {
+ desc, err := resolve(fd.file, fd.wrapped.Enum(), cache)
+ if err != nil {
return err
- } else {
- fd.enumType = desc.(*EnumDescriptor)
}
+ enumType, ok := desc.(*EnumDescriptor)
+ if !ok {
+ return fmt.Errorf("field %v indicates a type of enum, but references %q which is %s", fd.GetFullyQualifiedName(), fd.proto.GetTypeName(), descriptorType(desc))
+ }
+ fd.enumType = enumType
}
- if fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_MESSAGE || fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_GROUP {
- if desc, err := resolve(fd.file, fd.proto.GetTypeName(), scopes); err != nil {
+ if fd.proto.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE || fd.proto.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
+ desc, err := resolve(fd.file, fd.wrapped.Message(), cache)
+ if err != nil {
return err
- } else {
- fd.msgType = desc.(*MessageDescriptor)
}
+ msgType, ok := desc.(*MessageDescriptor)
+ if !ok {
+ return fmt.Errorf("field %v indicates a type of message, but references %q which is %s", fd.GetFullyQualifiedName(), fd.proto.GetTypeName(), descriptorType(desc))
+ }
+ fd.msgType = msgType
}
- if fd.proto.GetExtendee() != "" {
- if desc, err := resolve(fd.file, fd.proto.GetExtendee(), scopes); err != nil {
+ if fd.IsExtension() {
+ desc, err := resolve(fd.file, fd.wrapped.ContainingMessage(), cache)
+ if err != nil {
return err
- } else {
- fd.owner = desc.(*MessageDescriptor)
}
+ msgType, ok := desc.(*MessageDescriptor)
+ if !ok {
+ return fmt.Errorf("field %v extends %q which should be a message but is %s", fd.GetFullyQualifiedName(), fd.proto.GetExtendee(), descriptorType(desc))
+ }
+ fd.owner = msgType
}
fd.file.registerField(fd)
- fd.isMap = fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REPEATED &&
- fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_MESSAGE &&
- fd.GetMessageType().IsMapEntry()
return nil
}
@@ -588,7 +679,7 @@
return nil
}
- proto3 := fd.file.isProto3
+ proto3 := fd.file.IsProto3()
if !proto3 {
def := fd.AsFieldDescriptorProto().GetDefaultValue()
if def != "" {
@@ -601,31 +692,31 @@
}
switch fd.GetType() {
- case dpb.FieldDescriptorProto_TYPE_FIXED32,
- dpb.FieldDescriptorProto_TYPE_UINT32:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED32,
+ descriptorpb.FieldDescriptorProto_TYPE_UINT32:
return uint32(0)
- case dpb.FieldDescriptorProto_TYPE_SFIXED32,
- dpb.FieldDescriptorProto_TYPE_INT32,
- dpb.FieldDescriptorProto_TYPE_SINT32:
+ case descriptorpb.FieldDescriptorProto_TYPE_SFIXED32,
+ descriptorpb.FieldDescriptorProto_TYPE_INT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT32:
return int32(0)
- case dpb.FieldDescriptorProto_TYPE_FIXED64,
- dpb.FieldDescriptorProto_TYPE_UINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED64,
+ descriptorpb.FieldDescriptorProto_TYPE_UINT64:
return uint64(0)
- case dpb.FieldDescriptorProto_TYPE_SFIXED64,
- dpb.FieldDescriptorProto_TYPE_INT64,
- dpb.FieldDescriptorProto_TYPE_SINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_SFIXED64,
+ descriptorpb.FieldDescriptorProto_TYPE_INT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT64:
return int64(0)
- case dpb.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
return float32(0.0)
- case dpb.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
return float64(0.0)
- case dpb.FieldDescriptorProto_TYPE_BOOL:
+ case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
return false
- case dpb.FieldDescriptorProto_TYPE_BYTES:
+ case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
return []byte(nil)
- case dpb.FieldDescriptorProto_TYPE_STRING:
+ case descriptorpb.FieldDescriptorProto_TYPE_STRING:
return ""
- case dpb.FieldDescriptorProto_TYPE_ENUM:
+ case descriptorpb.FieldDescriptorProto_TYPE_ENUM:
if proto3 {
return int32(0)
}
@@ -642,60 +733,60 @@
func parseDefaultValue(fd *FieldDescriptor, val string) interface{} {
switch fd.GetType() {
- case dpb.FieldDescriptorProto_TYPE_ENUM:
+ case descriptorpb.FieldDescriptorProto_TYPE_ENUM:
vd := fd.GetEnumType().FindValueByName(val)
if vd != nil {
return vd.GetNumber()
}
return nil
- case dpb.FieldDescriptorProto_TYPE_BOOL:
+ case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
if val == "true" {
return true
} else if val == "false" {
return false
}
return nil
- case dpb.FieldDescriptorProto_TYPE_BYTES:
+ case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
return []byte(unescape(val))
- case dpb.FieldDescriptorProto_TYPE_STRING:
+ case descriptorpb.FieldDescriptorProto_TYPE_STRING:
return val
- case dpb.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
if f, err := strconv.ParseFloat(val, 32); err == nil {
return float32(f)
} else {
return float32(0)
}
- case dpb.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
if f, err := strconv.ParseFloat(val, 64); err == nil {
return f
} else {
return float64(0)
}
- case dpb.FieldDescriptorProto_TYPE_INT32,
- dpb.FieldDescriptorProto_TYPE_SINT32,
- dpb.FieldDescriptorProto_TYPE_SFIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED32:
if i, err := strconv.ParseInt(val, 10, 32); err == nil {
return int32(i)
} else {
return int32(0)
}
- case dpb.FieldDescriptorProto_TYPE_UINT32,
- dpb.FieldDescriptorProto_TYPE_FIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED32:
if i, err := strconv.ParseUint(val, 10, 32); err == nil {
return uint32(i)
} else {
return uint32(0)
}
- case dpb.FieldDescriptorProto_TYPE_INT64,
- dpb.FieldDescriptorProto_TYPE_SINT64,
- dpb.FieldDescriptorProto_TYPE_SFIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED64:
if i, err := strconv.ParseInt(val, 10, 64); err == nil {
return i
} else {
return int64(0)
}
- case dpb.FieldDescriptorProto_TYPE_UINT64,
- dpb.FieldDescriptorProto_TYPE_FIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED64:
if i, err := strconv.ParseUint(val, 10, 64); err == nil {
return i
} else {
@@ -827,12 +918,12 @@
// GetName returns the name of the field.
func (fd *FieldDescriptor) GetName() string {
- return fd.proto.GetName()
+ return string(fd.wrapped.Name())
}
// GetNumber returns the tag number of this field.
func (fd *FieldDescriptor) GetNumber() int32 {
- return fd.proto.GetNumber()
+ return int32(fd.wrapped.Number())
}
// GetFullyQualifiedName returns the fully qualified name of the field. Unlike
@@ -846,7 +937,7 @@
// If this field is part of a one-of, the fully qualified name does *not*
// include the name of the one-of, only of the enclosing message.
func (fd *FieldDescriptor) GetFullyQualifiedName() string {
- return fd.fqn
+ return string(fd.wrapped.FullName())
}
// GetParent returns the fields's enclosing descriptor. For normal
@@ -871,7 +962,7 @@
}
// GetFieldOptions returns the field's options.
-func (fd *FieldDescriptor) GetFieldOptions() *dpb.FieldOptions {
+func (fd *FieldDescriptor) GetFieldOptions() *descriptorpb.FieldOptions {
return fd.proto.GetOptions()
}
@@ -880,7 +971,7 @@
// returned info contains information about the location in the file where the
// field was defined and also contains comments associated with the field
// definition.
-func (fd *FieldDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (fd *FieldDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return fd.file.sourceInfo.Get(fd.sourceInfoPath)
}
@@ -892,7 +983,7 @@
}
// AsFieldDescriptorProto returns the underlying descriptor proto.
-func (fd *FieldDescriptor) AsFieldDescriptorProto() *dpb.FieldDescriptorProto {
+func (fd *FieldDescriptor) AsFieldDescriptorProto() *descriptorpb.FieldDescriptorProto {
return fd.proto
}
@@ -962,7 +1053,7 @@
// IsExtension returns true if this is an extension field.
func (fd *FieldDescriptor) IsExtension() bool {
- return fd.proto.GetExtendee() != ""
+ return fd.wrapped.IsExtension()
}
// GetOneOf returns the one-of field set to which this field belongs. If this field
@@ -974,24 +1065,24 @@
// GetType returns the type of this field. If the type indicates an enum, the
// enum type can be queried via GetEnumType. If the type indicates a message, the
// message type can be queried via GetMessageType.
-func (fd *FieldDescriptor) GetType() dpb.FieldDescriptorProto_Type {
+func (fd *FieldDescriptor) GetType() descriptorpb.FieldDescriptorProto_Type {
return fd.proto.GetType()
}
// GetLabel returns the label for this field. The label can be required (proto2-only),
// optional (default for proto3), or required.
-func (fd *FieldDescriptor) GetLabel() dpb.FieldDescriptorProto_Label {
+func (fd *FieldDescriptor) GetLabel() descriptorpb.FieldDescriptorProto_Label {
return fd.proto.GetLabel()
}
// IsRequired returns true if this field has the "required" label.
func (fd *FieldDescriptor) IsRequired() bool {
- return fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REQUIRED
+ return fd.wrapped.Cardinality() == protoreflect.Required
}
// IsRepeated returns true if this field has the "repeated" label.
func (fd *FieldDescriptor) IsRepeated() bool {
- return fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REPEATED
+ return fd.wrapped.Cardinality() == protoreflect.Repeated
}
// IsProto3Optional returns true if this field has an explicit "optional" label
@@ -999,30 +1090,27 @@
// extensions), will be nested in synthetic oneofs that contain only the single
// field.
func (fd *FieldDescriptor) IsProto3Optional() bool {
- return internal.GetProto3Optional(fd.proto)
+ return fd.proto.GetProto3Optional()
}
// HasPresence returns true if this field can distinguish when a value is
// present or not. Scalar fields in "proto3" syntax files, for example, return
// false since absent values are indistinguishable from zero values.
func (fd *FieldDescriptor) HasPresence() bool {
- if !fd.file.isProto3 {
- return true
- }
- return fd.msgType != nil || fd.oneOf != nil
+ return fd.wrapped.HasPresence()
}
// IsMap returns true if this is a map field. If so, it will have the "repeated"
// label its type will be a message that represents a map entry. The map entry
// message will have exactly two fields: tag #1 is the key and tag #2 is the value.
func (fd *FieldDescriptor) IsMap() bool {
- return fd.isMap
+ return fd.wrapped.IsMap()
}
// GetMapKeyType returns the type of the key field if this is a map field. If it is
// not a map field, nil is returned.
func (fd *FieldDescriptor) GetMapKeyType() *FieldDescriptor {
- if fd.isMap {
+ if fd.IsMap() {
return fd.msgType.FindFieldByNumber(int32(1))
}
return nil
@@ -1031,7 +1119,7 @@
// GetMapValueType returns the type of the value field if this is a map field. If it
// is not a map field, nil is returned.
func (fd *FieldDescriptor) GetMapValueType() *FieldDescriptor {
- if fd.isMap {
+ if fd.IsMap() {
return fd.msgType.FindFieldByNumber(int32(2))
}
return nil
@@ -1060,40 +1148,66 @@
// Otherwise, it returns the declared default value for the field or a zero value, if no
// default is declared or if the file is proto3. The type of said return value corresponds
// to the type of the field:
-// +-------------------------+-----------+
-// | Declared Type | Go Type |
-// +-------------------------+-----------+
-// | int32, sint32, sfixed32 | int32 |
-// | int64, sint64, sfixed64 | int64 |
-// | uint32, fixed32 | uint32 |
-// | uint64, fixed64 | uint64 |
-// | float | float32 |
-// | double | double32 |
-// | bool | bool |
-// | string | string |
-// | bytes | []byte |
-// +-------------------------+-----------+
+//
+// +-------------------------+-----------+
+// | Declared Type | Go Type |
+// +-------------------------+-----------+
+// | int32, sint32, sfixed32 | int32 |
+// | int64, sint64, sfixed64 | int64 |
+// | uint32, fixed32 | uint32 |
+// | uint64, fixed64 | uint64 |
+// | float | float32 |
+// | double | double32 |
+// | bool | bool |
+// | string | string |
+// | bytes | []byte |
+// +-------------------------+-----------+
func (fd *FieldDescriptor) GetDefaultValue() interface{} {
return fd.getDefaultValue()
}
// EnumDescriptor describes an enum declared in a proto file.
type EnumDescriptor struct {
- proto *dpb.EnumDescriptorProto
+ wrapped protoreflect.EnumDescriptor
+ proto *descriptorpb.EnumDescriptorProto
parent Descriptor
file *FileDescriptor
values []*EnumValueDescriptor
valuesByNum sortedValues
- fqn string
sourceInfoPath []int32
}
-func createEnumDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, ed *dpb.EnumDescriptorProto, symbols map[string]Descriptor) (*EnumDescriptor, string) {
- enumName := merge(enclosing, ed.GetName())
- ret := &EnumDescriptor{proto: ed, parent: parent, file: fd, fqn: enumName}
- for _, ev := range ed.GetValue() {
- evd, n := createEnumValueDescriptor(fd, ret, enumName, ev)
- symbols[n] = evd
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapEnum, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (ed *EnumDescriptor) Unwrap() protoreflect.Descriptor {
+ return ed.wrapped
+}
+
+// UnwrapEnum returns the underlying protoreflect.EnumDescriptor.
+func (ed *EnumDescriptor) UnwrapEnum() protoreflect.EnumDescriptor {
+ return ed.wrapped
+}
+
+func createEnumDescriptor(fd *FileDescriptor, parent Descriptor, ed protoreflect.EnumDescriptor, edp *descriptorpb.EnumDescriptorProto, symbols map[string]Descriptor, cache descriptorCache, path []int32) *EnumDescriptor {
+ ret := &EnumDescriptor{
+ wrapped: ed,
+ proto: edp,
+ parent: parent,
+ file: fd,
+ sourceInfoPath: append([]int32(nil), path...), // defensive copy
+ }
+ path = append(path, internal.Enum_valuesTag)
+ for i := 0; i < ed.Values().Len(); i++ {
+ src := ed.Values().Get(i)
+ srcProto := edp.GetValue()[src.Index()]
+ evd := createEnumValueDescriptor(fd, ret, src, srcProto, append(path, int32(i)))
+ symbols[string(src.FullName())] = evd
+ // NB: for backwards compatibility, also register the enum value as if
+ // scoped within the enum (counter-intuitively, enum value full names are
+ // scoped in the enum's parent element). EnumValueDescripto.GetFullyQualifiedName
+ // returns that alternate full name.
+ symbols[evd.GetFullyQualifiedName()] = evd
ret.values = append(ret.values, evd)
}
if len(ret.values) > 0 {
@@ -1101,7 +1215,7 @@
copy(ret.valuesByNum, ret.values)
sort.Stable(ret.valuesByNum)
}
- return ret, enumName
+ return ret
}
type sortedValues []*EnumValueDescriptor
@@ -1116,26 +1230,19 @@
func (sv sortedValues) Swap(i, j int) {
sv[i], sv[j] = sv[j], sv[i]
-}
-func (ed *EnumDescriptor) resolve(path []int32) {
- ed.sourceInfoPath = append([]int32(nil), path...) // defensive copy
- path = append(path, internal.Enum_valuesTag)
- for i, evd := range ed.values {
- evd.resolve(append(path, int32(i)))
- }
}
// GetName returns the simple (unqualified) name of the enum type.
func (ed *EnumDescriptor) GetName() string {
- return ed.proto.GetName()
+ return string(ed.wrapped.Name())
}
// GetFullyQualifiedName returns the fully qualified name of the enum type.
// This includes the package name (if there is one) as well as the names of any
// enclosing messages.
func (ed *EnumDescriptor) GetFullyQualifiedName() string {
- return ed.fqn
+ return string(ed.wrapped.FullName())
}
// GetParent returns the enum type's enclosing descriptor. For top-level enums,
@@ -1158,7 +1265,7 @@
}
// GetEnumOptions returns the enum type's options.
-func (ed *EnumDescriptor) GetEnumOptions() *dpb.EnumOptions {
+func (ed *EnumDescriptor) GetEnumOptions() *descriptorpb.EnumOptions {
return ed.proto.GetOptions()
}
@@ -1167,7 +1274,7 @@
// returned info contains information about the location in the file where the
// enum type was defined and also contains comments associated with the enum
// definition.
-func (ed *EnumDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (ed *EnumDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return ed.file.sourceInfo.Get(ed.sourceInfoPath)
}
@@ -1179,7 +1286,7 @@
}
// AsEnumDescriptorProto returns the underlying descriptor proto.
-func (ed *EnumDescriptor) AsEnumDescriptorProto() *dpb.EnumDescriptorProto {
+func (ed *EnumDescriptor) AsEnumDescriptorProto() *descriptorpb.EnumDescriptorProto {
return ed.proto
}
@@ -1196,7 +1303,7 @@
// FindValueByName finds the enum value with the given name. If no such value exists
// then nil is returned.
func (ed *EnumDescriptor) FindValueByName(name string) *EnumValueDescriptor {
- fqn := fmt.Sprintf("%s.%s", ed.fqn, name)
+ fqn := fmt.Sprintf("%s.%s", ed.GetFullyQualifiedName(), name)
if vd, ok := ed.file.symbols[fqn].(*EnumValueDescriptor); ok {
return vd
} else {
@@ -1220,16 +1327,33 @@
// EnumValueDescriptor describes an allowed value of an enum declared in a proto file.
type EnumValueDescriptor struct {
- proto *dpb.EnumValueDescriptorProto
+ wrapped protoreflect.EnumValueDescriptor
+ proto *descriptorpb.EnumValueDescriptorProto
parent *EnumDescriptor
file *FileDescriptor
- fqn string
sourceInfoPath []int32
}
-func createEnumValueDescriptor(fd *FileDescriptor, parent *EnumDescriptor, enclosing string, evd *dpb.EnumValueDescriptorProto) (*EnumValueDescriptor, string) {
- valName := merge(enclosing, evd.GetName())
- return &EnumValueDescriptor{proto: evd, parent: parent, file: fd, fqn: valName}, valName
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapEnumValue, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (vd *EnumValueDescriptor) Unwrap() protoreflect.Descriptor {
+ return vd.wrapped
+}
+
+// UnwrapEnumValue returns the underlying protoreflect.EnumValueDescriptor.
+func (vd *EnumValueDescriptor) UnwrapEnumValue() protoreflect.EnumValueDescriptor {
+ return vd.wrapped
+}
+
+func createEnumValueDescriptor(fd *FileDescriptor, parent *EnumDescriptor, evd protoreflect.EnumValueDescriptor, evdp *descriptorpb.EnumValueDescriptorProto, path []int32) *EnumValueDescriptor {
+ return &EnumValueDescriptor{
+ wrapped: evd,
+ proto: evdp,
+ parent: parent,
+ file: fd,
+ sourceInfoPath: append([]int32(nil), path...), // defensive copy
+ }
}
func (vd *EnumValueDescriptor) resolve(path []int32) {
@@ -1238,18 +1362,24 @@
// GetName returns the name of the enum value.
func (vd *EnumValueDescriptor) GetName() string {
- return vd.proto.GetName()
+ return string(vd.wrapped.Name())
}
// GetNumber returns the numeric value associated with this enum value.
func (vd *EnumValueDescriptor) GetNumber() int32 {
- return vd.proto.GetNumber()
+ return int32(vd.wrapped.Number())
}
// GetFullyQualifiedName returns the fully qualified name of the enum value.
// Unlike GetName, this includes fully qualified name of the enclosing enum.
func (vd *EnumValueDescriptor) GetFullyQualifiedName() string {
- return vd.fqn
+ // NB: Technically, we do not return the correct value. Enum values are
+ // scoped within the enclosing element, not within the enum itself (which
+ // is very non-intuitive, but it follows C++ scoping rules). The value
+ // returned from vd.wrapped.FullName() is correct. However, we return
+ // something different, just for backwards compatibility, as this package
+ // has always instead returned the name scoped inside the enum.
+ return fmt.Sprintf("%s.%s", vd.parent.GetFullyQualifiedName(), vd.wrapped.Name())
}
// GetParent returns the descriptor for the enum in which this enum value is
@@ -1278,7 +1408,7 @@
}
// GetEnumValueOptions returns the enum value's options.
-func (vd *EnumValueDescriptor) GetEnumValueOptions() *dpb.EnumValueOptions {
+func (vd *EnumValueDescriptor) GetEnumValueOptions() *descriptorpb.EnumValueOptions {
return vd.proto.GetOptions()
}
@@ -1287,7 +1417,7 @@
// returned info contains information about the location in the file where the
// enum value was defined and also contains comments associated with the enum
// value definition.
-func (vd *EnumValueDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (vd *EnumValueDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return vd.file.sourceInfo.Get(vd.sourceInfoPath)
}
@@ -1299,7 +1429,7 @@
}
// AsEnumValueDescriptorProto returns the underlying descriptor proto.
-func (vd *EnumValueDescriptor) AsEnumValueDescriptorProto() *dpb.EnumValueDescriptorProto {
+func (vd *EnumValueDescriptor) AsEnumValueDescriptorProto() *descriptorpb.EnumValueDescriptorProto {
return vd.proto
}
@@ -1310,29 +1440,46 @@
// ServiceDescriptor describes an RPC service declared in a proto file.
type ServiceDescriptor struct {
- proto *dpb.ServiceDescriptorProto
+ wrapped protoreflect.ServiceDescriptor
+ proto *descriptorpb.ServiceDescriptorProto
file *FileDescriptor
methods []*MethodDescriptor
- fqn string
sourceInfoPath []int32
}
-func createServiceDescriptor(fd *FileDescriptor, enclosing string, sd *dpb.ServiceDescriptorProto, symbols map[string]Descriptor) (*ServiceDescriptor, string) {
- serviceName := merge(enclosing, sd.GetName())
- ret := &ServiceDescriptor{proto: sd, file: fd, fqn: serviceName}
- for _, m := range sd.GetMethod() {
- md, n := createMethodDescriptor(fd, ret, serviceName, m)
- symbols[n] = md
- ret.methods = append(ret.methods, md)
- }
- return ret, serviceName
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapService, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (sd *ServiceDescriptor) Unwrap() protoreflect.Descriptor {
+ return sd.wrapped
}
-func (sd *ServiceDescriptor) resolve(path []int32, scopes []scope) error {
- sd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+// UnwrapService returns the underlying protoreflect.ServiceDescriptor.
+func (sd *ServiceDescriptor) UnwrapService() protoreflect.ServiceDescriptor {
+ return sd.wrapped
+}
+
+func createServiceDescriptor(fd *FileDescriptor, sd protoreflect.ServiceDescriptor, sdp *descriptorpb.ServiceDescriptorProto, symbols map[string]Descriptor, path []int32) *ServiceDescriptor {
+ ret := &ServiceDescriptor{
+ wrapped: sd,
+ proto: sdp,
+ file: fd,
+ sourceInfoPath: append([]int32(nil), path...), // defensive copy
+ }
path = append(path, internal.Service_methodsTag)
- for i, md := range sd.methods {
- if err := md.resolve(append(path, int32(i)), scopes); err != nil {
+ for i := 0; i < sd.Methods().Len(); i++ {
+ src := sd.Methods().Get(i)
+ srcProto := sdp.GetMethod()[src.Index()]
+ md := createMethodDescriptor(fd, ret, src, srcProto, append(path, int32(i)))
+ symbols[string(src.FullName())] = md
+ ret.methods = append(ret.methods, md)
+ }
+ return ret
+}
+
+func (sd *ServiceDescriptor) resolve(cache descriptorCache) error {
+ for _, md := range sd.methods {
+ if err := md.resolve(cache); err != nil {
return err
}
}
@@ -1341,13 +1488,13 @@
// GetName returns the simple (unqualified) name of the service.
func (sd *ServiceDescriptor) GetName() string {
- return sd.proto.GetName()
+ return string(sd.wrapped.Name())
}
// GetFullyQualifiedName returns the fully qualified name of the service. This
// includes the package name (if there is one).
func (sd *ServiceDescriptor) GetFullyQualifiedName() string {
- return sd.fqn
+ return string(sd.wrapped.FullName())
}
// GetParent returns the descriptor for the file in which this service is
@@ -1370,7 +1517,7 @@
}
// GetServiceOptions returns the service's options.
-func (sd *ServiceDescriptor) GetServiceOptions() *dpb.ServiceOptions {
+func (sd *ServiceDescriptor) GetServiceOptions() *descriptorpb.ServiceOptions {
return sd.proto.GetOptions()
}
@@ -1379,7 +1526,7 @@
// returned info contains information about the location in the file where the
// service was defined and also contains comments associated with the service
// definition.
-func (sd *ServiceDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (sd *ServiceDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return sd.file.sourceInfo.Get(sd.sourceInfoPath)
}
@@ -1391,7 +1538,7 @@
}
// AsServiceDescriptorProto returns the underlying descriptor proto.
-func (sd *ServiceDescriptor) AsServiceDescriptorProto() *dpb.ServiceDescriptorProto {
+func (sd *ServiceDescriptor) AsServiceDescriptorProto() *descriptorpb.ServiceDescriptorProto {
return sd.proto
}
@@ -1408,7 +1555,7 @@
// FindMethodByName finds the method with the given name. If no such method exists
// then nil is returned.
func (sd *ServiceDescriptor) FindMethodByName(name string) *MethodDescriptor {
- fqn := fmt.Sprintf("%s.%s", sd.fqn, name)
+ fqn := fmt.Sprintf("%s.%s", sd.GetFullyQualifiedName(), name)
if md, ok := sd.file.symbols[fqn].(*MethodDescriptor); ok {
return md
} else {
@@ -1418,45 +1565,69 @@
// MethodDescriptor describes an RPC method declared in a proto file.
type MethodDescriptor struct {
- proto *dpb.MethodDescriptorProto
+ wrapped protoreflect.MethodDescriptor
+ proto *descriptorpb.MethodDescriptorProto
parent *ServiceDescriptor
file *FileDescriptor
inType *MessageDescriptor
outType *MessageDescriptor
- fqn string
sourceInfoPath []int32
}
-func createMethodDescriptor(fd *FileDescriptor, parent *ServiceDescriptor, enclosing string, md *dpb.MethodDescriptorProto) (*MethodDescriptor, string) {
- // request and response types get resolved later
- methodName := merge(enclosing, md.GetName())
- return &MethodDescriptor{proto: md, parent: parent, file: fd, fqn: methodName}, methodName
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapMethod, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (md *MethodDescriptor) Unwrap() protoreflect.Descriptor {
+ return md.wrapped
}
-func (md *MethodDescriptor) resolve(path []int32, scopes []scope) error {
- md.sourceInfoPath = append([]int32(nil), path...) // defensive copy
- if desc, err := resolve(md.file, md.proto.GetInputType(), scopes); err != nil {
- return err
- } else {
- md.inType = desc.(*MessageDescriptor)
+// UnwrapMethod returns the underlying protoreflect.MethodDescriptor.
+func (md *MethodDescriptor) UnwrapMethod() protoreflect.MethodDescriptor {
+ return md.wrapped
+}
+
+func createMethodDescriptor(fd *FileDescriptor, parent *ServiceDescriptor, md protoreflect.MethodDescriptor, mdp *descriptorpb.MethodDescriptorProto, path []int32) *MethodDescriptor {
+ // request and response types get resolved later
+ return &MethodDescriptor{
+ wrapped: md,
+ proto: mdp,
+ parent: parent,
+ file: fd,
+ sourceInfoPath: append([]int32(nil), path...), // defensive copy
}
- if desc, err := resolve(md.file, md.proto.GetOutputType(), scopes); err != nil {
+}
+
+func (md *MethodDescriptor) resolve(cache descriptorCache) error {
+ if desc, err := resolve(md.file, md.wrapped.Input(), cache); err != nil {
return err
} else {
- md.outType = desc.(*MessageDescriptor)
+ msgType, ok := desc.(*MessageDescriptor)
+ if !ok {
+ return fmt.Errorf("method %v has request type %q which should be a message but is %s", md.GetFullyQualifiedName(), md.proto.GetInputType(), descriptorType(desc))
+ }
+ md.inType = msgType
+ }
+ if desc, err := resolve(md.file, md.wrapped.Output(), cache); err != nil {
+ return err
+ } else {
+ msgType, ok := desc.(*MessageDescriptor)
+ if !ok {
+ return fmt.Errorf("method %v has response type %q which should be a message but is %s", md.GetFullyQualifiedName(), md.proto.GetOutputType(), descriptorType(desc))
+ }
+ md.outType = msgType
}
return nil
}
// GetName returns the name of the method.
func (md *MethodDescriptor) GetName() string {
- return md.proto.GetName()
+ return string(md.wrapped.Name())
}
// GetFullyQualifiedName returns the fully qualified name of the method. Unlike
// GetName, this includes fully qualified name of the enclosing service.
func (md *MethodDescriptor) GetFullyQualifiedName() string {
- return md.fqn
+ return string(md.wrapped.FullName())
}
// GetParent returns the descriptor for the service in which this method is
@@ -1485,7 +1656,7 @@
}
// GetMethodOptions returns the method's options.
-func (md *MethodDescriptor) GetMethodOptions() *dpb.MethodOptions {
+func (md *MethodDescriptor) GetMethodOptions() *descriptorpb.MethodOptions {
return md.proto.GetOptions()
}
@@ -1494,7 +1665,7 @@
// returned info contains information about the location in the file where the
// method was defined and also contains comments associated with the method
// definition.
-func (md *MethodDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (md *MethodDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return md.file.sourceInfo.Get(md.sourceInfoPath)
}
@@ -1506,7 +1677,7 @@
}
// AsMethodDescriptorProto returns the underlying descriptor proto.
-func (md *MethodDescriptor) AsMethodDescriptorProto() *dpb.MethodDescriptorProto {
+func (md *MethodDescriptor) AsMethodDescriptorProto() *descriptorpb.MethodDescriptorProto {
return md.proto
}
@@ -1517,12 +1688,12 @@
// IsServerStreaming returns true if this is a server-streaming method.
func (md *MethodDescriptor) IsServerStreaming() bool {
- return md.proto.GetServerStreaming()
+ return md.wrapped.IsStreamingServer()
}
// IsClientStreaming returns true if this is a client-streaming method.
func (md *MethodDescriptor) IsClientStreaming() bool {
- return md.proto.GetClientStreaming()
+ return md.wrapped.IsStreamingClient()
}
// GetInputType returns the input type, or request type, of the RPC method.
@@ -1537,17 +1708,34 @@
// OneOfDescriptor describes a one-of field set declared in a protocol buffer message.
type OneOfDescriptor struct {
- proto *dpb.OneofDescriptorProto
+ wrapped protoreflect.OneofDescriptor
+ proto *descriptorpb.OneofDescriptorProto
parent *MessageDescriptor
file *FileDescriptor
choices []*FieldDescriptor
- fqn string
sourceInfoPath []int32
}
-func createOneOfDescriptor(fd *FileDescriptor, parent *MessageDescriptor, index int, enclosing string, od *dpb.OneofDescriptorProto) (*OneOfDescriptor, string) {
- oneOfName := merge(enclosing, od.GetName())
- ret := &OneOfDescriptor{proto: od, parent: parent, file: fd, fqn: oneOfName}
+// Unwrap returns the underlying protoreflect.Descriptor. Most usages will be more
+// interested in UnwrapOneOf, which has a more specific return type. This generic
+// version is present to satisfy the DescriptorWrapper interface.
+func (od *OneOfDescriptor) Unwrap() protoreflect.Descriptor {
+ return od.wrapped
+}
+
+// UnwrapOneOf returns the underlying protoreflect.OneofDescriptor.
+func (od *OneOfDescriptor) UnwrapOneOf() protoreflect.OneofDescriptor {
+ return od.wrapped
+}
+
+func createOneOfDescriptor(fd *FileDescriptor, parent *MessageDescriptor, index int, od protoreflect.OneofDescriptor, odp *descriptorpb.OneofDescriptorProto, path []int32) *OneOfDescriptor {
+ ret := &OneOfDescriptor{
+ wrapped: od,
+ proto: odp,
+ parent: parent,
+ file: fd,
+ sourceInfoPath: append([]int32(nil), path...), // defensive copy
+ }
for _, f := range parent.fields {
oi := f.proto.OneofIndex
if oi != nil && *oi == int32(index) {
@@ -1555,22 +1743,18 @@
ret.choices = append(ret.choices, f)
}
}
- return ret, oneOfName
-}
-
-func (od *OneOfDescriptor) resolve(path []int32) {
- od.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+ return ret
}
// GetName returns the name of the one-of.
func (od *OneOfDescriptor) GetName() string {
- return od.proto.GetName()
+ return string(od.wrapped.Name())
}
// GetFullyQualifiedName returns the fully qualified name of the one-of. Unlike
// GetName, this includes fully qualified name of the enclosing message.
func (od *OneOfDescriptor) GetFullyQualifiedName() string {
- return od.fqn
+ return string(od.wrapped.FullName())
}
// GetParent returns the descriptor for the message in which this one-of is
@@ -1599,7 +1783,7 @@
}
// GetOneOfOptions returns the one-of's options.
-func (od *OneOfDescriptor) GetOneOfOptions() *dpb.OneofOptions {
+func (od *OneOfDescriptor) GetOneOfOptions() *descriptorpb.OneofOptions {
return od.proto.GetOptions()
}
@@ -1608,7 +1792,7 @@
// returned info contains information about the location in the file where the
// one-of was defined and also contains comments associated with the one-of
// definition.
-func (od *OneOfDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+func (od *OneOfDescriptor) GetSourceInfo() *descriptorpb.SourceCodeInfo_Location {
return od.file.sourceInfo.Get(od.sourceInfoPath)
}
@@ -1620,7 +1804,7 @@
}
// AsOneofDescriptorProto returns the underlying descriptor proto.
-func (od *OneOfDescriptor) AsOneofDescriptorProto() *dpb.OneofDescriptorProto {
+func (od *OneOfDescriptor) AsOneofDescriptorProto() *descriptorpb.OneofDescriptorProto {
return od.proto
}
@@ -1636,88 +1820,28 @@
}
func (od *OneOfDescriptor) IsSynthetic() bool {
- return len(od.choices) == 1 && od.choices[0].IsProto3Optional()
+ return od.wrapped.IsSynthetic()
}
-// scope represents a lexical scope in a proto file in which messages and enums
-// can be declared.
-type scope func(string) Descriptor
-
-func fileScope(fd *FileDescriptor) scope {
- // we search symbols in this file, but also symbols in other files that have
- // the same package as this file or a "parent" package (in protobuf,
- // packages are a hierarchy like C++ namespaces)
- prefixes := internal.CreatePrefixList(fd.proto.GetPackage())
- return func(name string) Descriptor {
- for _, prefix := range prefixes {
- n := merge(prefix, name)
- d := findSymbol(fd, n, false)
- if d != nil {
- return d
- }
- }
- return nil
+func resolve(fd *FileDescriptor, src protoreflect.Descriptor, cache descriptorCache) (Descriptor, error) {
+ d := cache.get(src)
+ if d != nil {
+ return d, nil
}
-}
-func messageScope(md *MessageDescriptor) scope {
- return func(name string) Descriptor {
- n := merge(md.fqn, name)
- if d, ok := md.file.symbols[n]; ok {
- return d
- }
- return nil
+ fqn := string(src.FullName())
+
+ d = fd.FindSymbol(fqn)
+ if d != nil {
+ return d, nil
}
-}
-func resolve(fd *FileDescriptor, name string, scopes []scope) (Descriptor, error) {
- if strings.HasPrefix(name, ".") {
- // already fully-qualified
- d := findSymbol(fd, name[1:], false)
+ for _, dep := range fd.deps {
+ d := dep.FindSymbol(fqn)
if d != nil {
return d, nil
}
- } else {
- // unqualified, so we look in the enclosing (last) scope first and move
- // towards outermost (first) scope, trying to resolve the symbol
- for i := len(scopes) - 1; i >= 0; i-- {
- d := scopes[i](name)
- if d != nil {
- return d, nil
- }
- }
- }
- return nil, fmt.Errorf("file %q included an unresolvable reference to %q", fd.proto.GetName(), name)
-}
-
-func findSymbol(fd *FileDescriptor, name string, public bool) Descriptor {
- d := fd.symbols[name]
- if d != nil {
- return d
}
- // When public = false, we are searching only directly imported symbols. But we
- // also need to search transitive public imports due to semantics of public imports.
- var deps []*FileDescriptor
- if public {
- deps = fd.publicDeps
- } else {
- deps = fd.deps
- }
- for _, dep := range deps {
- d = findSymbol(dep, name, true)
- if d != nil {
- return d
- }
- }
-
- return nil
-}
-
-func merge(a, b string) string {
- if a == "" {
- return b
- } else {
- return a + "." + b
- }
+ return nil, fmt.Errorf("file %q included an unresolvable reference to %q", fd.proto.GetName(), fqn)
}
diff --git a/vendor/github.com/jhump/protoreflect/desc/doc.go b/vendor/github.com/jhump/protoreflect/desc/doc.go
index 1740dce..07bcbf3 100644
--- a/vendor/github.com/jhump/protoreflect/desc/doc.go
+++ b/vendor/github.com/jhump/protoreflect/desc/doc.go
@@ -24,18 +24,47 @@
// properties that are not immediately accessible through rich descriptor's
// methods.
//
+// Also see the grpcreflect, dynamic, and grpcdynamic packages in this same
+// repo to see just how useful rich descriptors really are.
+//
+// # Loading Descriptors
+//
// Rich descriptors can be accessed in similar ways as their "poor" cousins
// (descriptor protos). Instead of using proto.FileDescriptor, use
// desc.LoadFileDescriptor. Message descriptors and extension field descriptors
// can also be easily accessed using desc.LoadMessageDescriptor and
// desc.LoadFieldDescriptorForExtension, respectively.
//
+// If you are using the protoc-gen-gosrcinfo plugin (also in this repo), then
+// the descriptors returned from these Load* functions will include source code
+// information, and thus include comments for elements.
+//
+// # Creating Descriptors
+//
// It is also possible create rich descriptors for proto messages that a given
// Go program doesn't even know about. For example, they could be loaded from a
// FileDescriptorSet file (which can be generated by protoc) or loaded from a
// server. This enables interesting things like dynamic clients: where a Go
// program can be an RPC client of a service it wasn't compiled to know about.
//
-// Also see the grpcreflect, dynamic, and grpcdynamic packages in this same
-// repo to see just how useful rich descriptors really are.
+// You cannot create a message descriptor without also creating its enclosing
+// file, because the enclosing file is what contains other relevant information
+// like other symbols and dependencies/imports, which is how type references
+// are resolved (such as when a field in a message has a type that is another
+// message or enum).
+//
+// So the functions in this package for creating descriptors are all for
+// creating *file* descriptors. See the various Create* functions for more
+// information.
+//
+// Also see the desc/builder sub-package, for another API that makes it easier
+// to synthesize descriptors programmatically.
+//
+// Deprecated: This module was created for use with the older "v1" Protobuf API
+// in github.com/golang/protobuf. However, much of this module is no longer
+// necessary as the newer "v2" API in google.golang.org/protobuf provides similar
+// capabilities. Instead of using this github.com/jhump/protoreflect/desc package,
+// see [google.golang.org/protobuf/reflect/protoreflect].
+//
+// [google.golang.org/protobuf/reflect/protoreflect]: https://pkg.go.dev/google.golang.org/protobuf/reflect/protoreflect
package desc
diff --git a/vendor/github.com/jhump/protoreflect/desc/imports.go b/vendor/github.com/jhump/protoreflect/desc/imports.go
index ab93032..dc6b735 100644
--- a/vendor/github.com/jhump/protoreflect/desc/imports.go
+++ b/vendor/github.com/jhump/protoreflect/desc/imports.go
@@ -8,7 +8,8 @@
"sync"
"github.com/golang/protobuf/proto"
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/reflect/protoregistry"
+ "google.golang.org/protobuf/types/descriptorpb"
)
var (
@@ -37,8 +38,8 @@
if len(importPath) == 0 {
panic("import path cannot be empty")
}
- desc := proto.FileDescriptor(registerPath)
- if len(desc) == 0 {
+ _, err := protoregistry.GlobalFiles.FindFileByPath(registerPath)
+ if err != nil {
panic(fmt.Sprintf("path %q is not a registered proto file", registerPath))
}
globalImportPathMu.Lock()
@@ -76,30 +77,40 @@
//
// For example, let's say we have two proto source files: "foo/bar.proto" and
// "fubar/baz.proto". The latter imports the former using a line like so:
-// import "foo/bar.proto";
+//
+// import "foo/bar.proto";
+//
// However, when protoc is invoked, the command-line args looks like so:
-// protoc -Ifoo/ --go_out=foo/ bar.proto
-// protoc -I./ -Ifubar/ --go_out=fubar/ baz.proto
+//
+// protoc -Ifoo/ --go_out=foo/ bar.proto
+// protoc -I./ -Ifubar/ --go_out=fubar/ baz.proto
+//
// Because the path given to protoc is just "bar.proto" and "baz.proto", this is
// how they are registered in the Go protobuf runtime. So, when loading the
// descriptor for "fubar/baz.proto", we'll see an import path of "foo/bar.proto"
// but will find no file registered with that path:
-// fd, err := desc.LoadFileDescriptor("baz.proto")
-// // err will be non-nil, complaining that there is no such file
-// // found named "foo/bar.proto"
+//
+// fd, err := desc.LoadFileDescriptor("baz.proto")
+// // err will be non-nil, complaining that there is no such file
+// // found named "foo/bar.proto"
//
// This can be remedied by registering alternate import paths using an
// ImportResolver. Continuing with the example above, the code below would fix
// any link issue:
-// var r desc.ImportResolver
-// r.RegisterImportPath("bar.proto", "foo/bar.proto")
-// fd, err := r.LoadFileDescriptor("baz.proto")
-// // err will be nil; descriptor successfully loaded!
+//
+// var r desc.ImportResolver
+// r.RegisterImportPath("bar.proto", "foo/bar.proto")
+// fd, err := r.LoadFileDescriptor("baz.proto")
+// // err will be nil; descriptor successfully loaded!
//
// If there are files that are *always* imported using a different relative
// path then how they are registered, consider using the global
// RegisterImportPath function, so you don't have to use an ImportResolver for
// every file that imports it.
+//
+// Note that the new protobuf runtime (v1.4+) verifies that import paths are
+// correct and that descriptors can be linked during package initialization. So
+// customizing import paths for descriptor resolution is no longer necessary.
type ImportResolver struct {
children map[string]*ImportResolver
importPaths map[string]string
@@ -134,7 +145,7 @@
return r.importPaths[importPath]
}
var car, cdr string
- idx := strings.IndexRune(source, filepath.Separator)
+ idx := strings.IndexRune(source, '/')
if idx < 0 {
car, cdr = source, ""
} else {
@@ -205,7 +216,7 @@
return
}
var car, cdr string
- idx := strings.IndexRune(source, filepath.Separator)
+ idx := strings.IndexRune(source, '/')
if idx < 0 {
car, cdr = source, ""
} else {
@@ -226,86 +237,86 @@
// any alternate paths configured in this resolver are used when linking the
// given descriptor proto.
func (r *ImportResolver) LoadFileDescriptor(filePath string) (*FileDescriptor, error) {
- return loadFileDescriptor(filePath, r)
+ return LoadFileDescriptor(filePath)
}
// LoadMessageDescriptor is the same as the package function of the same name,
// but any alternate paths configured in this resolver are used when linking
// files for the returned descriptor.
func (r *ImportResolver) LoadMessageDescriptor(msgName string) (*MessageDescriptor, error) {
- return loadMessageDescriptor(msgName, r)
+ return LoadMessageDescriptor(msgName)
}
// LoadMessageDescriptorForMessage is the same as the package function of the
// same name, but any alternate paths configured in this resolver are used when
// linking files for the returned descriptor.
func (r *ImportResolver) LoadMessageDescriptorForMessage(msg proto.Message) (*MessageDescriptor, error) {
- return loadMessageDescriptorForMessage(msg, r)
+ return LoadMessageDescriptorForMessage(msg)
}
// LoadMessageDescriptorForType is the same as the package function of the same
// name, but any alternate paths configured in this resolver are used when
// linking files for the returned descriptor.
func (r *ImportResolver) LoadMessageDescriptorForType(msgType reflect.Type) (*MessageDescriptor, error) {
- return loadMessageDescriptorForType(msgType, r)
+ return LoadMessageDescriptorForType(msgType)
}
// LoadEnumDescriptorForEnum is the same as the package function of the same
// name, but any alternate paths configured in this resolver are used when
// linking files for the returned descriptor.
func (r *ImportResolver) LoadEnumDescriptorForEnum(enum protoEnum) (*EnumDescriptor, error) {
- return loadEnumDescriptorForEnum(enum, r)
+ return LoadEnumDescriptorForEnum(enum)
}
// LoadEnumDescriptorForType is the same as the package function of the same
// name, but any alternate paths configured in this resolver are used when
// linking files for the returned descriptor.
func (r *ImportResolver) LoadEnumDescriptorForType(enumType reflect.Type) (*EnumDescriptor, error) {
- return loadEnumDescriptorForType(enumType, r)
+ return LoadEnumDescriptorForType(enumType)
}
// LoadFieldDescriptorForExtension is the same as the package function of the
// same name, but any alternate paths configured in this resolver are used when
// linking files for the returned descriptor.
func (r *ImportResolver) LoadFieldDescriptorForExtension(ext *proto.ExtensionDesc) (*FieldDescriptor, error) {
- return loadFieldDescriptorForExtension(ext, r)
+ return LoadFieldDescriptorForExtension(ext)
}
// CreateFileDescriptor is the same as the package function of the same name,
// but any alternate paths configured in this resolver are used when linking the
// given descriptor proto.
-func (r *ImportResolver) CreateFileDescriptor(fdp *dpb.FileDescriptorProto, deps ...*FileDescriptor) (*FileDescriptor, error) {
+func (r *ImportResolver) CreateFileDescriptor(fdp *descriptorpb.FileDescriptorProto, deps ...*FileDescriptor) (*FileDescriptor, error) {
return createFileDescriptor(fdp, deps, r)
}
// CreateFileDescriptors is the same as the package function of the same name,
// but any alternate paths configured in this resolver are used when linking the
// given descriptor protos.
-func (r *ImportResolver) CreateFileDescriptors(fds []*dpb.FileDescriptorProto) (map[string]*FileDescriptor, error) {
+func (r *ImportResolver) CreateFileDescriptors(fds []*descriptorpb.FileDescriptorProto) (map[string]*FileDescriptor, error) {
return createFileDescriptors(fds, r)
}
// CreateFileDescriptorFromSet is the same as the package function of the same
// name, but any alternate paths configured in this resolver are used when
// linking the descriptor protos in the given set.
-func (r *ImportResolver) CreateFileDescriptorFromSet(fds *dpb.FileDescriptorSet) (*FileDescriptor, error) {
+func (r *ImportResolver) CreateFileDescriptorFromSet(fds *descriptorpb.FileDescriptorSet) (*FileDescriptor, error) {
return createFileDescriptorFromSet(fds, r)
}
// CreateFileDescriptorsFromSet is the same as the package function of the same
// name, but any alternate paths configured in this resolver are used when
// linking the descriptor protos in the given set.
-func (r *ImportResolver) CreateFileDescriptorsFromSet(fds *dpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
+func (r *ImportResolver) CreateFileDescriptorsFromSet(fds *descriptorpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
return createFileDescriptorsFromSet(fds, r)
}
-const dotPrefix = "." + string(filepath.Separator)
+const dotPrefix = "./"
func clean(path string) string {
if path == "" {
return ""
}
- path = filepath.Clean(path)
+ path = filepath.ToSlash(filepath.Clean(path))
if path == "." {
return ""
}
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/proto3_optional.go b/vendor/github.com/jhump/protoreflect/desc/internal/proto3_optional.go
index 9aa4a3e..aa8c3e9 100644
--- a/vendor/github.com/jhump/protoreflect/desc/internal/proto3_optional.go
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/proto3_optional.go
@@ -1,86 +1,37 @@
package internal
import (
- "github.com/golang/protobuf/proto"
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
- "github.com/jhump/protoreflect/internal/codec"
- "reflect"
"strings"
- "github.com/jhump/protoreflect/internal"
+ "github.com/golang/protobuf/proto"
+ "google.golang.org/protobuf/types/descriptorpb"
)
-// NB: We use reflection or unknown fields in case we are linked against an older
-// version of the proto runtime which does not know about the proto3_optional field.
-// We don't require linking with newer version (which would greatly simplify this)
-// because that means pulling in v1.4+ of the protobuf runtime, which has some
-// compatibility issues. (We'll be nice to users and not require they upgrade to
-// that latest runtime to upgrade to newer protoreflect.)
-
-func GetProto3Optional(fd *dpb.FieldDescriptorProto) bool {
- type newerFieldDesc interface {
- GetProto3Optional() bool
- }
- var pm proto.Message = fd
- if fd, ok := pm.(newerFieldDesc); ok {
- return fd.GetProto3Optional()
- }
-
- // Field does not exist, so we have to examine unknown fields
- // (we just silently bail if we have problems parsing them)
- unk := internal.GetUnrecognized(pm)
- buf := codec.NewBuffer(unk)
- for {
- tag, wt, err := buf.DecodeTagAndWireType()
- if err != nil {
- return false
- }
- if tag == Field_proto3OptionalTag && wt == proto.WireVarint {
- v, _ := buf.DecodeVarint()
- return v != 0
- }
- if err := buf.SkipField(wt); err != nil {
- return false
- }
- }
-}
-
-func SetProto3Optional(fd *dpb.FieldDescriptorProto) {
- rv := reflect.ValueOf(fd).Elem()
- fld := rv.FieldByName("Proto3Optional")
- if fld.IsValid() {
- fld.Set(reflect.ValueOf(proto.Bool(true)))
- return
- }
-
- // Field does not exist, so we have to store as unknown field.
- var buf codec.Buffer
- if err := buf.EncodeTagAndWireType(Field_proto3OptionalTag, proto.WireVarint); err != nil {
- // TODO: panic? log?
- return
- }
- if err := buf.EncodeVarint(1); err != nil {
- // TODO: panic? log?
- return
- }
- internal.SetUnrecognized(fd, buf.Bytes())
-}
-
// ProcessProto3OptionalFields adds synthetic oneofs to the given message descriptor
// for each proto3 optional field. It also updates the fields to have the correct
-// oneof index reference.
-func ProcessProto3OptionalFields(msgd *dpb.DescriptorProto) {
+// oneof index reference. The given callback, if not nil, is called for each synthetic
+// oneof created.
+func ProcessProto3OptionalFields(msgd *descriptorpb.DescriptorProto, callback func(*descriptorpb.FieldDescriptorProto, *descriptorpb.OneofDescriptorProto)) {
var allNames map[string]struct{}
for _, fd := range msgd.Field {
- if GetProto3Optional(fd) {
+ if fd.GetProto3Optional() {
// lazy init the set of all names
if allNames == nil {
allNames = map[string]struct{}{}
for _, fd := range msgd.Field {
allNames[fd.GetName()] = struct{}{}
}
- for _, fd := range msgd.Extension {
- allNames[fd.GetName()] = struct{}{}
+ for _, od := range msgd.OneofDecl {
+ allNames[od.GetName()] = struct{}{}
+ }
+ // NB: protoc only considers names of other fields and oneofs
+ // when computing the synthetic oneof name. But that feels like
+ // a bug, since it means it could generate a name that conflicts
+ // with some other symbol defined in the message. If it's decided
+ // that's NOT a bug and is desirable, then we should remove the
+ // following four loops to mimic protoc's behavior.
+ for _, xd := range msgd.Extension {
+ allNames[xd.GetName()] = struct{}{}
}
for _, ed := range msgd.EnumType {
allNames[ed.GetName()] = struct{}{}
@@ -114,7 +65,11 @@
}
fd.OneofIndex = proto.Int32(int32(len(msgd.OneofDecl)))
- msgd.OneofDecl = append(msgd.OneofDecl, &dpb.OneofDescriptorProto{Name: proto.String(ooName)})
+ ood := &descriptorpb.OneofDescriptorProto{Name: proto.String(ooName)}
+ msgd.OneofDecl = append(msgd.OneofDecl, ood)
+ if callback != nil {
+ callback(fd, ood)
+ }
}
}
}
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/registry.go b/vendor/github.com/jhump/protoreflect/desc/internal/registry.go
new file mode 100644
index 0000000..d7259e4
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/registry.go
@@ -0,0 +1,67 @@
+package internal
+
+import (
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+ "google.golang.org/protobuf/types/dynamicpb"
+)
+
+// RegisterExtensionsFromImportedFile registers extensions in the given file as well
+// as those in its public imports. So if another file imports the given fd, this adds
+// all extensions made visible to that importing file.
+//
+// All extensions in the given file are made visible to the importing file, and so are
+// extensions in any public imports in the given file.
+func RegisterExtensionsFromImportedFile(reg *protoregistry.Types, fd protoreflect.FileDescriptor) {
+ registerTypesForFile(reg, fd, true, true)
+}
+
+// RegisterExtensionsVisibleToFile registers all extensions visible to the given file.
+// This includes all extensions defined in fd and as well as extensions defined in the
+// files that it imports (and any public imports thereof, etc).
+//
+// This is effectively the same as registering the extensions in fd and then calling
+// RegisterExtensionsFromImportedFile for each file imported by fd.
+func RegisterExtensionsVisibleToFile(reg *protoregistry.Types, fd protoreflect.FileDescriptor) {
+ registerTypesForFile(reg, fd, true, false)
+}
+
+// RegisterTypesVisibleToFile registers all types visible to the given file.
+// This is the same as RegisterExtensionsVisibleToFile but it also registers
+// message and enum types, not just extensions.
+func RegisterTypesVisibleToFile(reg *protoregistry.Types, fd protoreflect.FileDescriptor) {
+ registerTypesForFile(reg, fd, false, false)
+}
+
+func registerTypesForFile(reg *protoregistry.Types, fd protoreflect.FileDescriptor, extensionsOnly, publicImportsOnly bool) {
+ registerTypes(reg, fd, extensionsOnly)
+ for i := 0; i < fd.Imports().Len(); i++ {
+ imp := fd.Imports().Get(i)
+ if imp.IsPublic || !publicImportsOnly {
+ registerTypesForFile(reg, imp, extensionsOnly, true)
+ }
+ }
+}
+
+func registerTypes(reg *protoregistry.Types, elem fileOrMessage, extensionsOnly bool) {
+ for i := 0; i < elem.Extensions().Len(); i++ {
+ _ = reg.RegisterExtension(dynamicpb.NewExtensionType(elem.Extensions().Get(i)))
+ }
+ if !extensionsOnly {
+ for i := 0; i < elem.Messages().Len(); i++ {
+ _ = reg.RegisterMessage(dynamicpb.NewMessageType(elem.Messages().Get(i)))
+ }
+ for i := 0; i < elem.Enums().Len(); i++ {
+ _ = reg.RegisterEnum(dynamicpb.NewEnumType(elem.Enums().Get(i)))
+ }
+ }
+ for i := 0; i < elem.Messages().Len(); i++ {
+ registerTypes(reg, elem.Messages().Get(i), extensionsOnly)
+ }
+}
+
+type fileOrMessage interface {
+ Extensions() protoreflect.ExtensionDescriptors
+ Messages() protoreflect.MessageDescriptors
+ Enums() protoreflect.EnumDescriptors
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go b/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
index b4150b8..6037128 100644
--- a/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
@@ -1,16 +1,16 @@
package internal
import (
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/types/descriptorpb"
)
// SourceInfoMap is a map of paths in a descriptor to the corresponding source
// code info.
-type SourceInfoMap map[string][]*dpb.SourceCodeInfo_Location
+type SourceInfoMap map[string][]*descriptorpb.SourceCodeInfo_Location
// Get returns the source code info for the given path. If there are
// multiple locations for the same path, the first one is returned.
-func (m SourceInfoMap) Get(path []int32) *dpb.SourceCodeInfo_Location {
+func (m SourceInfoMap) Get(path []int32) *descriptorpb.SourceCodeInfo_Location {
v := m[asMapKey(path)]
if len(v) > 0 {
return v[0]
@@ -19,24 +19,24 @@
}
// GetAll returns all source code info for the given path.
-func (m SourceInfoMap) GetAll(path []int32) []*dpb.SourceCodeInfo_Location {
+func (m SourceInfoMap) GetAll(path []int32) []*descriptorpb.SourceCodeInfo_Location {
return m[asMapKey(path)]
}
// Add stores the given source code info for the given path.
-func (m SourceInfoMap) Add(path []int32, loc *dpb.SourceCodeInfo_Location) {
+func (m SourceInfoMap) Add(path []int32, loc *descriptorpb.SourceCodeInfo_Location) {
m[asMapKey(path)] = append(m[asMapKey(path)], loc)
}
// PutIfAbsent stores the given source code info for the given path only if the
// given path does not exist in the map. This method returns true when the value
// is stored, false if the path already exists.
-func (m SourceInfoMap) PutIfAbsent(path []int32, loc *dpb.SourceCodeInfo_Location) bool {
+func (m SourceInfoMap) PutIfAbsent(path []int32, loc *descriptorpb.SourceCodeInfo_Location) bool {
k := asMapKey(path)
if _, ok := m[k]; ok {
return false
}
- m[k] = []*dpb.SourceCodeInfo_Location{loc}
+ m[k] = []*descriptorpb.SourceCodeInfo_Location{loc}
return true
}
@@ -63,7 +63,7 @@
// CreateSourceInfoMap constructs a new SourceInfoMap and populates it with the
// source code info in the given file descriptor proto.
-func CreateSourceInfoMap(fd *dpb.FileDescriptorProto) SourceInfoMap {
+func CreateSourceInfoMap(fd *descriptorpb.FileDescriptorProto) SourceInfoMap {
res := SourceInfoMap{}
PopulateSourceInfoMap(fd, res)
return res
@@ -71,7 +71,7 @@
// PopulateSourceInfoMap populates the given SourceInfoMap with information from
// the given file descriptor.
-func PopulateSourceInfoMap(fd *dpb.FileDescriptorProto, m SourceInfoMap) {
+func PopulateSourceInfoMap(fd *descriptorpb.FileDescriptorProto, m SourceInfoMap) {
for _, l := range fd.GetSourceCodeInfo().GetLocation() {
m.Add(l.Path, l)
}
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/util.go b/vendor/github.com/jhump/protoreflect/desc/internal/util.go
index 71855bf..595c872 100644
--- a/vendor/github.com/jhump/protoreflect/desc/internal/util.go
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/util.go
@@ -54,6 +54,9 @@
// File_syntaxTag is the tag number of the syntax element in a file
// descriptor proto.
File_syntaxTag = 12
+ // File_editionTag is the tag number of the edition element in a file
+ // descriptor proto.
+ File_editionTag = 14
// Message_nameTag is the tag number of the name element in a message
// descriptor proto.
Message_nameTag = 1
@@ -219,17 +222,18 @@
)
// JsonName returns the default JSON name for a field with the given name.
+// This mirrors the algorithm in protoc:
+//
+// https://github.com/protocolbuffers/protobuf/blob/v21.3/src/google/protobuf/descriptor.cc#L95
func JsonName(name string) string {
var js []rune
nextUpper := false
- for i, r := range name {
+ for _, r := range name {
if r == '_' {
nextUpper = true
continue
}
- if i == 0 {
- js = append(js, r)
- } else if nextUpper {
+ if nextUpper {
nextUpper = false
js = append(js, unicode.ToUpper(r))
} else {
@@ -251,7 +255,8 @@
// that token and the empty string, e.g. ["foo", ""]. Otherwise, it returns
// successively shorter prefixes of the package and then the empty string. For
// example, for a package named "foo.bar.baz" it will return the following list:
-// ["foo.bar.baz", "foo.bar", "foo", ""]
+//
+// ["foo.bar.baz", "foo.bar", "foo", ""]
func CreatePrefixList(pkg string) []string {
if pkg == "" {
return []string{""}
diff --git a/vendor/github.com/jhump/protoreflect/desc/load.go b/vendor/github.com/jhump/protoreflect/desc/load.go
index 4a05830..8fd09ac 100644
--- a/vendor/github.com/jhump/protoreflect/desc/load.go
+++ b/vendor/github.com/jhump/protoreflect/desc/load.go
@@ -1,150 +1,109 @@
package desc
import (
+ "errors"
"fmt"
"reflect"
"sync"
"github.com/golang/protobuf/proto"
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+ "google.golang.org/protobuf/types/descriptorpb"
+ "github.com/jhump/protoreflect/desc/sourceinfo"
"github.com/jhump/protoreflect/internal"
)
+// The global cache is used to store descriptors that wrap items in
+// protoregistry.GlobalTypes and protoregistry.GlobalFiles. This prevents
+// repeating work to re-wrap underlying global descriptors.
var (
- cacheMu sync.RWMutex
- filesCache = map[string]*FileDescriptor{}
- messagesCache = map[string]*MessageDescriptor{}
- enumCache = map[reflect.Type]*EnumDescriptor{}
+ // We put all wrapped file and message descriptors in this cache.
+ loadedDescriptors = lockingCache{cache: mapCache{}}
+
+ // Unfortunately, we need a different mechanism for enums for
+ // compatibility with old APIs, which required that they were
+ // registered in a different way :(
+ loadedEnumsMu sync.RWMutex
+ loadedEnums = map[reflect.Type]*EnumDescriptor{}
)
// LoadFileDescriptor creates a file descriptor using the bytes returned by
// proto.FileDescriptor. Descriptors are cached so that they do not need to be
// re-processed if the same file is fetched again later.
func LoadFileDescriptor(file string) (*FileDescriptor, error) {
- return loadFileDescriptor(file, nil)
-}
-
-func loadFileDescriptor(file string, r *ImportResolver) (*FileDescriptor, error) {
- f := getFileFromCache(file)
- if f != nil {
- return f, nil
- }
- cacheMu.Lock()
- defer cacheMu.Unlock()
- return loadFileDescriptorLocked(file, r)
-}
-
-func loadFileDescriptorLocked(file string, r *ImportResolver) (*FileDescriptor, error) {
- f := filesCache[file]
- if f != nil {
- return f, nil
- }
- fd, err := internal.LoadFileDescriptor(file)
- if err != nil {
- return nil, err
- }
-
- f, err = toFileDescriptorLocked(fd, r)
- if err != nil {
- return nil, err
- }
- putCacheLocked(file, f)
- return f, nil
-}
-
-func toFileDescriptorLocked(fd *dpb.FileDescriptorProto, r *ImportResolver) (*FileDescriptor, error) {
- deps := make([]*FileDescriptor, len(fd.GetDependency()))
- for i, dep := range fd.GetDependency() {
- resolvedDep := r.ResolveImport(fd.GetName(), dep)
- var err error
- deps[i], err = loadFileDescriptorLocked(resolvedDep, r)
- if _, ok := err.(internal.ErrNoSuchFile); ok && resolvedDep != dep {
- // try original path
- deps[i], err = loadFileDescriptorLocked(dep, r)
- }
- if err != nil {
- return nil, err
+ d, err := sourceinfo.GlobalFiles.FindFileByPath(file)
+ if errors.Is(err, protoregistry.NotFound) {
+ // for backwards compatibility, see if this matches a known old
+ // alias for the file (older versions of libraries that registered
+ // the files using incorrect/non-canonical paths)
+ if alt := internal.StdFileAliases[file]; alt != "" {
+ d, err = sourceinfo.GlobalFiles.FindFileByPath(alt)
}
}
- return CreateFileDescriptor(fd, deps...)
-}
-
-func getFileFromCache(file string) *FileDescriptor {
- cacheMu.RLock()
- defer cacheMu.RUnlock()
- return filesCache[file]
-}
-
-func putCacheLocked(filename string, fd *FileDescriptor) {
- filesCache[filename] = fd
- putMessageCacheLocked(fd.messages)
-}
-
-func putMessageCacheLocked(mds []*MessageDescriptor) {
- for _, md := range mds {
- messagesCache[md.fqn] = md
- putMessageCacheLocked(md.nested)
+ if err != nil {
+ if !errors.Is(err, protoregistry.NotFound) {
+ return nil, internal.ErrNoSuchFile(file)
+ }
+ return nil, err
}
-}
+ if fd := loadedDescriptors.get(d); fd != nil {
+ return fd.(*FileDescriptor), nil
+ }
-// interface implemented by generated messages, which all have a Descriptor() method in
-// addition to the methods of proto.Message
-type protoMessage interface {
- proto.Message
- Descriptor() ([]byte, []int)
+ var fd *FileDescriptor
+ loadedDescriptors.withLock(func(cache descriptorCache) {
+ fd, err = wrapFile(d, cache)
+ })
+ return fd, err
}
// LoadMessageDescriptor loads descriptor using the encoded descriptor proto returned by
// Message.Descriptor() for the given message type. If the given type is not recognized,
// then a nil descriptor is returned.
func LoadMessageDescriptor(message string) (*MessageDescriptor, error) {
- return loadMessageDescriptor(message, nil)
+ mt, err := sourceinfo.GlobalTypes.FindMessageByName(protoreflect.FullName(message))
+ if err != nil {
+ if errors.Is(err, protoregistry.NotFound) {
+ return nil, nil
+ }
+ return nil, err
+ }
+ return loadMessageDescriptor(mt.Descriptor())
}
-func loadMessageDescriptor(message string, r *ImportResolver) (*MessageDescriptor, error) {
- m := getMessageFromCache(message)
- if m != nil {
- return m, nil
+func loadMessageDescriptor(md protoreflect.MessageDescriptor) (*MessageDescriptor, error) {
+ d := loadedDescriptors.get(md)
+ if d != nil {
+ return d.(*MessageDescriptor), nil
}
- pt := proto.MessageType(message)
- if pt == nil {
- return nil, nil
- }
- msg, err := messageFromType(pt)
+ var err error
+ loadedDescriptors.withLock(func(cache descriptorCache) {
+ d, err = wrapMessage(md, cache)
+ })
if err != nil {
return nil, err
}
-
- cacheMu.Lock()
- defer cacheMu.Unlock()
- return loadMessageDescriptorForTypeLocked(message, msg, r)
+ return d.(*MessageDescriptor), err
}
// LoadMessageDescriptorForType loads descriptor using the encoded descriptor proto returned
// by message.Descriptor() for the given message type. If the given type is not recognized,
// then a nil descriptor is returned.
func LoadMessageDescriptorForType(messageType reflect.Type) (*MessageDescriptor, error) {
- return loadMessageDescriptorForType(messageType, nil)
-}
-
-func loadMessageDescriptorForType(messageType reflect.Type, r *ImportResolver) (*MessageDescriptor, error) {
m, err := messageFromType(messageType)
if err != nil {
return nil, err
}
- return loadMessageDescriptorForMessage(m, r)
+ return LoadMessageDescriptorForMessage(m)
}
// LoadMessageDescriptorForMessage loads descriptor using the encoded descriptor proto
// returned by message.Descriptor(). If the given type is not recognized, then a nil
// descriptor is returned.
func LoadMessageDescriptorForMessage(message proto.Message) (*MessageDescriptor, error) {
- return loadMessageDescriptorForMessage(message, nil)
-}
-
-func loadMessageDescriptorForMessage(message proto.Message, r *ImportResolver) (*MessageDescriptor, error) {
// efficiently handle dynamic messages
type descriptorable interface {
GetMessageDescriptor() *MessageDescriptor
@@ -153,57 +112,26 @@
return d.GetMessageDescriptor(), nil
}
- name := proto.MessageName(message)
- if name == "" {
- return nil, nil
+ var md protoreflect.MessageDescriptor
+ if m, ok := message.(protoreflect.ProtoMessage); ok {
+ md = m.ProtoReflect().Descriptor()
+ } else {
+ md = proto.MessageReflect(message).Descriptor()
}
- m := getMessageFromCache(name)
- if m != nil {
- return m, nil
- }
-
- cacheMu.Lock()
- defer cacheMu.Unlock()
- return loadMessageDescriptorForTypeLocked(name, message.(protoMessage), nil)
+ return loadMessageDescriptor(sourceinfo.WrapMessage(md))
}
-func messageFromType(mt reflect.Type) (protoMessage, error) {
+func messageFromType(mt reflect.Type) (proto.Message, error) {
if mt.Kind() != reflect.Ptr {
mt = reflect.PtrTo(mt)
}
- m, ok := reflect.Zero(mt).Interface().(protoMessage)
+ m, ok := reflect.Zero(mt).Interface().(proto.Message)
if !ok {
return nil, fmt.Errorf("failed to create message from type: %v", mt)
}
return m, nil
}
-func loadMessageDescriptorForTypeLocked(name string, message protoMessage, r *ImportResolver) (*MessageDescriptor, error) {
- m := messagesCache[name]
- if m != nil {
- return m, nil
- }
-
- fdb, _ := message.Descriptor()
- fd, err := internal.DecodeFileDescriptor(name, fdb)
- if err != nil {
- return nil, err
- }
-
- f, err := toFileDescriptorLocked(fd, r)
- if err != nil {
- return nil, err
- }
- putCacheLocked(fd.GetName(), f)
- return f.FindSymbol(name).(*MessageDescriptor), nil
-}
-
-func getMessageFromCache(message string) *MessageDescriptor {
- cacheMu.RLock()
- defer cacheMu.RUnlock()
- return messagesCache[message]
-}
-
// interface implemented by all generated enums
type protoEnum interface {
EnumDescriptor() ([]byte, []int)
@@ -220,10 +148,6 @@
// LoadEnumDescriptorForType loads descriptor using the encoded descriptor proto returned
// by enum.EnumDescriptor() for the given enum type.
func LoadEnumDescriptorForType(enumType reflect.Type) (*EnumDescriptor, error) {
- return loadEnumDescriptorForType(enumType, nil)
-}
-
-func loadEnumDescriptorForType(enumType reflect.Type, r *ImportResolver) (*EnumDescriptor, error) {
// we cache descriptors using non-pointer type
if enumType.Kind() == reflect.Ptr {
enumType = enumType.Elem()
@@ -237,18 +161,24 @@
return nil, err
}
- cacheMu.Lock()
- defer cacheMu.Unlock()
- return loadEnumDescriptorForTypeLocked(enumType, enum, r)
+ return loadEnumDescriptor(enumType, enum)
+}
+
+func getEnumFromCache(t reflect.Type) *EnumDescriptor {
+ loadedEnumsMu.RLock()
+ defer loadedEnumsMu.RUnlock()
+ return loadedEnums[t]
+}
+
+func putEnumInCache(t reflect.Type, d *EnumDescriptor) {
+ loadedEnumsMu.Lock()
+ defer loadedEnumsMu.Unlock()
+ loadedEnums[t] = d
}
// LoadEnumDescriptorForEnum loads descriptor using the encoded descriptor proto
// returned by enum.EnumDescriptor().
func LoadEnumDescriptorForEnum(enum protoEnum) (*EnumDescriptor, error) {
- return loadEnumDescriptorForEnum(enum, nil)
-}
-
-func loadEnumDescriptorForEnum(enum protoEnum, r *ImportResolver) (*EnumDescriptor, error) {
et := reflect.TypeOf(enum)
// we cache descriptors using non-pointer type
if et.Kind() == reflect.Ptr {
@@ -260,55 +190,46 @@
return e, nil
}
- cacheMu.Lock()
- defer cacheMu.Unlock()
- return loadEnumDescriptorForTypeLocked(et, enum, r)
+ return loadEnumDescriptor(et, enum)
}
func enumFromType(et reflect.Type) (protoEnum, error) {
- if et.Kind() != reflect.Int32 {
- et = reflect.PtrTo(et)
- }
e, ok := reflect.Zero(et).Interface().(protoEnum)
if !ok {
+ if et.Kind() != reflect.Ptr {
+ et = et.Elem()
+ }
+ e, ok = reflect.Zero(et).Interface().(protoEnum)
+ }
+ if !ok {
return nil, fmt.Errorf("failed to create enum from type: %v", et)
}
return e, nil
}
-func loadEnumDescriptorForTypeLocked(et reflect.Type, enum protoEnum, r *ImportResolver) (*EnumDescriptor, error) {
- e := enumCache[et]
- if e != nil {
- return e, nil
- }
-
+func getDescriptorForEnum(enum protoEnum) (*descriptorpb.FileDescriptorProto, []int, error) {
fdb, path := enum.EnumDescriptor()
- name := fmt.Sprintf("%v", et)
+ name := fmt.Sprintf("%T", enum)
fd, err := internal.DecodeFileDescriptor(name, fdb)
+ return fd, path, err
+}
+
+func loadEnumDescriptor(et reflect.Type, enum protoEnum) (*EnumDescriptor, error) {
+ fdp, path, err := getDescriptorForEnum(enum)
if err != nil {
return nil, err
}
- // see if we already have cached "rich" descriptor
- f, ok := filesCache[fd.GetName()]
- if !ok {
- f, err = toFileDescriptorLocked(fd, r)
- if err != nil {
- return nil, err
- }
- putCacheLocked(fd.GetName(), f)
+
+ fd, err := LoadFileDescriptor(fdp.GetName())
+ if err != nil {
+ return nil, err
}
- ed := findEnum(f, path)
- enumCache[et] = ed
+ ed := findEnum(fd, path)
+ putEnumInCache(et, ed)
return ed, nil
}
-func getEnumFromCache(et reflect.Type) *EnumDescriptor {
- cacheMu.RLock()
- defer cacheMu.RUnlock()
- return enumCache[et]
-}
-
func findEnum(fd *FileDescriptor, path []int) *EnumDescriptor {
if len(path) == 1 {
return fd.GetEnumTypes()[path[0]]
@@ -323,11 +244,7 @@
// LoadFieldDescriptorForExtension loads the field descriptor that corresponds to the given
// extension description.
func LoadFieldDescriptorForExtension(ext *proto.ExtensionDesc) (*FieldDescriptor, error) {
- return loadFieldDescriptorForExtension(ext, nil)
-}
-
-func loadFieldDescriptorForExtension(ext *proto.ExtensionDesc, r *ImportResolver) (*FieldDescriptor, error) {
- file, err := loadFileDescriptor(ext.Filename, r)
+ file, err := LoadFileDescriptor(ext.Filename)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/jhump/protoreflect/desc/sourceinfo/locations.go b/vendor/github.com/jhump/protoreflect/desc/sourceinfo/locations.go
new file mode 100644
index 0000000..20d2d7a
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/sourceinfo/locations.go
@@ -0,0 +1,207 @@
+package sourceinfo
+
+import (
+ "math"
+ "sync"
+
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/types/descriptorpb"
+
+ "github.com/jhump/protoreflect/desc/internal"
+)
+
+// NB: forked from google.golang.org/protobuf/internal/filedesc
+type sourceLocations struct {
+ protoreflect.SourceLocations
+
+ orig []*descriptorpb.SourceCodeInfo_Location
+ // locs is a list of sourceLocations.
+ // The SourceLocation.Next field does not need to be populated
+ // as it will be lazily populated upon first need.
+ locs []protoreflect.SourceLocation
+
+ // fd is the parent file descriptor that these locations are relative to.
+ // If non-nil, ByDescriptor verifies that the provided descriptor
+ // is a child of this file descriptor.
+ fd protoreflect.FileDescriptor
+
+ once sync.Once
+ byPath map[pathKey]int
+}
+
+func (p *sourceLocations) Len() int { return len(p.orig) }
+func (p *sourceLocations) Get(i int) protoreflect.SourceLocation {
+ return p.lazyInit().locs[i]
+}
+func (p *sourceLocations) byKey(k pathKey) protoreflect.SourceLocation {
+ if i, ok := p.lazyInit().byPath[k]; ok {
+ return p.locs[i]
+ }
+ return protoreflect.SourceLocation{}
+}
+func (p *sourceLocations) ByPath(path protoreflect.SourcePath) protoreflect.SourceLocation {
+ return p.byKey(newPathKey(path))
+}
+func (p *sourceLocations) ByDescriptor(desc protoreflect.Descriptor) protoreflect.SourceLocation {
+ if p.fd != nil && desc != nil && p.fd != desc.ParentFile() {
+ return protoreflect.SourceLocation{} // mismatching parent imports
+ }
+ var pathArr [16]int32
+ path := pathArr[:0]
+ for {
+ switch desc.(type) {
+ case protoreflect.FileDescriptor:
+ // Reverse the path since it was constructed in reverse.
+ for i, j := 0, len(path)-1; i < j; i, j = i+1, j-1 {
+ path[i], path[j] = path[j], path[i]
+ }
+ return p.byKey(newPathKey(path))
+ case protoreflect.MessageDescriptor:
+ path = append(path, int32(desc.Index()))
+ desc = desc.Parent()
+ switch desc.(type) {
+ case protoreflect.FileDescriptor:
+ path = append(path, int32(internal.File_messagesTag))
+ case protoreflect.MessageDescriptor:
+ path = append(path, int32(internal.Message_nestedMessagesTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ case protoreflect.FieldDescriptor:
+ isExtension := desc.(protoreflect.FieldDescriptor).IsExtension()
+ path = append(path, int32(desc.Index()))
+ desc = desc.Parent()
+ if isExtension {
+ switch desc.(type) {
+ case protoreflect.FileDescriptor:
+ path = append(path, int32(internal.File_extensionsTag))
+ case protoreflect.MessageDescriptor:
+ path = append(path, int32(internal.Message_extensionsTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ } else {
+ switch desc.(type) {
+ case protoreflect.MessageDescriptor:
+ path = append(path, int32(internal.Message_fieldsTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ }
+ case protoreflect.OneofDescriptor:
+ path = append(path, int32(desc.Index()))
+ desc = desc.Parent()
+ switch desc.(type) {
+ case protoreflect.MessageDescriptor:
+ path = append(path, int32(internal.Message_oneOfsTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ case protoreflect.EnumDescriptor:
+ path = append(path, int32(desc.Index()))
+ desc = desc.Parent()
+ switch desc.(type) {
+ case protoreflect.FileDescriptor:
+ path = append(path, int32(internal.File_enumsTag))
+ case protoreflect.MessageDescriptor:
+ path = append(path, int32(internal.Message_enumsTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ case protoreflect.EnumValueDescriptor:
+ path = append(path, int32(desc.Index()))
+ desc = desc.Parent()
+ switch desc.(type) {
+ case protoreflect.EnumDescriptor:
+ path = append(path, int32(internal.Enum_valuesTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ case protoreflect.ServiceDescriptor:
+ path = append(path, int32(desc.Index()))
+ desc = desc.Parent()
+ switch desc.(type) {
+ case protoreflect.FileDescriptor:
+ path = append(path, int32(internal.File_servicesTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ case protoreflect.MethodDescriptor:
+ path = append(path, int32(desc.Index()))
+ desc = desc.Parent()
+ switch desc.(type) {
+ case protoreflect.ServiceDescriptor:
+ path = append(path, int32(internal.Service_methodsTag))
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ default:
+ return protoreflect.SourceLocation{}
+ }
+ }
+}
+func (p *sourceLocations) lazyInit() *sourceLocations {
+ p.once.Do(func() {
+ if len(p.orig) > 0 {
+ p.locs = make([]protoreflect.SourceLocation, len(p.orig))
+ // Collect all the indexes for a given path.
+ pathIdxs := make(map[pathKey][]int, len(p.locs))
+ for i := range p.orig {
+ l := asSourceLocation(p.orig[i])
+ p.locs[i] = l
+ k := newPathKey(l.Path)
+ pathIdxs[k] = append(pathIdxs[k], i)
+ }
+
+ // Update the next index for all locations.
+ p.byPath = make(map[pathKey]int, len(p.locs))
+ for k, idxs := range pathIdxs {
+ for i := 0; i < len(idxs)-1; i++ {
+ p.locs[idxs[i]].Next = idxs[i+1]
+ }
+ p.locs[idxs[len(idxs)-1]].Next = 0
+ p.byPath[k] = idxs[0] // record the first location for this path
+ }
+ }
+ })
+ return p
+}
+
+func asSourceLocation(l *descriptorpb.SourceCodeInfo_Location) protoreflect.SourceLocation {
+ endLine := l.Span[0]
+ endCol := l.Span[2]
+ if len(l.Span) > 3 {
+ endLine = l.Span[2]
+ endCol = l.Span[3]
+ }
+ return protoreflect.SourceLocation{
+ Path: l.Path,
+ StartLine: int(l.Span[0]),
+ StartColumn: int(l.Span[1]),
+ EndLine: int(endLine),
+ EndColumn: int(endCol),
+ LeadingDetachedComments: l.LeadingDetachedComments,
+ LeadingComments: l.GetLeadingComments(),
+ TrailingComments: l.GetTrailingComments(),
+ }
+}
+
+// pathKey is a comparable representation of protoreflect.SourcePath.
+type pathKey struct {
+ arr [16]uint8 // first n-1 path segments; last element is the length
+ str string // used if the path does not fit in arr
+}
+
+func newPathKey(p protoreflect.SourcePath) (k pathKey) {
+ if len(p) < len(k.arr) {
+ for i, ps := range p {
+ if ps < 0 || math.MaxUint8 <= ps {
+ return pathKey{str: p.String()}
+ }
+ k.arr[i] = uint8(ps)
+ }
+ k.arr[len(k.arr)-1] = uint8(len(p))
+ return k
+ }
+ return pathKey{str: p.String()}
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/sourceinfo/registry.go b/vendor/github.com/jhump/protoreflect/desc/sourceinfo/registry.go
new file mode 100644
index 0000000..8301c40
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/sourceinfo/registry.go
@@ -0,0 +1,340 @@
+// Package sourceinfo provides the ability to register and query source code info
+// for file descriptors that are compiled into the binary. This data is registered
+// by code generated from the protoc-gen-gosrcinfo plugin.
+//
+// The standard descriptors bundled into the compiled binary are stripped of source
+// code info, to reduce binary size and reduce runtime memory footprint. However,
+// the source code info can be very handy and worth the size cost when used with
+// gRPC services and the server reflection service. Without source code info, the
+// descriptors that a client downloads from the reflection service have no comments.
+// But the presence of comments, and the ability to show them to humans, can greatly
+// improve the utility of user agents that use the reflection service.
+//
+// When the protoc-gen-gosrcinfo plugin is used, the desc.Load* methods, which load
+// descriptors for compiled-in elements, will automatically include source code
+// info, using the data registered with this package.
+//
+// In order to make the reflection service use this functionality, you will need to
+// be using v1.45 or higher of the Go runtime for gRPC (google.golang.org/grpc). The
+// following snippet demonstrates how to do this in your server. Do this instead of
+// using the reflection.Register function:
+//
+// refSvr := reflection.NewServer(reflection.ServerOptions{
+// Services: grpcServer,
+// DescriptorResolver: sourceinfo.GlobalFiles,
+// ExtensionResolver: sourceinfo.GlobalFiles,
+// })
+// grpc_reflection_v1alpha.RegisterServerReflectionServer(grpcServer, refSvr)
+package sourceinfo
+
+import (
+ "bytes"
+ "compress/gzip"
+ "errors"
+ "fmt"
+ "io"
+ "sync"
+
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protodesc"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+ "google.golang.org/protobuf/types/descriptorpb"
+)
+
+var (
+ // GlobalFiles is a registry of descriptors that include source code info, if the
+ // files they belong to were processed with protoc-gen-gosrcinfo.
+ //
+ // If is mean to serve as a drop-in alternative to protoregistry.GlobalFiles that
+ // can include source code info in the returned descriptors.
+ GlobalFiles Resolver = registry{}
+
+ // GlobalTypes is a registry of descriptors that include source code info, if the
+ // files they belong to were processed with protoc-gen-gosrcinfo.
+ //
+ // If is mean to serve as a drop-in alternative to protoregistry.GlobalTypes that
+ // can include source code info in the returned descriptors.
+ GlobalTypes TypeResolver = registry{}
+
+ mu sync.RWMutex
+ sourceInfoByFile = map[string]*descriptorpb.SourceCodeInfo{}
+ fileDescriptors = map[protoreflect.FileDescriptor]protoreflect.FileDescriptor{}
+ updatedDescriptors filesWithFallback
+)
+
+// Resolver can resolve file names into file descriptors and also provides methods for
+// resolving extensions.
+type Resolver interface {
+ protodesc.Resolver
+ protoregistry.ExtensionTypeResolver
+ RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
+}
+
+// NB: These interfaces are far from ideal. Ideally, Resolver would have
+// * EITHER been named FileResolver and not included the extension methods.
+// * OR also included message methods (i.e. embed protoregistry.MessageTypeResolver).
+// Now (since it's been released) we can't add the message methods to the interface as
+// that's not a backwards-compatible change. So we have to introduce the new interface
+// below, which is now a little confusing since it has some overlap with Resolver.
+
+// TypeResolver can resolve message names and URLs into message descriptors and also
+// provides methods for resolving extensions.
+type TypeResolver interface {
+ protoregistry.MessageTypeResolver
+ protoregistry.ExtensionTypeResolver
+ RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
+}
+
+// RegisterSourceInfo registers the given source code info for the file descriptor
+// with the given path/name.
+//
+// This is automatically used from older generated code if using a previous release of
+// the protoc-gen-gosrcinfo plugin.
+func RegisterSourceInfo(file string, srcInfo *descriptorpb.SourceCodeInfo) {
+ mu.Lock()
+ defer mu.Unlock()
+ sourceInfoByFile[file] = srcInfo
+}
+
+// RegisterEncodedSourceInfo registers the given source code info, which is a serialized
+// and gzipped form of a google.protobuf.SourceCodeInfo message.
+//
+// This is automatically used from generated code if using the protoc-gen-gosrcinfo
+// plugin.
+func RegisterEncodedSourceInfo(file string, data []byte) error {
+ zipReader, err := gzip.NewReader(bytes.NewReader(data))
+ if err != nil {
+ return err
+ }
+ defer func() {
+ _ = zipReader.Close()
+ }()
+ unzipped, err := io.ReadAll(zipReader)
+ if err != nil {
+ return err
+ }
+ var srcInfo descriptorpb.SourceCodeInfo
+ if err := proto.Unmarshal(unzipped, &srcInfo); err != nil {
+ return err
+ }
+ RegisterSourceInfo(file, &srcInfo)
+ return nil
+}
+
+// SourceInfoForFile queries for any registered source code info for the file
+// descriptor with the given path/name. It returns nil if no source code info
+// was registered.
+func SourceInfoForFile(file string) *descriptorpb.SourceCodeInfo {
+ mu.RLock()
+ defer mu.RUnlock()
+ return sourceInfoByFile[file]
+}
+
+func canUpgrade(d protoreflect.Descriptor) bool {
+ if d == nil {
+ return false
+ }
+ fd := d.ParentFile()
+ if fd.SourceLocations().Len() > 0 {
+ // already has source info
+ return false
+ }
+ if genFile, err := protoregistry.GlobalFiles.FindFileByPath(fd.Path()); err != nil || genFile != fd {
+ // given descriptor is not from generated code
+ return false
+ }
+ return true
+}
+
+func getFile(fd protoreflect.FileDescriptor) (protoreflect.FileDescriptor, error) {
+ if !canUpgrade(fd) {
+ return fd, nil
+ }
+
+ mu.RLock()
+ result := fileDescriptors[fd]
+ mu.RUnlock()
+
+ if result != nil {
+ return result, nil
+ }
+
+ mu.Lock()
+ defer mu.Unlock()
+ result, err := getFileLocked(fd)
+ if err != nil {
+ return nil, fmt.Errorf("updating file %q: %w", fd.Path(), err)
+ }
+ return result, nil
+}
+
+func getFileLocked(fd protoreflect.FileDescriptor) (protoreflect.FileDescriptor, error) {
+ result := fileDescriptors[fd]
+ if result != nil {
+ return result, nil
+ }
+
+ // We have to build its dependencies, too, so that the descriptor's
+ // references *all* have source code info.
+ var deps []protoreflect.FileDescriptor
+ imps := fd.Imports()
+ for i, length := 0, imps.Len(); i < length; i++ {
+ origDep := imps.Get(i).FileDescriptor
+ updatedDep, err := getFileLocked(origDep)
+ if err != nil {
+ return nil, fmt.Errorf("updating import %q: %w", origDep.Path(), err)
+ }
+ if updatedDep != origDep && deps == nil {
+ // lazily init slice of deps and copy over deps before this one
+ deps = make([]protoreflect.FileDescriptor, i, length)
+ for j := 0; j < i; j++ {
+ deps[j] = imps.Get(i).FileDescriptor
+ }
+ }
+ if deps != nil {
+ deps = append(deps, updatedDep)
+ }
+ }
+
+ srcInfo := sourceInfoByFile[fd.Path()]
+ if len(srcInfo.GetLocation()) == 0 && len(deps) == 0 {
+ // nothing to do; don't bother changing
+ return fd, nil
+ }
+
+ // Add source code info and rebuild.
+ fdProto := protodesc.ToFileDescriptorProto(fd)
+ fdProto.SourceCodeInfo = srcInfo
+
+ result, err := protodesc.NewFile(fdProto, &updatedDescriptors)
+ if err != nil {
+ return nil, err
+ }
+ if err := updatedDescriptors.RegisterFile(result); err != nil {
+ return nil, fmt.Errorf("registering import %q: %w", result.Path(), err)
+ }
+
+ fileDescriptors[fd] = result
+ return result, nil
+}
+
+type registry struct{}
+
+var _ protodesc.Resolver = ®istry{}
+
+func (r registry) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
+ fd, err := protoregistry.GlobalFiles.FindFileByPath(path)
+ if err != nil {
+ return nil, err
+ }
+ return getFile(fd)
+}
+
+func (r registry) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
+ d, err := protoregistry.GlobalFiles.FindDescriptorByName(name)
+ if err != nil {
+ return nil, err
+ }
+ if !canUpgrade(d) {
+ return d, nil
+ }
+ switch d := d.(type) {
+ case protoreflect.FileDescriptor:
+ return getFile(d)
+ case protoreflect.MessageDescriptor:
+ return updateDescriptor(d)
+ case protoreflect.FieldDescriptor:
+ return updateField(d)
+ case protoreflect.OneofDescriptor:
+ return updateDescriptor(d)
+ case protoreflect.EnumDescriptor:
+ return updateDescriptor(d)
+ case protoreflect.EnumValueDescriptor:
+ return updateDescriptor(d)
+ case protoreflect.ServiceDescriptor:
+ return updateDescriptor(d)
+ case protoreflect.MethodDescriptor:
+ return updateDescriptor(d)
+ default:
+ return nil, fmt.Errorf("unrecognized descriptor type: %T", d)
+ }
+}
+
+func (r registry) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
+ mt, err := protoregistry.GlobalTypes.FindMessageByName(message)
+ if err != nil {
+ return nil, err
+ }
+ msg, err := updateDescriptor(mt.Descriptor())
+ if err != nil {
+ return mt, nil
+ }
+ return messageType{MessageType: mt, msgDesc: msg}, nil
+}
+
+func (r registry) FindMessageByURL(url string) (protoreflect.MessageType, error) {
+ mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
+ if err != nil {
+ return nil, err
+ }
+ msg, err := updateDescriptor(mt.Descriptor())
+ if err != nil {
+ return mt, nil
+ }
+ return messageType{MessageType: mt, msgDesc: msg}, nil
+}
+
+func (r registry) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
+ xt, err := protoregistry.GlobalTypes.FindExtensionByName(field)
+ if err != nil {
+ return nil, err
+ }
+ ext, err := updateDescriptor(xt.TypeDescriptor().Descriptor())
+ if err != nil {
+ return xt, nil
+ }
+ return extensionType{ExtensionType: xt, extDesc: ext}, nil
+}
+
+func (r registry) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
+ xt, err := protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
+ if err != nil {
+ return nil, err
+ }
+ ext, err := updateDescriptor(xt.TypeDescriptor().Descriptor())
+ if err != nil {
+ return xt, nil
+ }
+ return extensionType{ExtensionType: xt, extDesc: ext}, nil
+}
+
+func (r registry) RangeExtensionsByMessage(message protoreflect.FullName, fn func(protoreflect.ExtensionType) bool) {
+ protoregistry.GlobalTypes.RangeExtensionsByMessage(message, func(xt protoreflect.ExtensionType) bool {
+ ext, err := updateDescriptor(xt.TypeDescriptor().Descriptor())
+ if err != nil {
+ return fn(xt)
+ }
+ return fn(extensionType{ExtensionType: xt, extDesc: ext})
+ })
+}
+
+type filesWithFallback struct {
+ protoregistry.Files
+}
+
+func (f *filesWithFallback) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
+ fd, err := f.Files.FindFileByPath(path)
+ if errors.Is(err, protoregistry.NotFound) {
+ fd, err = protoregistry.GlobalFiles.FindFileByPath(path)
+ }
+ return fd, err
+}
+
+func (f *filesWithFallback) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
+ fd, err := f.Files.FindDescriptorByName(name)
+ if errors.Is(err, protoregistry.NotFound) {
+ fd, err = protoregistry.GlobalFiles.FindDescriptorByName(name)
+ }
+ return fd, err
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/sourceinfo/update.go b/vendor/github.com/jhump/protoreflect/desc/sourceinfo/update.go
new file mode 100644
index 0000000..53bc457
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/sourceinfo/update.go
@@ -0,0 +1,314 @@
+package sourceinfo
+
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+// AddSourceInfoToFile will return a new file descriptor that is a copy
+// of fd except that it includes source code info. If the given file
+// already contains source info, was not registered from generated code,
+// or was not processed with the protoc-gen-gosrcinfo plugin, then fd
+// is returned as is, unchanged.
+func AddSourceInfoToFile(fd protoreflect.FileDescriptor) (protoreflect.FileDescriptor, error) {
+ return getFile(fd)
+}
+
+// AddSourceInfoToMessage will return a new message descriptor that is a
+// copy of md except that it includes source code info. If the file that
+// contains the given message descriptor already contains source info,
+// was not registered from generated code, or was not processed with the
+// protoc-gen-gosrcinfo plugin, then md is returned as is, unchanged.
+func AddSourceInfoToMessage(md protoreflect.MessageDescriptor) (protoreflect.MessageDescriptor, error) {
+ return updateDescriptor(md)
+}
+
+// AddSourceInfoToEnum will return a new enum descriptor that is a copy
+// of ed except that it includes source code info. If the file that
+// contains the given enum descriptor already contains source info, was
+// not registered from generated code, or was not processed with the
+// protoc-gen-gosrcinfo plugin, then ed is returned as is, unchanged.
+func AddSourceInfoToEnum(ed protoreflect.EnumDescriptor) (protoreflect.EnumDescriptor, error) {
+ return updateDescriptor(ed)
+}
+
+// AddSourceInfoToService will return a new service descriptor that is
+// a copy of sd except that it includes source code info. If the file
+// that contains the given service descriptor already contains source
+// info, was not registered from generated code, or was not processed
+// with the protoc-gen-gosrcinfo plugin, then ed is returned as is,
+// unchanged.
+func AddSourceInfoToService(sd protoreflect.ServiceDescriptor) (protoreflect.ServiceDescriptor, error) {
+ return updateDescriptor(sd)
+}
+
+// AddSourceInfoToExtensionType will return a new extension type that
+// is a copy of xt except that its associated descriptors includes
+// source code info. If the file that contains the given extension
+// already contains source info, was not registered from generated
+// code, or was not processed with the protoc-gen-gosrcinfo plugin,
+// then xt is returned as is, unchanged.
+func AddSourceInfoToExtensionType(xt protoreflect.ExtensionType) (protoreflect.ExtensionType, error) {
+ if genType, err := protoregistry.GlobalTypes.FindExtensionByName(xt.TypeDescriptor().FullName()); err != nil || genType != xt {
+ return xt, nil // not from generated code
+ }
+ ext, err := updateField(xt.TypeDescriptor().Descriptor())
+ if err != nil {
+ return nil, err
+ }
+ return extensionType{ExtensionType: xt, extDesc: ext}, nil
+}
+
+// AddSourceInfoToMessageType will return a new message type that
+// is a copy of mt except that its associated descriptors includes
+// source code info. If the file that contains the given message
+// already contains source info, was not registered from generated
+// code, or was not processed with the protoc-gen-gosrcinfo plugin,
+// then mt is returned as is, unchanged.
+func AddSourceInfoToMessageType(mt protoreflect.MessageType) (protoreflect.MessageType, error) {
+ if genType, err := protoregistry.GlobalTypes.FindMessageByName(mt.Descriptor().FullName()); err != nil || genType != mt {
+ return mt, nil // not from generated code
+ }
+ msg, err := updateDescriptor(mt.Descriptor())
+ if err != nil {
+ return nil, err
+ }
+ return messageType{MessageType: mt, msgDesc: msg}, nil
+}
+
+// WrapFile is present for backwards-compatibility reasons. It calls
+// AddSourceInfoToFile and panics if that function returns an error.
+//
+// Deprecated: Use AddSourceInfoToFile directly instead. The word "wrap" is
+// a misnomer since this method does not actually wrap the given value.
+// Though unlikely, the operation can technically fail, so the recommended
+// function allows the return of an error instead of panic'ing.
+func WrapFile(fd protoreflect.FileDescriptor) protoreflect.FileDescriptor {
+ result, err := AddSourceInfoToFile(fd)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+// WrapMessage is present for backwards-compatibility reasons. It calls
+// AddSourceInfoToMessage and panics if that function returns an error.
+//
+// Deprecated: Use AddSourceInfoToMessage directly instead. The word
+// "wrap" is a misnomer since this method does not actually wrap the
+// given value. Though unlikely, the operation can technically fail,
+// so the recommended function allows the return of an error instead
+// of panic'ing.
+func WrapMessage(md protoreflect.MessageDescriptor) protoreflect.MessageDescriptor {
+ result, err := AddSourceInfoToMessage(md)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+// WrapEnum is present for backwards-compatibility reasons. It calls
+// AddSourceInfoToEnum and panics if that function returns an error.
+//
+// Deprecated: Use AddSourceInfoToEnum directly instead. The word
+// "wrap" is a misnomer since this method does not actually wrap the
+// given value. Though unlikely, the operation can technically fail,
+// so the recommended function allows the return of an error instead
+// of panic'ing.
+func WrapEnum(ed protoreflect.EnumDescriptor) protoreflect.EnumDescriptor {
+ result, err := AddSourceInfoToEnum(ed)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+// WrapService is present for backwards-compatibility reasons. It calls
+// AddSourceInfoToService and panics if that function returns an error.
+//
+// Deprecated: Use AddSourceInfoToService directly instead. The word
+// "wrap" is a misnomer since this method does not actually wrap the
+// given value. Though unlikely, the operation can technically fail,
+// so the recommended function allows the return of an error instead
+// of panic'ing.
+func WrapService(sd protoreflect.ServiceDescriptor) protoreflect.ServiceDescriptor {
+ result, err := AddSourceInfoToService(sd)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+// WrapExtensionType is present for backwards-compatibility reasons. It
+// calls AddSourceInfoToExtensionType and panics if that function
+// returns an error.
+//
+// Deprecated: Use AddSourceInfoToExtensionType directly instead. The
+// word "wrap" is a misnomer since this method does not actually wrap
+// the given value. Though unlikely, the operation can technically fail,
+// so the recommended function allows the return of an error instead
+// of panic'ing.
+func WrapExtensionType(xt protoreflect.ExtensionType) protoreflect.ExtensionType {
+ result, err := AddSourceInfoToExtensionType(xt)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+// WrapMessageType is present for backwards-compatibility reasons. It
+// calls AddSourceInfoToMessageType and panics if that function returns
+// an error.
+//
+// Deprecated: Use AddSourceInfoToMessageType directly instead. The word
+// "wrap" is a misnomer since this method does not actually wrap the
+// given value. Though unlikely, the operation can technically fail, so
+// the recommended function allows the return of an error instead of
+// panic'ing.
+func WrapMessageType(mt protoreflect.MessageType) protoreflect.MessageType {
+ result, err := AddSourceInfoToMessageType(mt)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+type extensionType struct {
+ protoreflect.ExtensionType
+ extDesc protoreflect.ExtensionDescriptor
+}
+
+func (xt extensionType) TypeDescriptor() protoreflect.ExtensionTypeDescriptor {
+ return extensionTypeDescriptor{ExtensionDescriptor: xt.extDesc, extType: xt.ExtensionType}
+}
+
+type extensionTypeDescriptor struct {
+ protoreflect.ExtensionDescriptor
+ extType protoreflect.ExtensionType
+}
+
+func (xtd extensionTypeDescriptor) Type() protoreflect.ExtensionType {
+ return extensionType{ExtensionType: xtd.extType, extDesc: xtd.ExtensionDescriptor}
+}
+
+func (xtd extensionTypeDescriptor) Descriptor() protoreflect.ExtensionDescriptor {
+ return xtd.ExtensionDescriptor
+}
+
+type messageType struct {
+ protoreflect.MessageType
+ msgDesc protoreflect.MessageDescriptor
+}
+
+func (mt messageType) Descriptor() protoreflect.MessageDescriptor {
+ return mt.msgDesc
+}
+
+func updateField(fd protoreflect.FieldDescriptor) (protoreflect.FieldDescriptor, error) {
+ if xtd, ok := fd.(protoreflect.ExtensionTypeDescriptor); ok {
+ ext, err := updateField(xtd.Descriptor())
+ if err != nil {
+ return nil, err
+ }
+ return extensionTypeDescriptor{ExtensionDescriptor: ext, extType: xtd.Type()}, nil
+ }
+ d, err := updateDescriptor(fd)
+ if err != nil {
+ return nil, err
+ }
+ return d.(protoreflect.FieldDescriptor), nil
+}
+
+func updateDescriptor[D protoreflect.Descriptor](d D) (D, error) {
+ updatedFile, err := getFile(d.ParentFile())
+ if err != nil {
+ var zero D
+ return zero, err
+ }
+ if updatedFile == d.ParentFile() {
+ // no change
+ return d, nil
+ }
+ updated := findDescriptor(updatedFile, d)
+ result, ok := updated.(D)
+ if !ok {
+ var zero D
+ return zero, fmt.Errorf("updated result is type %T which could not be converted to %T", updated, result)
+ }
+ return result, nil
+}
+
+func findDescriptor(fd protoreflect.FileDescriptor, d protoreflect.Descriptor) protoreflect.Descriptor {
+ if d == nil {
+ return nil
+ }
+ if _, isFile := d.(protoreflect.FileDescriptor); isFile {
+ return fd
+ }
+ if d.Parent() == nil {
+ return d
+ }
+ switch d := d.(type) {
+ case protoreflect.MessageDescriptor:
+ parent := findDescriptor(fd, d.Parent()).(messageContainer)
+ return parent.Messages().Get(d.Index())
+ case protoreflect.FieldDescriptor:
+ if d.IsExtension() {
+ parent := findDescriptor(fd, d.Parent()).(extensionContainer)
+ return parent.Extensions().Get(d.Index())
+ } else {
+ parent := findDescriptor(fd, d.Parent()).(fieldContainer)
+ return parent.Fields().Get(d.Index())
+ }
+ case protoreflect.OneofDescriptor:
+ parent := findDescriptor(fd, d.Parent()).(oneofContainer)
+ return parent.Oneofs().Get(d.Index())
+ case protoreflect.EnumDescriptor:
+ parent := findDescriptor(fd, d.Parent()).(enumContainer)
+ return parent.Enums().Get(d.Index())
+ case protoreflect.EnumValueDescriptor:
+ parent := findDescriptor(fd, d.Parent()).(enumValueContainer)
+ return parent.Values().Get(d.Index())
+ case protoreflect.ServiceDescriptor:
+ parent := findDescriptor(fd, d.Parent()).(serviceContainer)
+ return parent.Services().Get(d.Index())
+ case protoreflect.MethodDescriptor:
+ parent := findDescriptor(fd, d.Parent()).(methodContainer)
+ return parent.Methods().Get(d.Index())
+ }
+ return d
+}
+
+type messageContainer interface {
+ Messages() protoreflect.MessageDescriptors
+}
+
+type extensionContainer interface {
+ Extensions() protoreflect.ExtensionDescriptors
+}
+
+type fieldContainer interface {
+ Fields() protoreflect.FieldDescriptors
+}
+
+type oneofContainer interface {
+ Oneofs() protoreflect.OneofDescriptors
+}
+
+type enumContainer interface {
+ Enums() protoreflect.EnumDescriptors
+}
+
+type enumValueContainer interface {
+ Values() protoreflect.EnumValueDescriptors
+}
+
+type serviceContainer interface {
+ Services() protoreflect.ServiceDescriptors
+}
+
+type methodContainer interface {
+ Methods() protoreflect.MethodDescriptors
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/wrap.go b/vendor/github.com/jhump/protoreflect/desc/wrap.go
new file mode 100644
index 0000000..5491afd
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/wrap.go
@@ -0,0 +1,211 @@
+package desc
+
+import (
+ "fmt"
+
+ "github.com/bufbuild/protocompile/protoutil"
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+// DescriptorWrapper wraps a protoreflect.Descriptor. All of the Descriptor
+// implementations in this package implement this interface. This can be
+// used to recover the underlying descriptor. Each descriptor type in this
+// package also provides a strongly-typed form of this method, such as the
+// following method for *FileDescriptor:
+//
+// UnwrapFile() protoreflect.FileDescriptor
+type DescriptorWrapper interface {
+ Unwrap() protoreflect.Descriptor
+}
+
+// WrapDescriptor wraps the given descriptor, returning a desc.Descriptor
+// value that represents the same element.
+func WrapDescriptor(d protoreflect.Descriptor) (Descriptor, error) {
+ return wrapDescriptor(d, mapCache{})
+}
+
+func wrapDescriptor(d protoreflect.Descriptor, cache descriptorCache) (Descriptor, error) {
+ switch d := d.(type) {
+ case protoreflect.FileDescriptor:
+ return wrapFile(d, cache)
+ case protoreflect.MessageDescriptor:
+ return wrapMessage(d, cache)
+ case protoreflect.FieldDescriptor:
+ return wrapField(d, cache)
+ case protoreflect.OneofDescriptor:
+ return wrapOneOf(d, cache)
+ case protoreflect.EnumDescriptor:
+ return wrapEnum(d, cache)
+ case protoreflect.EnumValueDescriptor:
+ return wrapEnumValue(d, cache)
+ case protoreflect.ServiceDescriptor:
+ return wrapService(d, cache)
+ case protoreflect.MethodDescriptor:
+ return wrapMethod(d, cache)
+ default:
+ return nil, fmt.Errorf("unknown descriptor type: %T", d)
+ }
+}
+
+// WrapFiles wraps the given file descriptors, returning a slice of *desc.FileDescriptor
+// values that represent the same files.
+func WrapFiles(d []protoreflect.FileDescriptor) ([]*FileDescriptor, error) {
+ cache := mapCache{}
+ results := make([]*FileDescriptor, len(d))
+ for i := range d {
+ var err error
+ results[i], err = wrapFile(d[i], cache)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return results, nil
+}
+
+// WrapFile wraps the given file descriptor, returning a *desc.FileDescriptor
+// value that represents the same file.
+func WrapFile(d protoreflect.FileDescriptor) (*FileDescriptor, error) {
+ return wrapFile(d, mapCache{})
+}
+
+func wrapFile(d protoreflect.FileDescriptor, cache descriptorCache) (*FileDescriptor, error) {
+ if res := cache.get(d); res != nil {
+ return res.(*FileDescriptor), nil
+ }
+ fdp := protoutil.ProtoFromFileDescriptor(d)
+ return convertFile(d, fdp, cache)
+}
+
+// WrapMessage wraps the given message descriptor, returning a *desc.MessageDescriptor
+// value that represents the same message.
+func WrapMessage(d protoreflect.MessageDescriptor) (*MessageDescriptor, error) {
+ return wrapMessage(d, mapCache{})
+}
+
+func wrapMessage(d protoreflect.MessageDescriptor, cache descriptorCache) (*MessageDescriptor, error) {
+ parent, err := wrapDescriptor(d.Parent(), cache)
+ if err != nil {
+ return nil, err
+ }
+ switch p := parent.(type) {
+ case *FileDescriptor:
+ return p.messages[d.Index()], nil
+ case *MessageDescriptor:
+ return p.nested[d.Index()], nil
+ default:
+ return nil, fmt.Errorf("message has unexpected parent type: %T", parent)
+ }
+}
+
+// WrapField wraps the given field descriptor, returning a *desc.FieldDescriptor
+// value that represents the same field.
+func WrapField(d protoreflect.FieldDescriptor) (*FieldDescriptor, error) {
+ return wrapField(d, mapCache{})
+}
+
+func wrapField(d protoreflect.FieldDescriptor, cache descriptorCache) (*FieldDescriptor, error) {
+ parent, err := wrapDescriptor(d.Parent(), cache)
+ if err != nil {
+ return nil, err
+ }
+ switch p := parent.(type) {
+ case *FileDescriptor:
+ return p.extensions[d.Index()], nil
+ case *MessageDescriptor:
+ if d.IsExtension() {
+ return p.extensions[d.Index()], nil
+ }
+ return p.fields[d.Index()], nil
+ default:
+ return nil, fmt.Errorf("field has unexpected parent type: %T", parent)
+ }
+}
+
+// WrapOneOf wraps the given oneof descriptor, returning a *desc.OneOfDescriptor
+// value that represents the same oneof.
+func WrapOneOf(d protoreflect.OneofDescriptor) (*OneOfDescriptor, error) {
+ return wrapOneOf(d, mapCache{})
+}
+
+func wrapOneOf(d protoreflect.OneofDescriptor, cache descriptorCache) (*OneOfDescriptor, error) {
+ parent, err := wrapDescriptor(d.Parent(), cache)
+ if err != nil {
+ return nil, err
+ }
+ if p, ok := parent.(*MessageDescriptor); ok {
+ return p.oneOfs[d.Index()], nil
+ }
+ return nil, fmt.Errorf("oneof has unexpected parent type: %T", parent)
+}
+
+// WrapEnum wraps the given enum descriptor, returning a *desc.EnumDescriptor
+// value that represents the same enum.
+func WrapEnum(d protoreflect.EnumDescriptor) (*EnumDescriptor, error) {
+ return wrapEnum(d, mapCache{})
+}
+
+func wrapEnum(d protoreflect.EnumDescriptor, cache descriptorCache) (*EnumDescriptor, error) {
+ parent, err := wrapDescriptor(d.Parent(), cache)
+ if err != nil {
+ return nil, err
+ }
+ switch p := parent.(type) {
+ case *FileDescriptor:
+ return p.enums[d.Index()], nil
+ case *MessageDescriptor:
+ return p.enums[d.Index()], nil
+ default:
+ return nil, fmt.Errorf("enum has unexpected parent type: %T", parent)
+ }
+}
+
+// WrapEnumValue wraps the given enum value descriptor, returning a *desc.EnumValueDescriptor
+// value that represents the same enum value.
+func WrapEnumValue(d protoreflect.EnumValueDescriptor) (*EnumValueDescriptor, error) {
+ return wrapEnumValue(d, mapCache{})
+}
+
+func wrapEnumValue(d protoreflect.EnumValueDescriptor, cache descriptorCache) (*EnumValueDescriptor, error) {
+ parent, err := wrapDescriptor(d.Parent(), cache)
+ if err != nil {
+ return nil, err
+ }
+ if p, ok := parent.(*EnumDescriptor); ok {
+ return p.values[d.Index()], nil
+ }
+ return nil, fmt.Errorf("enum value has unexpected parent type: %T", parent)
+}
+
+// WrapService wraps the given service descriptor, returning a *desc.ServiceDescriptor
+// value that represents the same service.
+func WrapService(d protoreflect.ServiceDescriptor) (*ServiceDescriptor, error) {
+ return wrapService(d, mapCache{})
+}
+
+func wrapService(d protoreflect.ServiceDescriptor, cache descriptorCache) (*ServiceDescriptor, error) {
+ parent, err := wrapDescriptor(d.Parent(), cache)
+ if err != nil {
+ return nil, err
+ }
+ if p, ok := parent.(*FileDescriptor); ok {
+ return p.services[d.Index()], nil
+ }
+ return nil, fmt.Errorf("service has unexpected parent type: %T", parent)
+}
+
+// WrapMethod wraps the given method descriptor, returning a *desc.MethodDescriptor
+// value that represents the same method.
+func WrapMethod(d protoreflect.MethodDescriptor) (*MethodDescriptor, error) {
+ return wrapMethod(d, mapCache{})
+}
+
+func wrapMethod(d protoreflect.MethodDescriptor, cache descriptorCache) (*MethodDescriptor, error) {
+ parent, err := wrapDescriptor(d.Parent(), cache)
+ if err != nil {
+ return nil, err
+ }
+ if p, ok := parent.(*ServiceDescriptor); ok {
+ return p.methods[d.Index()], nil
+ }
+ return nil, fmt.Errorf("method has unexpected parent type: %T", parent)
+}