[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/LICENSE b/vendor/github.com/jhump/protoreflect/LICENSE
index d645695..b53b91d 100644
--- a/vendor/github.com/jhump/protoreflect/LICENSE
+++ b/vendor/github.com/jhump/protoreflect/LICENSE
@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright [yyyy] [name of copyright owner]
+ Copyright 2017 Joshua Humphries
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/vendor/github.com/jhump/protoreflect/codec/codec.go b/vendor/github.com/jhump/protoreflect/codec/codec.go
index b6f4ed0..7e5c568 100644
--- a/vendor/github.com/jhump/protoreflect/codec/codec.go
+++ b/vendor/github.com/jhump/protoreflect/codec/codec.go
@@ -4,6 +4,7 @@
"io"
"github.com/golang/protobuf/proto"
+
"github.com/jhump/protoreflect/internal/codec"
)
diff --git a/vendor/github.com/jhump/protoreflect/codec/decode_fields.go b/vendor/github.com/jhump/protoreflect/codec/decode_fields.go
index 02f8a32..0edb817 100644
--- a/vendor/github.com/jhump/protoreflect/codec/decode_fields.go
+++ b/vendor/github.com/jhump/protoreflect/codec/decode_fields.go
@@ -7,32 +7,32 @@
"math"
"github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/types/descriptorpb"
"github.com/jhump/protoreflect/desc"
)
-var varintTypes = map[descriptor.FieldDescriptorProto_Type]bool{}
-var fixed32Types = map[descriptor.FieldDescriptorProto_Type]bool{}
-var fixed64Types = map[descriptor.FieldDescriptorProto_Type]bool{}
+var varintTypes = map[descriptorpb.FieldDescriptorProto_Type]bool{}
+var fixed32Types = map[descriptorpb.FieldDescriptorProto_Type]bool{}
+var fixed64Types = map[descriptorpb.FieldDescriptorProto_Type]bool{}
func init() {
- varintTypes[descriptor.FieldDescriptorProto_TYPE_BOOL] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_INT32] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_INT64] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT32] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT64] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT32] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT64] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_ENUM] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_BOOL] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_INT32] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_INT64] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_UINT32] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_UINT64] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_SINT32] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_SINT64] = true
+ varintTypes[descriptorpb.FieldDescriptorProto_TYPE_ENUM] = true
- fixed32Types[descriptor.FieldDescriptorProto_TYPE_FIXED32] = true
- fixed32Types[descriptor.FieldDescriptorProto_TYPE_SFIXED32] = true
- fixed32Types[descriptor.FieldDescriptorProto_TYPE_FLOAT] = true
+ fixed32Types[descriptorpb.FieldDescriptorProto_TYPE_FIXED32] = true
+ fixed32Types[descriptorpb.FieldDescriptorProto_TYPE_SFIXED32] = true
+ fixed32Types[descriptorpb.FieldDescriptorProto_TYPE_FLOAT] = true
- fixed64Types[descriptor.FieldDescriptorProto_TYPE_FIXED64] = true
- fixed64Types[descriptor.FieldDescriptorProto_TYPE_SFIXED64] = true
- fixed64Types[descriptor.FieldDescriptorProto_TYPE_DOUBLE] = true
+ fixed64Types[descriptorpb.FieldDescriptorProto_TYPE_FIXED64] = true
+ fixed64Types[descriptorpb.FieldDescriptorProto_TYPE_SFIXED64] = true
+ fixed64Types[descriptorpb.FieldDescriptorProto_TYPE_DOUBLE] = true
}
// ErrWireTypeEndGroup is returned from DecodeFieldValue if the tag and wire-type
@@ -117,53 +117,53 @@
// messages, bytes, and strings), an error is returned.
func DecodeScalarField(fd *desc.FieldDescriptor, v uint64) (interface{}, error) {
switch fd.GetType() {
- case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
return v != 0, nil
- case descriptor.FieldDescriptorProto_TYPE_UINT32,
- descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED32:
if v > math.MaxUint32 {
return nil, ErrOverflow
}
return uint32(v), nil
- case descriptor.FieldDescriptorProto_TYPE_INT32,
- descriptor.FieldDescriptorProto_TYPE_ENUM:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT32,
+ descriptorpb.FieldDescriptorProto_TYPE_ENUM:
s := int64(v)
if s > math.MaxInt32 || s < math.MinInt32 {
return nil, ErrOverflow
}
return int32(s), nil
- case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_SFIXED32:
if v > math.MaxUint32 {
return nil, ErrOverflow
}
return int32(v), nil
- case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ case descriptorpb.FieldDescriptorProto_TYPE_SINT32:
if v > math.MaxUint32 {
return nil, ErrOverflow
}
return DecodeZigZag32(v), nil
- case descriptor.FieldDescriptorProto_TYPE_UINT64,
- descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED64:
return v, nil
- case descriptor.FieldDescriptorProto_TYPE_INT64,
- descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED64:
return int64(v), nil
- case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_SINT64:
return DecodeZigZag64(v), nil
- case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
if v > math.MaxUint32 {
return nil, ErrOverflow
}
return math.Float32frombits(uint32(v)), nil
- case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
return math.Float64frombits(v), nil
default:
@@ -184,14 +184,14 @@
// contains multiple values, only the last value is returned.
func DecodeLengthDelimitedField(fd *desc.FieldDescriptor, bytes []byte, mf MessageFactory) (interface{}, error) {
switch {
- case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_BYTES:
+ case fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_BYTES:
return bytes, nil
- case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_STRING:
+ case fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_STRING:
return string(bytes), nil
- case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE ||
- fd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP:
+ case fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE ||
+ fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP:
msg := mf.NewMessage(fd.GetMessageType())
err := proto.Unmarshal(bytes, msg)
if err != nil {
@@ -263,7 +263,7 @@
}
case proto.WireBytes:
- alloc := fd.GetType() == descriptor.FieldDescriptorProto_TYPE_BYTES
+ alloc := fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_BYTES
var raw []byte
raw, err = b.DecodeRawBytes(alloc)
if err == nil {
diff --git a/vendor/github.com/jhump/protoreflect/codec/encode_fields.go b/vendor/github.com/jhump/protoreflect/codec/encode_fields.go
index 499aa95..280f730 100644
--- a/vendor/github.com/jhump/protoreflect/codec/encode_fields.go
+++ b/vendor/github.com/jhump/protoreflect/codec/encode_fields.go
@@ -7,7 +7,7 @@
"sort"
"github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/types/descriptorpb"
"github.com/jhump/protoreflect/desc"
)
@@ -175,74 +175,74 @@
func (b *Buffer) encodeFieldValue(fd *desc.FieldDescriptor, val interface{}) error {
switch fd.GetType() {
- case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
v := val.(bool)
if v {
return b.EncodeVarint(1)
}
return b.EncodeVarint(0)
- case descriptor.FieldDescriptorProto_TYPE_ENUM,
- descriptor.FieldDescriptorProto_TYPE_INT32:
+ case descriptorpb.FieldDescriptorProto_TYPE_ENUM,
+ descriptorpb.FieldDescriptorProto_TYPE_INT32:
v := val.(int32)
return b.EncodeVarint(uint64(v))
- case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_SFIXED32:
v := val.(int32)
return b.EncodeFixed32(uint64(v))
- case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ case descriptorpb.FieldDescriptorProto_TYPE_SINT32:
v := val.(int32)
return b.EncodeVarint(EncodeZigZag32(v))
- case descriptor.FieldDescriptorProto_TYPE_UINT32:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT32:
v := val.(uint32)
return b.EncodeVarint(uint64(v))
- case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED32:
v := val.(uint32)
return b.EncodeFixed32(uint64(v))
- case descriptor.FieldDescriptorProto_TYPE_INT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT64:
v := val.(int64)
return b.EncodeVarint(uint64(v))
- case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_SFIXED64:
v := val.(int64)
return b.EncodeFixed64(uint64(v))
- case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_SINT64:
v := val.(int64)
return b.EncodeVarint(EncodeZigZag64(v))
- case descriptor.FieldDescriptorProto_TYPE_UINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT64:
v := val.(uint64)
return b.EncodeVarint(v)
- case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED64:
v := val.(uint64)
return b.EncodeFixed64(v)
- case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
v := val.(float64)
return b.EncodeFixed64(math.Float64bits(v))
- case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
v := val.(float32)
return b.EncodeFixed32(uint64(math.Float32bits(v)))
- case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
v := val.([]byte)
return b.EncodeRawBytes(v)
- case descriptor.FieldDescriptorProto_TYPE_STRING:
+ case descriptorpb.FieldDescriptorProto_TYPE_STRING:
v := val.(string)
return b.EncodeRawBytes(([]byte)(v))
- case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE:
return b.EncodeDelimitedMessage(val.(proto.Message))
- case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ case descriptorpb.FieldDescriptorProto_TYPE_GROUP:
// just append the nested message to this buffer
return b.EncodeMessage(val.(proto.Message))
// whosoever writeth start-group tag (e.g. caller) is responsible for writing end-group tag
@@ -252,34 +252,34 @@
}
}
-func getWireType(t descriptor.FieldDescriptorProto_Type) (int8, error) {
+func getWireType(t descriptorpb.FieldDescriptorProto_Type) (int8, error) {
switch t {
- case descriptor.FieldDescriptorProto_TYPE_ENUM,
- descriptor.FieldDescriptorProto_TYPE_BOOL,
- descriptor.FieldDescriptorProto_TYPE_INT32,
- descriptor.FieldDescriptorProto_TYPE_SINT32,
- descriptor.FieldDescriptorProto_TYPE_UINT32,
- descriptor.FieldDescriptorProto_TYPE_INT64,
- descriptor.FieldDescriptorProto_TYPE_SINT64,
- descriptor.FieldDescriptorProto_TYPE_UINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_ENUM,
+ descriptorpb.FieldDescriptorProto_TYPE_BOOL,
+ descriptorpb.FieldDescriptorProto_TYPE_INT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_UINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_INT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_UINT64:
return proto.WireVarint, nil
- case descriptor.FieldDescriptorProto_TYPE_FIXED32,
- descriptor.FieldDescriptorProto_TYPE_SFIXED32,
- descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED32,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED32,
+ descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
return proto.WireFixed32, nil
- case descriptor.FieldDescriptorProto_TYPE_FIXED64,
- descriptor.FieldDescriptorProto_TYPE_SFIXED64,
- descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED64,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED64,
+ descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
return proto.WireFixed64, nil
- case descriptor.FieldDescriptorProto_TYPE_BYTES,
- descriptor.FieldDescriptorProto_TYPE_STRING,
- descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ case descriptorpb.FieldDescriptorProto_TYPE_BYTES,
+ descriptorpb.FieldDescriptorProto_TYPE_STRING,
+ descriptorpb.FieldDescriptorProto_TYPE_MESSAGE:
return proto.WireBytes, nil
- case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ case descriptorpb.FieldDescriptorProto_TYPE_GROUP:
return proto.WireStartGroup, nil
default:
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)
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/binary.go b/vendor/github.com/jhump/protoreflect/dynamic/binary.go
index 91fd672..39e077a 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/binary.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/binary.go
@@ -4,9 +4,11 @@
import (
"fmt"
- "github.com/golang/protobuf/proto"
- "github.com/jhump/protoreflect/codec"
"io"
+
+ "github.com/golang/protobuf/proto"
+
+ "github.com/jhump/protoreflect/codec"
)
// defaultDeterminism, if true, will mean that calls to Marshal will produce
@@ -71,6 +73,9 @@
}
func (m *Message) marshal(b *codec.Buffer) error {
+ if m.GetMessageDescriptor().GetMessageOptions().GetMessageSetWireFormat() {
+ return fmt.Errorf("%s is a message set; marshaling message sets is not implemented", m.GetMessageDescriptor().GetFullyQualifiedName())
+ }
if err := m.marshalKnownFields(b); err != nil {
return err
}
@@ -150,6 +155,9 @@
}
func (m *Message) unmarshal(buf *codec.Buffer, isGroup bool) error {
+ if m.GetMessageDescriptor().GetMessageOptions().GetMessageSetWireFormat() {
+ return fmt.Errorf("%s is a message set; unmarshaling message sets is not implemented", m.GetMessageDescriptor().GetFullyQualifiedName())
+ }
for !buf.EOF() {
fd, val, err := buf.DecodeFieldValue(m.FindFieldDescriptor, m.mf)
if err != nil {
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/doc.go b/vendor/github.com/jhump/protoreflect/dynamic/doc.go
index c329fcd..59b77eb 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/doc.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/doc.go
@@ -15,8 +15,7 @@
// will be used to create other messages or parse extension fields during
// de-serialization.
//
-//
-// Field Types
+// # Field Types
//
// The types of values expected by setters and returned by getters are the
// same as protoc generates for scalar fields. For repeated fields, there are
@@ -72,8 +71,7 @@
// but if the factory is configured with a KnownTypeRegistry, or if the field's
// type is a well-known type, it will return a zero value generated message.
//
-//
-// Unrecognized Fields
+// # Unrecognized Fields
//
// Unrecognized fields are preserved by the dynamic message when unmarshaling
// from the standard binary format. If the message's MessageFactory was
@@ -89,21 +87,20 @@
// it can even happen for non-extension fields! Here's an example scenario where
// a non-extension field can initially be unknown and become known:
//
-// 1. A dynamic message is created with a descriptor, A, and then
-// de-serialized from a stream of bytes. The stream includes an
-// unrecognized tag T. The message will include tag T in its unrecognized
-// field set.
-// 2. Another call site retrieves a newer descriptor, A', which includes a
-// newly added field with tag T.
-// 3. That other call site then uses a FieldDescriptor to access the value of
-// the new field. This will cause the dynamic message to parse the bytes
-// for the unknown tag T and store them as a known field.
-// 4. Subsequent operations for tag T, including setting the field using only
-// tag number or de-serializing a stream that includes tag T, will operate
-// as if that tag were part of the original descriptor, A.
+// 1. A dynamic message is created with a descriptor, A, and then
+// de-serialized from a stream of bytes. The stream includes an
+// unrecognized tag T. The message will include tag T in its unrecognized
+// field set.
+// 2. Another call site retrieves a newer descriptor, A', which includes a
+// newly added field with tag T.
+// 3. That other call site then uses a FieldDescriptor to access the value of
+// the new field. This will cause the dynamic message to parse the bytes
+// for the unknown tag T and store them as a known field.
+// 4. Subsequent operations for tag T, including setting the field using only
+// tag number or de-serializing a stream that includes tag T, will operate
+// as if that tag were part of the original descriptor, A.
//
-//
-// Compatibility
+// # Compatibility
//
// In addition to implementing the proto.Message interface, the included
// Message type also provides an XXX_MessageName() method, so it can work with
@@ -145,8 +142,7 @@
// about fields that the dynamic message does not, these unrecognized fields may
// become known fields in the generated message.
//
-//
-// Registries
+// # Registries
//
// This package also contains a couple of registries, for managing known types
// and descriptors.
@@ -160,4 +156,12 @@
//
// The ExtensionRegistry allows for recognizing and parsing extensions fields
// (for proto2 messages).
+//
+// 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/dynamic package,
+// see [google.golang.org/protobuf/types/dynamicpb].
+//
+// [google.golang.org/protobuf/types/dynamicpb]: https://pkg.go.dev/google.golang.org/protobuf/types/dynamicpb
package dynamic
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/dynamic_message.go b/vendor/github.com/jhump/protoreflect/dynamic/dynamic_message.go
index de13b92..ff136b0 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/dynamic_message.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/dynamic_message.go
@@ -10,7 +10,9 @@
"strings"
"github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ protov2 "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/types/descriptorpb"
"github.com/jhump/protoreflect/codec"
"github.com/jhump/protoreflect/desc"
@@ -411,19 +413,20 @@
// The Go type of the returned value, for scalar fields, is the same as protoc
// would generate for the field (in a non-dynamic message). The table below
// lists the scalar types and the corresponding Go types.
-// +-------------------------+-----------+
-// | 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 |
+// +-------------------------+-----------+
//
// Values for enum fields will always be int32 values. You can use the enum
// descriptor associated with the field to lookup value names with those values.
@@ -1883,42 +1886,42 @@
}
switch t {
- case descriptor.FieldDescriptorProto_TYPE_SFIXED32,
- descriptor.FieldDescriptorProto_TYPE_INT32,
- descriptor.FieldDescriptorProto_TYPE_SINT32,
- descriptor.FieldDescriptorProto_TYPE_ENUM:
+ case descriptorpb.FieldDescriptorProto_TYPE_SFIXED32,
+ descriptorpb.FieldDescriptorProto_TYPE_INT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_ENUM:
return toInt32(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_SFIXED64,
- descriptor.FieldDescriptorProto_TYPE_INT64,
- descriptor.FieldDescriptorProto_TYPE_SINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_SFIXED64,
+ descriptorpb.FieldDescriptorProto_TYPE_INT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT64:
return toInt64(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_FIXED32,
- descriptor.FieldDescriptorProto_TYPE_UINT32:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED32,
+ descriptorpb.FieldDescriptorProto_TYPE_UINT32:
return toUint32(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_FIXED64,
- descriptor.FieldDescriptorProto_TYPE_UINT64:
+ case descriptorpb.FieldDescriptorProto_TYPE_FIXED64,
+ descriptorpb.FieldDescriptorProto_TYPE_UINT64:
return toUint64(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
return toFloat32(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
return toFloat64(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
return toBool(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
return toBytes(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_STRING:
+ case descriptorpb.FieldDescriptorProto_TYPE_STRING:
return toString(reflect.Indirect(val), fd)
- case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
- descriptor.FieldDescriptorProto_TYPE_GROUP:
+ case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE,
+ descriptorpb.FieldDescriptorProto_TYPE_GROUP:
m, err := asMessage(val, fd.GetFullyQualifiedName())
// check that message is correct type
if err != nil {
@@ -2053,8 +2056,9 @@
// ConvertTo converts this dynamic message into the given message. This is
// shorthand for resetting then merging:
-// target.Reset()
-// m.MergeInto(target)
+//
+// target.Reset()
+// m.MergeInto(target)
func (m *Message) ConvertTo(target proto.Message) error {
if err := m.checkType(target); err != nil {
return err
@@ -2081,8 +2085,9 @@
// ConvertFrom converts the given message into this dynamic message. This is
// shorthand for resetting then merging:
-// m.Reset()
-// m.MergeFrom(target)
+//
+// m.Reset()
+// m.MergeFrom(target)
func (m *Message) ConvertFrom(target proto.Message) error {
if err := m.checkType(target); err != nil {
return err
@@ -2553,6 +2558,66 @@
}
}
+ // With API v2, it is possible that the new protoreflect interfaces
+ // were used to store an extension, which means it can't be returned
+ // by proto.ExtensionDescs and it's also not in the unrecognized data.
+ // So we have a separate loop to trawl through it...
+ var err error
+ proto.MessageReflect(pm).Range(func(fld protoreflect.FieldDescriptor, val protoreflect.Value) bool {
+ if !fld.IsExtension() {
+ // normal field... we already got it above
+ return true
+ }
+ xt := fld.(protoreflect.ExtensionTypeDescriptor)
+ if _, ok := xt.Type().(*proto.ExtensionDesc); ok {
+ // known extension... we already got it above
+ return true
+ }
+ var fd *desc.FieldDescriptor
+ fd, err = desc.WrapField(fld)
+ if err != nil {
+ return false
+ }
+ v := convertProtoReflectValue(val)
+ if v, err = validFieldValue(fd, v); err != nil {
+ return false
+ }
+ values[fd] = v
+ return true
+ })
+ if err != nil {
+ return err
+ }
+
+ // unrecognized extensions fields:
+ // In API v2 of proto, some extensions may NEITHER be included in ExtensionDescs
+ // above NOR included in unrecognized fields below. These are extensions that use
+ // a custom extension type (not a generated one -- i.e. not a linked in extension).
+ mr := proto.MessageReflect(pm)
+ var extBytes []byte
+ var retErr error
+ mr.Range(func(fld protoreflect.FieldDescriptor, val protoreflect.Value) bool {
+ if !fld.IsExtension() {
+ // normal field, already processed above
+ return true
+ }
+ if extd, ok := fld.(protoreflect.ExtensionTypeDescriptor); ok {
+ if _, ok := extd.Type().(*proto.ExtensionDesc); ok {
+ // normal known extension, already processed above
+ return true
+ }
+ }
+
+ // marshal the extension to bytes and then handle as unknown field below
+ mr.New()
+ mr.Set(fld, val)
+ extBytes, retErr = protov2.MarshalOptions{}.MarshalAppend(extBytes, mr.Interface())
+ return retErr == nil
+ })
+ if retErr != nil {
+ return retErr
+ }
+
// now actually perform the merge
for fd, v := range values {
if err := mergeField(m, fd, v); err != nil {
@@ -2560,6 +2625,12 @@
}
}
+ if len(extBytes) > 0 {
+ // treating unrecognized extensions like unknown fields: best-effort
+ // ignore any error returned: pulling in unknown fields is best-effort
+ _ = m.UnmarshalMerge(extBytes)
+ }
+
data := internal.GetUnrecognized(pm)
if len(data) > 0 {
// ignore any error returned: pulling in unknown fields is best-effort
@@ -2569,6 +2640,31 @@
return nil
}
+func convertProtoReflectValue(v protoreflect.Value) interface{} {
+ val := v.Interface()
+ switch val := val.(type) {
+ case protoreflect.Message:
+ return val.Interface()
+ case protoreflect.Map:
+ mp := make(map[interface{}]interface{}, val.Len())
+ val.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
+ mp[convertProtoReflectValue(k.Value())] = convertProtoReflectValue(v)
+ return true
+ })
+ return mp
+ case protoreflect.List:
+ sl := make([]interface{}, val.Len())
+ for i := 0; i < val.Len(); i++ {
+ sl[i] = convertProtoReflectValue(val.Get(i))
+ }
+ return sl
+ case protoreflect.EnumNumber:
+ return int32(val)
+ default:
+ return val
+ }
+}
+
// Validate checks that all required fields are present. It returns an error if any are absent.
func (m *Message) Validate() error {
missingFields := m.findMissingFields()
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/grpcdynamic/stub.go b/vendor/github.com/jhump/protoreflect/dynamic/grpcdynamic/stub.go
index 1eaedfa..6fca393 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/grpcdynamic/stub.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/grpcdynamic/stub.go
@@ -4,11 +4,11 @@
package grpcdynamic
import (
+ "context"
"fmt"
"io"
"github.com/golang/protobuf/proto"
- "golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
@@ -27,12 +27,7 @@
// type used to construct Stubs. But the use of this interface allows
// construction of stubs that use alternate concrete types as the transport for
// RPC operations.
-type Channel interface {
- Invoke(ctx context.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error
- NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error)
-}
-
-var _ Channel = (*grpc.ClientConn)(nil)
+type Channel = grpc.ClientConnInterface
// NewStub creates a new RPC stub that uses the given channel for dispatching RPCs.
func NewStub(channel Channel) Stub {
@@ -79,6 +74,7 @@
ClientStreams: method.IsClientStreaming(),
}
if cs, err := s.channel.NewStream(ctx, &sd, requestMethod(method), opts...); err != nil {
+ cancel()
return nil, err
} else {
err = cs.SendMsg(request)
@@ -91,6 +87,11 @@
cancel()
return nil, err
}
+ go func() {
+ // when the new stream is finished, also cleanup the parent context
+ <-cs.Context().Done()
+ cancel()
+ }()
return &ServerStream{cs, method.GetOutputType(), s.mf}, nil
}
}
@@ -108,8 +109,14 @@
ClientStreams: method.IsClientStreaming(),
}
if cs, err := s.channel.NewStream(ctx, &sd, requestMethod(method), opts...); err != nil {
+ cancel()
return nil, err
} else {
+ go func() {
+ // when the new stream is finished, also cleanup the parent context
+ <-cs.Context().Done()
+ cancel()
+ }()
return &ClientStream{cs, method, s.mf, cancel}, nil
}
}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/json.go b/vendor/github.com/jhump/protoreflect/dynamic/json.go
index 02c8298..9081965 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/json.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/json.go
@@ -17,14 +17,14 @@
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/types/descriptorpb"
// link in the well-known-types that have a special JSON format
- _ "github.com/golang/protobuf/ptypes/any"
- _ "github.com/golang/protobuf/ptypes/duration"
- _ "github.com/golang/protobuf/ptypes/empty"
- _ "github.com/golang/protobuf/ptypes/struct"
- _ "github.com/golang/protobuf/ptypes/timestamp"
- _ "github.com/golang/protobuf/ptypes/wrappers"
+ _ "google.golang.org/protobuf/types/known/anypb"
+ _ "google.golang.org/protobuf/types/known/durationpb"
+ _ "google.golang.org/protobuf/types/known/emptypb"
+ _ "google.golang.org/protobuf/types/known/structpb"
+ _ "google.golang.org/protobuf/types/known/timestamppb"
+ _ "google.golang.org/protobuf/types/known/wrapperspb"
"github.com/jhump/protoreflect/desc"
)
@@ -60,7 +60,7 @@
// This method is convenient shorthand for invoking MarshalJSONPB with a default
// (zero value) marshaler:
//
-// m.MarshalJSONPB(&jsonpb.Marshaler{})
+// m.MarshalJSONPB(&jsonpb.Marshaler{})
//
// So enums are serialized using enum value name strings, and values that are
// not present (including those with default/zero value for messages defined in
@@ -80,7 +80,7 @@
// This method is convenient shorthand for invoking MarshalJSONPB with a default
// (zero value) marshaler:
//
-// m.MarshalJSONPB(&jsonpb.Marshaler{Indent: " "})
+// m.MarshalJSONPB(&jsonpb.Marshaler{Indent: " "})
//
// So enums are serialized using enum value name strings, and values that are
// not present (including those with default/zero value for messages defined in
@@ -497,7 +497,7 @@
// This method is shorthand for invoking UnmarshalJSONPB with a default (zero
// value) unmarshaler:
//
-// m.UnmarshalMergeJSONPB(&jsonpb.Unmarshaler{}, js)
+// m.UnmarshalMergeJSONPB(&jsonpb.Unmarshaler{}, js)
//
// So unknown fields will result in an error, and no provided jsonpb.AnyResolver
// will be used when parsing google.protobuf.Any messages.
@@ -669,13 +669,13 @@
}
func isWellKnownValue(fd *desc.FieldDescriptor) bool {
- return !fd.IsRepeated() && fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE &&
+ return !fd.IsRepeated() && fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE &&
fd.GetMessageType().GetFullyQualifiedName() == "google.protobuf.Value"
}
func isWellKnownListValue(fd *desc.FieldDescriptor) bool {
// we look for ListValue; but we also look for Value, which can be assigned a ListValue
- return !fd.IsRepeated() && fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE &&
+ return !fd.IsRepeated() && fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE &&
(fd.GetMessageType().GetFullyQualifiedName() == "google.protobuf.ListValue" ||
fd.GetMessageType().GetFullyQualifiedName() == "google.protobuf.Value")
}
@@ -794,8 +794,8 @@
}
switch fd.GetType() {
- case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
- descriptor.FieldDescriptorProto_TYPE_GROUP:
+ case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE,
+ descriptorpb.FieldDescriptorProto_TYPE_GROUP:
if t == nil && allowNilMessage {
// if json is simply "null" return a nil pointer
@@ -822,7 +822,7 @@
}
return m, nil
- case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ case descriptorpb.FieldDescriptorProto_TYPE_ENUM:
if e, err := r.nextNumber(); err != nil {
return nil, err
} else {
@@ -842,9 +842,9 @@
}
}
- case descriptor.FieldDescriptorProto_TYPE_INT32,
- descriptor.FieldDescriptorProto_TYPE_SINT32,
- descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED32:
if i, err := r.nextInt(); err != nil {
return nil, err
} else if i > math.MaxInt32 || i < math.MinInt32 {
@@ -853,13 +853,13 @@
return int32(i), err
}
- case descriptor.FieldDescriptorProto_TYPE_INT64,
- descriptor.FieldDescriptorProto_TYPE_SINT64,
- descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED64:
return r.nextInt()
- case descriptor.FieldDescriptorProto_TYPE_UINT32,
- descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED32:
if i, err := r.nextUint(); err != nil {
return nil, err
} else if i > math.MaxUint32 {
@@ -868,11 +868,11 @@
return uint32(i), err
}
- case descriptor.FieldDescriptorProto_TYPE_UINT64,
- descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED64:
return r.nextUint()
- case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
if str, ok := t.(string); ok {
if str == "true" {
r.poll() // consume token
@@ -884,20 +884,20 @@
}
return r.nextBool()
- case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
if f, err := r.nextFloat(); err != nil {
return nil, err
} else {
return float32(f), nil
}
- case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
return r.nextFloat()
- case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
return r.nextBytes()
- case descriptor.FieldDescriptorProto_TYPE_STRING:
+ case descriptorpb.FieldDescriptorProto_TYPE_STRING:
return r.nextString()
default:
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/maps_1.11.go b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.11.go
index 03162a4..69969fc 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/maps_1.11.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.11.go
@@ -4,8 +4,9 @@
package dynamic
import (
- "github.com/jhump/protoreflect/desc"
"reflect"
+
+ "github.com/jhump/protoreflect/desc"
)
// Pre-Go-1.12, we must use reflect.Value.MapKeys to reflectively
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/maps_1.12.go b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.12.go
index ef1b370..fb353cf 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/maps_1.12.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.12.go
@@ -4,8 +4,9 @@
package dynamic
import (
- "github.com/jhump/protoreflect/desc"
"reflect"
+
+ "github.com/jhump/protoreflect/desc"
)
// With Go 1.12 and above, we can use reflect.Value.MapRange to iterate
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/message_factory.go b/vendor/github.com/jhump/protoreflect/dynamic/message_factory.go
index 9ab8e61..683e7b3 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/message_factory.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/message_factory.go
@@ -37,9 +37,10 @@
// (those for which protoc-generated code is statically linked into the Go program) are
// known types. If any dynamic messages are produced, they will recognize and parse all
// "default" extension fields. This is the equivalent of:
-// NewMessageFactoryWithRegistries(
-// NewExtensionRegistryWithDefaults(),
-// NewKnownTypeRegistryWithDefaults())
+//
+// NewMessageFactoryWithRegistries(
+// NewExtensionRegistryWithDefaults(),
+// NewKnownTypeRegistryWithDefaults())
func NewMessageFactoryWithDefaults() *MessageFactory {
return NewMessageFactoryWithRegistries(NewExtensionRegistryWithDefaults(), NewKnownTypeRegistryWithDefaults())
}
@@ -174,28 +175,33 @@
// GetKnownType will return the reflect.Type for the given message name if it is
// known. If it is not known, nil is returned.
func (r *KnownTypeRegistry) GetKnownType(messageName string) reflect.Type {
- var msgType reflect.Type
if r == nil {
// a nil registry behaves the same as zero value instance: only know of well-known types
t := proto.MessageType(messageName)
if t != nil && isWellKnownType(t) {
- msgType = t
+ return t
}
- } else {
- if r.includeDefault {
- msgType = proto.MessageType(messageName)
- } else if !r.excludeWkt {
- t := proto.MessageType(messageName)
- if t != nil && isWellKnownType(t) {
- msgType = t
- }
+ return nil
+ }
+
+ if r.includeDefault {
+ t := proto.MessageType(messageName)
+ if t != nil && isMessage(t) {
+ return t
}
- if msgType == nil {
- r.mu.RLock()
- msgType = r.types[messageName]
- r.mu.RUnlock()
+ } else if !r.excludeWkt {
+ t := proto.MessageType(messageName)
+ if t != nil && isWellKnownType(t) {
+ return t
}
}
- return msgType
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ return r.types[messageName]
+}
+
+func isMessage(t reflect.Type) bool {
+ _, ok := reflect.Zero(t).Interface().(proto.Message)
+ return ok
}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/text.go b/vendor/github.com/jhump/protoreflect/dynamic/text.go
index 5784d3e..5680dc2 100644
--- a/vendor/github.com/jhump/protoreflect/dynamic/text.go
+++ b/vendor/github.com/jhump/protoreflect/dynamic/text.go
@@ -15,7 +15,7 @@
"unicode"
"github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/types/descriptorpb"
"github.com/jhump/protoreflect/codec"
"github.com/jhump/protoreflect/desc"
@@ -208,7 +208,7 @@
}
func marshalKnownFieldText(b *indentBuffer, fd *desc.FieldDescriptor, v interface{}) error {
- group := fd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP
+ group := fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP
if group {
var name string
if fd.IsExtension() {
@@ -518,7 +518,7 @@
if fd == nil {
// See if it's a group name
for _, field := range m.md.GetFields() {
- if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetMessageType().GetName() == fieldName {
+ if field.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP && field.GetMessageType().GetName() == fieldName {
fd = field
break
}
@@ -581,8 +581,8 @@
return err
}
- } else if (fd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP ||
- fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
+ } else if (fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP ||
+ fd.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE) &&
tok.tokTyp.EndToken() != tokenError {
// TODO: use mf.NewMessage and, if not a dynamic message, use proto.UnmarshalText to unmarshal it
@@ -689,7 +689,7 @@
var expected string
switch fd.GetType() {
- case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
if tok.tokTyp == tokenIdent {
if tok.val.(string) == "true" {
return set(m, fd, true)
@@ -698,17 +698,17 @@
}
}
expected = "boolean value"
- case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
if tok.tokTyp == tokenString {
return set(m, fd, []byte(tok.val.(string)))
}
expected = "bytes string value"
- case descriptor.FieldDescriptorProto_TYPE_STRING:
+ case descriptorpb.FieldDescriptorProto_TYPE_STRING:
if tok.tokTyp == tokenString {
return set(m, fd, tok.val)
}
expected = "string value"
- case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
switch tok.tokTyp {
case tokenFloat:
return set(m, fd, float32(tok.val.(float64)))
@@ -736,7 +736,7 @@
}
}
expected = "float value"
- case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
switch tok.tokTyp {
case tokenFloat:
return set(m, fd, tok.val)
@@ -764,9 +764,9 @@
}
}
expected = "float value"
- case descriptor.FieldDescriptorProto_TYPE_INT32,
- descriptor.FieldDescriptorProto_TYPE_SINT32,
- descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED32:
if tok.tokTyp == tokenInt {
if i, err := strconv.ParseInt(tok.val.(string), 10, 32); err != nil {
return err
@@ -775,9 +775,9 @@
}
}
expected = "int value"
- case descriptor.FieldDescriptorProto_TYPE_INT64,
- descriptor.FieldDescriptorProto_TYPE_SINT64,
- descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_INT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_SFIXED64:
if tok.tokTyp == tokenInt {
if i, err := strconv.ParseInt(tok.val.(string), 10, 64); err != nil {
return err
@@ -786,8 +786,8 @@
}
}
expected = "int value"
- case descriptor.FieldDescriptorProto_TYPE_UINT32,
- descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT32,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED32:
if tok.tokTyp == tokenInt {
if i, err := strconv.ParseUint(tok.val.(string), 10, 32); err != nil {
return err
@@ -796,8 +796,8 @@
}
}
expected = "unsigned int value"
- case descriptor.FieldDescriptorProto_TYPE_UINT64,
- descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ case descriptorpb.FieldDescriptorProto_TYPE_UINT64,
+ descriptorpb.FieldDescriptorProto_TYPE_FIXED64:
if tok.tokTyp == tokenInt {
if i, err := strconv.ParseUint(tok.val.(string), 10, 64); err != nil {
return err
@@ -806,7 +806,7 @@
}
}
expected = "unsigned int value"
- case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ case descriptorpb.FieldDescriptorProto_TYPE_ENUM:
if tok.tokTyp == tokenIdent {
// TODO: add a flag to just ignore unrecognized enum value names?
vd := fd.GetEnumType().FindValueByName(tok.val.(string))
@@ -821,8 +821,8 @@
}
}
expected = fmt.Sprintf("enum %s value", fd.GetEnumType().GetFullyQualifiedName())
- case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
- descriptor.FieldDescriptorProto_TYPE_GROUP:
+ case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE,
+ descriptorpb.FieldDescriptorProto_TYPE_GROUP:
endTok := tok.tokTyp.EndToken()
if endTok != tokenError {
diff --git a/vendor/github.com/jhump/protoreflect/grpcreflect/adapt.go b/vendor/github.com/jhump/protoreflect/grpcreflect/adapt.go
new file mode 100644
index 0000000..661b925
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/grpcreflect/adapt.go
@@ -0,0 +1,137 @@
+package grpcreflect
+
+import (
+ refv1 "google.golang.org/grpc/reflection/grpc_reflection_v1"
+ refv1alpha "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
+)
+
+func toV1Request(v1alpha *refv1alpha.ServerReflectionRequest) *refv1.ServerReflectionRequest {
+ var v1 refv1.ServerReflectionRequest
+ v1.Host = v1alpha.Host
+ switch mr := v1alpha.MessageRequest.(type) {
+ case *refv1alpha.ServerReflectionRequest_FileByFilename:
+ v1.MessageRequest = &refv1.ServerReflectionRequest_FileByFilename{
+ FileByFilename: mr.FileByFilename,
+ }
+ case *refv1alpha.ServerReflectionRequest_FileContainingSymbol:
+ v1.MessageRequest = &refv1.ServerReflectionRequest_FileContainingSymbol{
+ FileContainingSymbol: mr.FileContainingSymbol,
+ }
+ case *refv1alpha.ServerReflectionRequest_FileContainingExtension:
+ if mr.FileContainingExtension != nil {
+ v1.MessageRequest = &refv1.ServerReflectionRequest_FileContainingExtension{
+ FileContainingExtension: &refv1.ExtensionRequest{
+ ContainingType: mr.FileContainingExtension.GetContainingType(),
+ ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(),
+ },
+ }
+ }
+ case *refv1alpha.ServerReflectionRequest_AllExtensionNumbersOfType:
+ v1.MessageRequest = &refv1.ServerReflectionRequest_AllExtensionNumbersOfType{
+ AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType,
+ }
+ case *refv1alpha.ServerReflectionRequest_ListServices:
+ v1.MessageRequest = &refv1.ServerReflectionRequest_ListServices{
+ ListServices: mr.ListServices,
+ }
+ default:
+ // no value set
+ }
+ return &v1
+}
+
+func toV1AlphaRequest(v1 *refv1.ServerReflectionRequest) *refv1alpha.ServerReflectionRequest {
+ var v1alpha refv1alpha.ServerReflectionRequest
+ v1alpha.Host = v1.Host
+ switch mr := v1.MessageRequest.(type) {
+ case *refv1.ServerReflectionRequest_FileByFilename:
+ if mr != nil {
+ v1alpha.MessageRequest = &refv1alpha.ServerReflectionRequest_FileByFilename{
+ FileByFilename: mr.FileByFilename,
+ }
+ }
+ case *refv1.ServerReflectionRequest_FileContainingSymbol:
+ if mr != nil {
+ v1alpha.MessageRequest = &refv1alpha.ServerReflectionRequest_FileContainingSymbol{
+ FileContainingSymbol: mr.FileContainingSymbol,
+ }
+ }
+ case *refv1.ServerReflectionRequest_FileContainingExtension:
+ if mr != nil {
+ v1alpha.MessageRequest = &refv1alpha.ServerReflectionRequest_FileContainingExtension{
+ FileContainingExtension: &refv1alpha.ExtensionRequest{
+ ContainingType: mr.FileContainingExtension.GetContainingType(),
+ ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(),
+ },
+ }
+ }
+ case *refv1.ServerReflectionRequest_AllExtensionNumbersOfType:
+ if mr != nil {
+ v1alpha.MessageRequest = &refv1alpha.ServerReflectionRequest_AllExtensionNumbersOfType{
+ AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType,
+ }
+ }
+ case *refv1.ServerReflectionRequest_ListServices:
+ if mr != nil {
+ v1alpha.MessageRequest = &refv1alpha.ServerReflectionRequest_ListServices{
+ ListServices: mr.ListServices,
+ }
+ }
+ default:
+ // no value set
+ }
+ return &v1alpha
+}
+
+func toV1Response(v1alpha *refv1alpha.ServerReflectionResponse) *refv1.ServerReflectionResponse {
+ var v1 refv1.ServerReflectionResponse
+ v1.ValidHost = v1alpha.ValidHost
+ if v1alpha.OriginalRequest != nil {
+ v1.OriginalRequest = toV1Request(v1alpha.OriginalRequest)
+ }
+ switch mr := v1alpha.MessageResponse.(type) {
+ case *refv1alpha.ServerReflectionResponse_FileDescriptorResponse:
+ if mr != nil {
+ v1.MessageResponse = &refv1.ServerReflectionResponse_FileDescriptorResponse{
+ FileDescriptorResponse: &refv1.FileDescriptorResponse{
+ FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(),
+ },
+ }
+ }
+ case *refv1alpha.ServerReflectionResponse_AllExtensionNumbersResponse:
+ if mr != nil {
+ v1.MessageResponse = &refv1.ServerReflectionResponse_AllExtensionNumbersResponse{
+ AllExtensionNumbersResponse: &refv1.ExtensionNumberResponse{
+ BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(),
+ ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(),
+ },
+ }
+ }
+ case *refv1alpha.ServerReflectionResponse_ListServicesResponse:
+ if mr != nil {
+ svcs := make([]*refv1.ServiceResponse, len(mr.ListServicesResponse.GetService()))
+ for i, svc := range mr.ListServicesResponse.GetService() {
+ svcs[i] = &refv1.ServiceResponse{
+ Name: svc.GetName(),
+ }
+ }
+ v1.MessageResponse = &refv1.ServerReflectionResponse_ListServicesResponse{
+ ListServicesResponse: &refv1.ListServiceResponse{
+ Service: svcs,
+ },
+ }
+ }
+ case *refv1alpha.ServerReflectionResponse_ErrorResponse:
+ if mr != nil {
+ v1.MessageResponse = &refv1.ServerReflectionResponse_ErrorResponse{
+ ErrorResponse: &refv1.ErrorResponse{
+ ErrorCode: mr.ErrorResponse.GetErrorCode(),
+ ErrorMessage: mr.ErrorResponse.GetErrorMessage(),
+ },
+ }
+ }
+ default:
+ // no value set
+ }
+ return &v1
+}
diff --git a/vendor/github.com/jhump/protoreflect/grpcreflect/client.go b/vendor/github.com/jhump/protoreflect/grpcreflect/client.go
index 3fca3eb..1a35540 100644
--- a/vendor/github.com/jhump/protoreflect/grpcreflect/client.go
+++ b/vendor/github.com/jhump/protoreflect/grpcreflect/client.go
@@ -2,23 +2,39 @@
import (
"bytes"
+ "context"
"fmt"
"io"
"reflect"
"runtime"
+ "sort"
"sync"
+ "sync/atomic"
+ "time"
"github.com/golang/protobuf/proto"
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
- "golang.org/x/net/context"
+ "google.golang.org/grpc"
"google.golang.org/grpc/codes"
- rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
+ refv1 "google.golang.org/grpc/reflection/grpc_reflection_v1"
+ refv1alpha "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status"
+ "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"
"github.com/jhump/protoreflect/internal"
)
+// If we try the v1 reflection API and get back "not implemented", we'll wait
+// this long before trying v1 again. This allows a long-lived client to
+// dynamically switch from v1alpha to v1 if the underlying server is updated
+// to support it. But it also prevents every stream request from always trying
+// v1 first: if we try it and see it fail, we shouldn't continually retry it
+// if we expect it will fail again.
+const durationBetweenV1Attempts = time.Hour
+
// elementNotFoundError is the error returned by reflective operations where the
// server does not recognize a given file name, symbol name, or extension.
type elementNotFoundError struct {
@@ -51,14 +67,31 @@
)
func symbolNotFound(symbol string, symType symbolType, cause *elementNotFoundError) error {
+ if cause != nil && cause.kind == elementKindSymbol && cause.name == symbol {
+ // no need to wrap
+ if symType != symbolTypeUnknown && cause.symType == symbolTypeUnknown {
+ // We previously didn't know symbol type but now do?
+ // Create a new error that has the right symbol type.
+ return &elementNotFoundError{name: symbol, symType: symType, kind: elementKindSymbol}
+ }
+ return cause
+ }
return &elementNotFoundError{name: symbol, symType: symType, kind: elementKindSymbol, cause: cause}
}
func extensionNotFound(extendee string, tag int32, cause *elementNotFoundError) error {
+ if cause != nil && cause.kind == elementKindExtension && cause.name == extendee && cause.tag == tag {
+ // no need to wrap
+ return cause
+ }
return &elementNotFoundError{name: extendee, tag: tag, kind: elementKindExtension, cause: cause}
}
func fileNotFound(file string, cause *elementNotFoundError) error {
+ if cause != nil && cause.kind == elementKindFile && cause.name == file {
+ // no need to wrap
+ return cause
+ }
return &elementNotFoundError{name: file, kind: elementKindFile, cause: cause}
}
@@ -69,15 +102,15 @@
if first {
first = false
} else {
- fmt.Fprint(&b, "\ncaused by: ")
+ _, _ = fmt.Fprint(&b, "\ncaused by: ")
}
switch e.kind {
case elementKindSymbol:
- fmt.Fprintf(&b, "%s not found: %s", e.symType, e.name)
+ _, _ = fmt.Fprintf(&b, "%s not found: %s", e.symType, e.name)
case elementKindExtension:
- fmt.Fprintf(&b, "Extension not found: tag %d for %s", e.tag, e.name)
+ _, _ = fmt.Fprintf(&b, "Extension not found: tag %d for %s", e.tag, e.name)
default:
- fmt.Fprintf(&b, "File not found: %s", e.name)
+ _, _ = fmt.Fprintf(&b, "File not found: %s", e.name)
}
}
return b.String()
@@ -105,79 +138,186 @@
extensionNumber int32
}
+type resolvers struct {
+ descriptorResolver protodesc.Resolver
+ extensionResolver protoregistry.ExtensionTypeResolver
+}
+
+type fileEntry struct {
+ fd *desc.FileDescriptor
+ fallback bool
+}
+
// Client is a client connection to a server for performing reflection calls
// and resolving remote symbols.
type Client struct {
- ctx context.Context
- stub rpb.ServerReflectionClient
+ ctx context.Context
+ now func() time.Time
+ stubV1 refv1.ServerReflectionClient
+ stubV1Alpha refv1alpha.ServerReflectionClient
+ allowMissing atomic.Bool
+ fallbackResolver atomic.Pointer[resolvers]
- connMu sync.Mutex
- cancel context.CancelFunc
- stream rpb.ServerReflection_ServerReflectionInfoClient
+ connMu sync.Mutex
+ cancel context.CancelFunc
+ stream refv1.ServerReflection_ServerReflectionInfoClient
+ useV1Alpha bool
+ lastTriedV1 time.Time
cacheMu sync.RWMutex
- protosByName map[string]*dpb.FileDescriptorProto
- filesByName map[string]*desc.FileDescriptor
- filesBySymbol map[string]*desc.FileDescriptor
- filesByExtension map[extDesc]*desc.FileDescriptor
+ protosByName map[string]*descriptorpb.FileDescriptorProto
+ filesByName map[string]fileEntry
+ filesBySymbol map[string]fileEntry
+ filesByExtension map[extDesc]fileEntry
}
// NewClient creates a new Client with the given root context and using the
// given RPC stub for talking to the server.
-func NewClient(ctx context.Context, stub rpb.ServerReflectionClient) *Client {
+//
+// Deprecated: Use NewClientV1Alpha if you are intentionally pinning the
+// v1alpha version of the reflection service. Otherwise, use NewClientAuto
+// instead.
+func NewClient(ctx context.Context, stub refv1alpha.ServerReflectionClient) *Client {
+ return NewClientV1Alpha(ctx, stub)
+}
+
+// NewClientV1Alpha creates a new Client using the v1alpha version of reflection
+// with the given root context and using the given RPC stub for talking to the
+// server.
+func NewClientV1Alpha(ctx context.Context, stub refv1alpha.ServerReflectionClient) *Client {
+ return newClient(ctx, nil, stub)
+}
+
+// NewClientV1 creates a new Client using the v1 version of reflection with the
+// given root context and using the given RPC stub for talking to the server.
+func NewClientV1(ctx context.Context, stub refv1.ServerReflectionClient) *Client {
+ return newClient(ctx, stub, nil)
+}
+
+func newClient(ctx context.Context, stubv1 refv1.ServerReflectionClient, stubv1alpha refv1alpha.ServerReflectionClient) *Client {
cr := &Client{
ctx: ctx,
- stub: stub,
- protosByName: map[string]*dpb.FileDescriptorProto{},
- filesByName: map[string]*desc.FileDescriptor{},
- filesBySymbol: map[string]*desc.FileDescriptor{},
- filesByExtension: map[extDesc]*desc.FileDescriptor{},
+ now: time.Now,
+ stubV1: stubv1,
+ stubV1Alpha: stubv1alpha,
+ protosByName: map[string]*descriptorpb.FileDescriptorProto{},
+ filesByName: map[string]fileEntry{},
+ filesBySymbol: map[string]fileEntry{},
+ filesByExtension: map[extDesc]fileEntry{},
}
// don't leak a grpc stream
runtime.SetFinalizer(cr, (*Client).Reset)
return cr
}
+// NewClientAuto creates a new Client that will use either v1 or v1alpha version
+// of reflection (based on what the server supports) with the given root context
+// and using the given client connection.
+//
+// It will first the v1 version of the reflection service. If it gets back an
+// "Unimplemented" error, it will fall back to using the v1alpha version. It
+// will remember which version the server supports for any subsequent operations
+// that need to re-invoke the streaming RPC. But, if it's a very long-lived
+// client, it will periodically retry the v1 version (in case the server is
+// updated to support it also). The period for these retries is every hour.
+func NewClientAuto(ctx context.Context, cc grpc.ClientConnInterface) *Client {
+ stubv1 := refv1.NewServerReflectionClient(cc)
+ stubv1alpha := refv1alpha.NewServerReflectionClient(cc)
+ return newClient(ctx, stubv1, stubv1alpha)
+}
+
+// AllowMissingFileDescriptors configures the client to allow missing files
+// when building descriptors when possible. Missing files are often fatal
+// errors, but with this option they can sometimes be worked around. Building
+// a schema can only succeed with some files missing if the files in question
+// only provide custom options and/or other unused types.
+func (cr *Client) AllowMissingFileDescriptors() {
+ cr.allowMissing.Store(true)
+}
+
+// AllowFallbackResolver configures the client to allow falling back to the
+// given resolvers if the server is unable to supply descriptors for a particular
+// query. This allows working around issues where servers' reflection service
+// provides an incomplete set of descriptors, but the client has knowledge of
+// the missing descriptors from another source. It is usually most appropriate
+// to pass [protoregistry.GlobalFiles] and [protoregistry.GlobalTypes] as the
+// resolver values.
+//
+// The first value is used as a fallback for FileByFilename and FileContainingSymbol
+// queries. The second value is used as a fallback for FileContainingExtension. It
+// can also be used as a fallback for AllExtensionNumbersForType if it provides
+// a method with the following signature (which *[protoregistry.Types] provides):
+//
+// RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
+func (cr *Client) AllowFallbackResolver(descriptors protodesc.Resolver, exts protoregistry.ExtensionTypeResolver) {
+ if descriptors == nil && exts == nil {
+ cr.fallbackResolver.Store(nil)
+ } else {
+ cr.fallbackResolver.Store(&resolvers{
+ descriptorResolver: descriptors,
+ extensionResolver: exts,
+ })
+ }
+}
+
// FileByFilename asks the server for a file descriptor for the proto file with
// the given name.
func (cr *Client) FileByFilename(filename string) (*desc.FileDescriptor, error) {
// hit the cache first
cr.cacheMu.RLock()
- if fd, ok := cr.filesByName[filename]; ok {
+ if entry, ok := cr.filesByName[filename]; ok {
cr.cacheMu.RUnlock()
- return fd, nil
+ return entry.fd, nil
}
+ // not there? see if we've downloaded the proto
fdp, ok := cr.protosByName[filename]
cr.cacheMu.RUnlock()
- // not there? see if we've downloaded the proto
if ok {
return cr.descriptorFromProto(fdp)
}
- req := &rpb.ServerReflectionRequest{
- MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{
+ req := &refv1.ServerReflectionRequest{
+ MessageRequest: &refv1.ServerReflectionRequest_FileByFilename{
FileByFilename: filename,
},
}
- fd, err := cr.getAndCacheFileDescriptors(req, filename, "")
+ accept := func(fd *desc.FileDescriptor) bool {
+ return fd.GetName() == filename
+ }
+
+ fd, err := cr.getAndCacheFileDescriptors(req, filename, "", accept)
if isNotFound(err) {
- // file not found? see if we can look up via alternate name
+ // File not found? see if we can look up via alternate name
if alternate, ok := internal.StdFileAliases[filename]; ok {
- req := &rpb.ServerReflectionRequest{
- MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{
+ req := &refv1.ServerReflectionRequest{
+ MessageRequest: &refv1.ServerReflectionRequest_FileByFilename{
FileByFilename: alternate,
},
}
- fd, err = cr.getAndCacheFileDescriptors(req, alternate, filename)
- if isNotFound(err) {
- err = fileNotFound(filename, nil)
- }
- } else {
- err = fileNotFound(filename, nil)
+ fd, err = cr.getAndCacheFileDescriptors(req, alternate, filename, accept)
}
+ }
+ if isNotFound(err) {
+ // Still no? See if we can use a fallback resolver
+ resolver := cr.fallbackResolver.Load()
+ if resolver != nil && resolver.descriptorResolver != nil {
+ fileDesc, fallbackErr := resolver.descriptorResolver.FindFileByPath(filename)
+ if fallbackErr == nil {
+ var wrapErr error
+ fd, wrapErr = desc.WrapFile(fileDesc)
+ if wrapErr == nil {
+ fd = cr.cacheFile(fd, true)
+ err = nil // clear error since we've succeeded via the fallback
+ }
+ }
+ }
+ }
+ if isNotFound(err) {
+ err = fileNotFound(filename, nil)
} else if e, ok := err.(*elementNotFoundError); ok {
err = fileNotFound(filename, e)
}
+
return fd, err
}
@@ -186,18 +326,36 @@
func (cr *Client) FileContainingSymbol(symbol string) (*desc.FileDescriptor, error) {
// hit the cache first
cr.cacheMu.RLock()
- fd, ok := cr.filesBySymbol[symbol]
+ entry, ok := cr.filesBySymbol[symbol]
cr.cacheMu.RUnlock()
if ok {
- return fd, nil
+ return entry.fd, nil
}
- req := &rpb.ServerReflectionRequest{
- MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{
+ req := &refv1.ServerReflectionRequest{
+ MessageRequest: &refv1.ServerReflectionRequest_FileContainingSymbol{
FileContainingSymbol: symbol,
},
}
- fd, err := cr.getAndCacheFileDescriptors(req, "", "")
+ accept := func(fd *desc.FileDescriptor) bool {
+ return fd.FindSymbol(symbol) != nil
+ }
+ fd, err := cr.getAndCacheFileDescriptors(req, "", "", accept)
+ if isNotFound(err) {
+ // Symbol not found? See if we can use a fallback resolver
+ resolver := cr.fallbackResolver.Load()
+ if resolver != nil && resolver.descriptorResolver != nil {
+ d, fallbackErr := resolver.descriptorResolver.FindDescriptorByName(protoreflect.FullName(symbol))
+ if fallbackErr == nil {
+ var wrapErr error
+ fd, wrapErr = desc.WrapFile(d.ParentFile())
+ if wrapErr == nil {
+ fd = cr.cacheFile(fd, true)
+ err = nil // clear error since we've succeeded via the fallback
+ }
+ }
+ }
+ }
if isNotFound(err) {
err = symbolNotFound(symbol, symbolTypeUnknown, nil)
} else if e, ok := err.(*elementNotFoundError); ok {
@@ -212,21 +370,39 @@
func (cr *Client) FileContainingExtension(extendedMessageName string, extensionNumber int32) (*desc.FileDescriptor, error) {
// hit the cache first
cr.cacheMu.RLock()
- fd, ok := cr.filesByExtension[extDesc{extendedMessageName, extensionNumber}]
+ entry, ok := cr.filesByExtension[extDesc{extendedMessageName, extensionNumber}]
cr.cacheMu.RUnlock()
if ok {
- return fd, nil
+ return entry.fd, nil
}
- req := &rpb.ServerReflectionRequest{
- MessageRequest: &rpb.ServerReflectionRequest_FileContainingExtension{
- FileContainingExtension: &rpb.ExtensionRequest{
+ req := &refv1.ServerReflectionRequest{
+ MessageRequest: &refv1.ServerReflectionRequest_FileContainingExtension{
+ FileContainingExtension: &refv1.ExtensionRequest{
ContainingType: extendedMessageName,
ExtensionNumber: extensionNumber,
},
},
}
- fd, err := cr.getAndCacheFileDescriptors(req, "", "")
+ accept := func(fd *desc.FileDescriptor) bool {
+ return fd.FindExtension(extendedMessageName, extensionNumber) != nil
+ }
+ fd, err := cr.getAndCacheFileDescriptors(req, "", "", accept)
+ if isNotFound(err) {
+ // Extension not found? See if we can use a fallback resolver
+ resolver := cr.fallbackResolver.Load()
+ if resolver != nil && resolver.extensionResolver != nil {
+ extType, fallbackErr := resolver.extensionResolver.FindExtensionByNumber(protoreflect.FullName(extendedMessageName), protoreflect.FieldNumber(extensionNumber))
+ if fallbackErr == nil {
+ var wrapErr error
+ fd, wrapErr = desc.WrapFile(extType.TypeDescriptor().ParentFile())
+ if wrapErr == nil {
+ fd = cr.cacheFile(fd, true)
+ err = nil // clear error since we've succeeded via the fallback
+ }
+ }
+ }
+ }
if isNotFound(err) {
err = extensionNotFound(extendedMessageName, extensionNumber, nil)
} else if e, ok := err.(*elementNotFoundError); ok {
@@ -235,7 +411,7 @@
return fd, err
}
-func (cr *Client) getAndCacheFileDescriptors(req *rpb.ServerReflectionRequest, expectedName, alias string) (*desc.FileDescriptor, error) {
+func (cr *Client) getAndCacheFileDescriptors(req *refv1.ServerReflectionRequest, expectedName, alias string, accept func(*desc.FileDescriptor) bool) (*desc.FileDescriptor, error) {
resp, err := cr.send(req)
if err != nil {
return nil, err
@@ -253,9 +429,9 @@
// should be the answer). If we're looking for a file by name, we can be
// smarter and make sure to grab one by name instead of just grabbing the
// first one.
- var firstFd *dpb.FileDescriptorProto
+ var fds []*descriptorpb.FileDescriptorProto
for _, fdBytes := range fdResp.FileDescriptorProto {
- fd := &dpb.FileDescriptorProto{}
+ fd := &descriptorpb.FileDescriptorProto{}
if err = proto.Unmarshal(fdBytes, fd); err != nil {
return nil, err
}
@@ -266,13 +442,6 @@
}
cr.cacheMu.Lock()
- // see if this file was created and cached concurrently
- if firstFd == nil {
- if d, ok := cr.filesByName[fd.GetName()]; ok {
- cr.cacheMu.Unlock()
- return d, nil
- }
- }
// store in cache of raw descriptor protos, but don't overwrite existing protos
if existingFd, ok := cr.protosByName[fd.GetName()]; ok {
fd = existingFd
@@ -280,120 +449,208 @@
cr.protosByName[fd.GetName()] = fd
}
cr.cacheMu.Unlock()
- if firstFd == nil {
- firstFd = fd
- }
- }
- if firstFd == nil {
- return nil, &ProtocolError{reflect.TypeOf(firstFd).Elem()}
+
+ fds = append(fds, fd)
}
- return cr.descriptorFromProto(firstFd)
+ // find the right result from the files returned
+ for _, fd := range fds {
+ result, err := cr.descriptorFromProto(fd)
+ if err != nil {
+ return nil, err
+ }
+ if accept(result) {
+ return result, nil
+ }
+ }
+
+ return nil, status.Errorf(codes.NotFound, "response does not include expected file")
}
-func (cr *Client) descriptorFromProto(fd *dpb.FileDescriptorProto) (*desc.FileDescriptor, error) {
- deps := make([]*desc.FileDescriptor, len(fd.GetDependency()))
+func (cr *Client) descriptorFromProto(fd *descriptorpb.FileDescriptorProto) (*desc.FileDescriptor, error) {
+ allowMissing := cr.allowMissing.Load()
+ deps := make([]*desc.FileDescriptor, 0, len(fd.GetDependency()))
+ var deferredErr error
+ var missingDeps []int
for i, depName := range fd.GetDependency() {
if dep, err := cr.FileByFilename(depName); err != nil {
- return nil, err
+ if _, ok := err.(*elementNotFoundError); !ok || !allowMissing {
+ return nil, err
+ }
+ // We'll ignore for now to see if the file is really necessary.
+ // (If it only supplies custom options, we can get by without it.)
+ if deferredErr == nil {
+ deferredErr = err
+ }
+ missingDeps = append(missingDeps, i)
} else {
- deps[i] = dep
+ deps = append(deps, dep)
}
}
+ if len(missingDeps) > 0 {
+ fd = fileWithoutDeps(fd, missingDeps)
+ }
d, err := desc.CreateFileDescriptor(fd, deps...)
if err != nil {
+ if deferredErr != nil {
+ // assume the issue is the missing dep
+ return nil, deferredErr
+ }
return nil, err
}
- d = cr.cacheFile(d)
+ d = cr.cacheFile(d, false)
return d, nil
}
-func (cr *Client) cacheFile(fd *desc.FileDescriptor) *desc.FileDescriptor {
+func (cr *Client) cacheFile(fd *desc.FileDescriptor, fallback bool) *desc.FileDescriptor {
cr.cacheMu.Lock()
defer cr.cacheMu.Unlock()
- // cache file descriptor by name, but don't overwrite existing entry
- // (existing entry could come from concurrent caller)
- if existingFd, ok := cr.filesByName[fd.GetName()]; ok {
- return existingFd
+ // Cache file descriptor by name. If we can't overwrite an existing
+ // entry, return it. (Existing entry could come from concurrent caller.)
+ if existing, ok := cr.filesByName[fd.GetName()]; ok && !canOverwrite(existing, fallback) {
+ return existing.fd
}
- cr.filesByName[fd.GetName()] = fd
+ entry := fileEntry{fd: fd, fallback: fallback}
+ cr.filesByName[fd.GetName()] = entry
// also cache by symbols and extensions
for _, m := range fd.GetMessageTypes() {
- cr.cacheMessageLocked(fd, m)
+ cr.cacheMessageLocked(m, entry)
}
for _, e := range fd.GetEnumTypes() {
- cr.filesBySymbol[e.GetFullyQualifiedName()] = fd
+ if !cr.maybeCacheFileBySymbol(e.GetFullyQualifiedName(), entry) {
+ continue
+ }
for _, v := range e.GetValues() {
- cr.filesBySymbol[v.GetFullyQualifiedName()] = fd
+ cr.maybeCacheFileBySymbol(v.GetFullyQualifiedName(), entry)
}
}
for _, e := range fd.GetExtensions() {
- cr.filesBySymbol[e.GetFullyQualifiedName()] = fd
- cr.filesByExtension[extDesc{e.GetOwner().GetFullyQualifiedName(), e.GetNumber()}] = fd
+ if !cr.maybeCacheFileBySymbol(e.GetFullyQualifiedName(), entry) {
+ continue
+ }
+ cr.maybeCacheFileByExtension(extDesc{e.GetOwner().GetFullyQualifiedName(), e.GetNumber()}, entry)
}
for _, s := range fd.GetServices() {
- cr.filesBySymbol[s.GetFullyQualifiedName()] = fd
+ if !cr.maybeCacheFileBySymbol(s.GetFullyQualifiedName(), entry) {
+ continue
+ }
for _, m := range s.GetMethods() {
- cr.filesBySymbol[m.GetFullyQualifiedName()] = fd
+ cr.maybeCacheFileBySymbol(m.GetFullyQualifiedName(), entry)
}
}
return fd
}
-func (cr *Client) cacheMessageLocked(fd *desc.FileDescriptor, md *desc.MessageDescriptor) {
- cr.filesBySymbol[md.GetFullyQualifiedName()] = fd
+func (cr *Client) cacheMessageLocked(md *desc.MessageDescriptor, entry fileEntry) {
+ if !cr.maybeCacheFileBySymbol(md.GetFullyQualifiedName(), entry) {
+ return
+ }
for _, f := range md.GetFields() {
- cr.filesBySymbol[f.GetFullyQualifiedName()] = fd
+ cr.maybeCacheFileBySymbol(f.GetFullyQualifiedName(), entry)
}
for _, o := range md.GetOneOfs() {
- cr.filesBySymbol[o.GetFullyQualifiedName()] = fd
+ cr.maybeCacheFileBySymbol(o.GetFullyQualifiedName(), entry)
}
for _, e := range md.GetNestedEnumTypes() {
- cr.filesBySymbol[e.GetFullyQualifiedName()] = fd
+ if !cr.maybeCacheFileBySymbol(e.GetFullyQualifiedName(), entry) {
+ continue
+ }
for _, v := range e.GetValues() {
- cr.filesBySymbol[v.GetFullyQualifiedName()] = fd
+ cr.maybeCacheFileBySymbol(v.GetFullyQualifiedName(), entry)
}
}
for _, e := range md.GetNestedExtensions() {
- cr.filesBySymbol[e.GetFullyQualifiedName()] = fd
- cr.filesByExtension[extDesc{e.GetOwner().GetFullyQualifiedName(), e.GetNumber()}] = fd
+ if !cr.maybeCacheFileBySymbol(e.GetFullyQualifiedName(), entry) {
+ continue
+ }
+ cr.maybeCacheFileByExtension(extDesc{e.GetOwner().GetFullyQualifiedName(), e.GetNumber()}, entry)
}
for _, m := range md.GetNestedMessageTypes() {
- cr.cacheMessageLocked(fd, m) // recurse
+ cr.cacheMessageLocked(m, entry) // recurse
}
}
+func canOverwrite(existing fileEntry, fallback bool) bool {
+ return !fallback && existing.fallback
+}
+
+func (cr *Client) maybeCacheFileBySymbol(symbol string, entry fileEntry) bool {
+ existing, ok := cr.filesBySymbol[symbol]
+ if ok && !canOverwrite(existing, entry.fallback) {
+ return false
+ }
+ cr.filesBySymbol[symbol] = entry
+ return true
+}
+
+func (cr *Client) maybeCacheFileByExtension(ext extDesc, entry fileEntry) {
+ existing, ok := cr.filesByExtension[ext]
+ if ok && !canOverwrite(existing, entry.fallback) {
+ return
+ }
+ cr.filesByExtension[ext] = entry
+}
+
// AllExtensionNumbersForType asks the server for all known extension numbers
// for the given fully-qualified message name.
func (cr *Client) AllExtensionNumbersForType(extendedMessageName string) ([]int32, error) {
- req := &rpb.ServerReflectionRequest{
- MessageRequest: &rpb.ServerReflectionRequest_AllExtensionNumbersOfType{
+ req := &refv1.ServerReflectionRequest{
+ MessageRequest: &refv1.ServerReflectionRequest_AllExtensionNumbersOfType{
AllExtensionNumbersOfType: extendedMessageName,
},
}
resp, err := cr.send(req)
- if err != nil {
- if isNotFound(err) {
- return nil, symbolNotFound(extendedMessageName, symbolTypeMessage, nil)
- }
+ var exts []int32
+ if err != nil && !isNotFound(err) {
+ // If the server doesn't know about the message type and returns "not found",
+ // we'll treat that as "no known extensions" instead of returning an error.
return nil, err
}
-
- extResp := resp.GetAllExtensionNumbersResponse()
- if extResp == nil {
- return nil, &ProtocolError{reflect.TypeOf(extResp).Elem()}
+ if err == nil {
+ extResp := resp.GetAllExtensionNumbersResponse()
+ if extResp == nil {
+ return nil, &ProtocolError{reflect.TypeOf(extResp).Elem()}
+ }
+ exts = extResp.ExtensionNumber
}
- return extResp.ExtensionNumber, nil
+
+ resolver := cr.fallbackResolver.Load()
+ if resolver != nil && resolver.extensionResolver != nil {
+ type extRanger interface {
+ RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
+ }
+ if ranger, ok := resolver.extensionResolver.(extRanger); ok {
+ // Merge results with fallback resolver
+ extSet := map[int32]struct{}{}
+ ranger.RangeExtensionsByMessage(protoreflect.FullName(extendedMessageName), func(extType protoreflect.ExtensionType) bool {
+ extSet[int32(extType.TypeDescriptor().Number())] = struct{}{}
+ return true
+ })
+ if len(extSet) > 0 {
+ // De-dupe with the set of extension numbers we got
+ // from the server and merge the results back into exts.
+ for _, ext := range exts {
+ extSet[ext] = struct{}{}
+ }
+ exts = make([]int32, 0, len(extSet))
+ for ext := range extSet {
+ exts = append(exts, ext)
+ }
+ sort.Slice(exts, func(i, j int) bool { return exts[i] < exts[j] })
+ }
+ }
+ }
+ return exts, nil
}
// ListServices asks the server for the fully-qualified names of all exposed
// services.
func (cr *Client) ListServices() ([]string, error) {
- req := &rpb.ServerReflectionRequest{
- MessageRequest: &rpb.ServerReflectionRequest_ListServices{
+ req := &refv1.ServerReflectionRequest{
+ MessageRequest: &refv1.ServerReflectionRequest_ListServices{
// proto doesn't indicate any purpose for this value and server impl
// doesn't actually use it...
ListServices: "*",
@@ -415,10 +672,10 @@
return serviceNames, nil
}
-func (cr *Client) send(req *rpb.ServerReflectionRequest) (*rpb.ServerReflectionResponse, error) {
+func (cr *Client) send(req *refv1.ServerReflectionRequest) (*refv1.ServerReflectionResponse, error) {
// we allow one immediate retry, in case we have a stale stream
// (e.g. closed by server)
- resp, err := cr.doSend(true, req)
+ resp, err := cr.doSend(req)
if err != nil {
return nil, err
}
@@ -440,16 +697,33 @@
return ok && s.Code() == codes.NotFound
}
-func (cr *Client) doSend(retry bool, req *rpb.ServerReflectionRequest) (*rpb.ServerReflectionResponse, error) {
+func (cr *Client) doSend(req *refv1.ServerReflectionRequest) (*refv1.ServerReflectionResponse, error) {
// TODO: Streams are thread-safe, so we shouldn't need to lock. But without locking, we'll need more machinery
// (goroutines and channels) to ensure that responses are correctly correlated with their requests and thus
// delivered in correct oder.
cr.connMu.Lock()
defer cr.connMu.Unlock()
- return cr.doSendLocked(retry, req)
+ return cr.doSendLocked(0, nil, req)
}
-func (cr *Client) doSendLocked(retry bool, req *rpb.ServerReflectionRequest) (*rpb.ServerReflectionResponse, error) {
+func (cr *Client) doSendLocked(attemptCount int, prevErr error, req *refv1.ServerReflectionRequest) (*refv1.ServerReflectionResponse, error) {
+ if attemptCount >= 3 && prevErr != nil {
+ return nil, prevErr
+ }
+ if (status.Code(prevErr) == codes.Unimplemented ||
+ status.Code(prevErr) == codes.Unavailable) &&
+ cr.useV1() {
+ // If v1 is unimplemented, fallback to v1alpha.
+ // We also fallback on unavailable because some servers have been
+ // observed to close the connection/cancel the stream, w/out sending
+ // back status or headers, when the service name is not known. When
+ // this happens, the RPC status code is unavailable.
+ // See https://github.com/fullstorydev/grpcurl/issues/434
+ cr.useV1Alpha = true
+ cr.lastTriedV1 = cr.now()
+ }
+ attemptCount++
+
if err := cr.initStreamLocked(); err != nil {
return nil, err
}
@@ -460,21 +734,15 @@
_, err = cr.stream.Recv()
}
cr.resetLocked()
- if retry {
- return cr.doSendLocked(false, req)
- }
- return nil, err
+ return cr.doSendLocked(attemptCount, err, req)
}
- if resp, err := cr.stream.Recv(); err != nil {
+ resp, err := cr.stream.Recv()
+ if err != nil {
cr.resetLocked()
- if retry {
- return cr.doSendLocked(false, req)
- }
- return nil, err
- } else {
- return resp, nil
+ return cr.doSendLocked(attemptCount, err, req)
}
+ return resp, nil
}
func (cr *Client) initStreamLocked() error {
@@ -483,11 +751,38 @@
}
var newCtx context.Context
newCtx, cr.cancel = context.WithCancel(cr.ctx)
+ if cr.useV1Alpha == true && cr.now().Sub(cr.lastTriedV1) > durationBetweenV1Attempts {
+ // we're due for periodic retry of v1
+ cr.useV1Alpha = false
+ }
+ if cr.useV1() {
+ // try the v1 API
+ streamv1, err := cr.stubV1.ServerReflectionInfo(newCtx)
+ if err == nil {
+ cr.stream = streamv1
+ return nil
+ }
+ if status.Code(err) != codes.Unimplemented {
+ return err
+ }
+ // oh well, fall through below to try v1alpha and update state
+ // so we skip straight to v1alpha next time
+ cr.useV1Alpha = true
+ cr.lastTriedV1 = cr.now()
+ }
var err error
- cr.stream, err = cr.stub.ServerReflectionInfo(newCtx)
+ streamv1alpha, err := cr.stubV1Alpha.ServerReflectionInfo(newCtx)
+ if err == nil {
+ cr.stream = adaptStreamFromV1Alpha{streamv1alpha}
+ return nil
+ }
return err
}
+func (cr *Client) useV1() bool {
+ return !cr.useV1Alpha && cr.stubV1 != nil
+}
+
// Reset ensures that any active stream with the server is closed, releasing any
// resources.
func (cr *Client) Reset() {
@@ -498,7 +793,7 @@
func (cr *Client) resetLocked() {
if cr.stream != nil {
- cr.stream.CloseSend()
+ _ = cr.stream.CloseSend()
for {
// drain the stream, this covers io.EOF too
if _, err := cr.stream.Recv(); err != nil {
@@ -605,6 +900,46 @@
}
}
+func fileWithoutDeps(fd *descriptorpb.FileDescriptorProto, missingDeps []int) *descriptorpb.FileDescriptorProto {
+ // We need to rebuild the file without the missing deps.
+ fd = proto.Clone(fd).(*descriptorpb.FileDescriptorProto)
+ newNumDeps := len(fd.GetDependency()) - len(missingDeps)
+ newDeps := make([]string, 0, newNumDeps)
+ remapped := make(map[int]int, newNumDeps)
+ missingIdx := 0
+ for i, dep := range fd.GetDependency() {
+ if missingIdx < len(missingDeps) {
+ if i == missingDeps[missingIdx] {
+ // This dep was missing. Skip it.
+ missingIdx++
+ continue
+ }
+ }
+ remapped[i] = len(newDeps)
+ newDeps = append(newDeps, dep)
+ }
+ // Also rebuild public and weak import slices.
+ newPublic := make([]int32, 0, len(fd.GetPublicDependency()))
+ for _, idx := range fd.GetPublicDependency() {
+ newIdx, ok := remapped[int(idx)]
+ if ok {
+ newPublic = append(newPublic, int32(newIdx))
+ }
+ }
+ newWeak := make([]int32, 0, len(fd.GetWeakDependency()))
+ for _, idx := range fd.GetWeakDependency() {
+ newIdx, ok := remapped[int(idx)]
+ if ok {
+ newWeak = append(newWeak, int32(newIdx))
+ }
+ }
+
+ fd.Dependency = newDeps
+ fd.PublicDependency = newPublic
+ fd.WeakDependency = newWeak
+ return fd
+}
+
func findExtension(extendedType string, extensionNumber int32, scope extensionScope) *desc.FieldDescriptor {
// search extensions in this scope
for _, ext := range scope.extensions() {
@@ -664,3 +999,20 @@
}
return scopes
}
+
+type adaptStreamFromV1Alpha struct {
+ refv1alpha.ServerReflection_ServerReflectionInfoClient
+}
+
+func (a adaptStreamFromV1Alpha) Send(request *refv1.ServerReflectionRequest) error {
+ v1req := toV1AlphaRequest(request)
+ return a.ServerReflection_ServerReflectionInfoClient.Send(v1req)
+}
+
+func (a adaptStreamFromV1Alpha) Recv() (*refv1.ServerReflectionResponse, error) {
+ v1resp, err := a.ServerReflection_ServerReflectionInfoClient.Recv()
+ if err != nil {
+ return nil, err
+ }
+ return toV1Response(v1resp), nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/grpcreflect/server.go b/vendor/github.com/jhump/protoreflect/grpcreflect/server.go
index c9ef619..7ff1912 100644
--- a/vendor/github.com/jhump/protoreflect/grpcreflect/server.go
+++ b/vendor/github.com/jhump/protoreflect/grpcreflect/server.go
@@ -4,13 +4,19 @@
"fmt"
"google.golang.org/grpc"
+ "google.golang.org/grpc/reflection"
"github.com/jhump/protoreflect/desc"
)
+// GRPCServer is the interface provided by a gRPC server. In addition to being a
+// service registrar (for registering services and handlers), it also has an
+// accessor for retrieving metadata about all registered services.
+type GRPCServer = reflection.GRPCServer
+
// LoadServiceDescriptors loads the service descriptors for all services exposed by the
// given GRPC server.
-func LoadServiceDescriptors(s *grpc.Server) (map[string]*desc.ServiceDescriptor, error) {
+func LoadServiceDescriptors(s GRPCServer) (map[string]*desc.ServiceDescriptor, error) {
descs := map[string]*desc.ServiceDescriptor{}
for name, info := range s.GetServiceInfo() {
file, ok := info.Metadata.(string)
diff --git a/vendor/github.com/jhump/protoreflect/internal/standard_files.go b/vendor/github.com/jhump/protoreflect/internal/standard_files.go
index 4a8b47a..777c3a4 100644
--- a/vendor/github.com/jhump/protoreflect/internal/standard_files.go
+++ b/vendor/github.com/jhump/protoreflect/internal/standard_files.go
@@ -9,7 +9,7 @@
"io/ioutil"
"github.com/golang/protobuf/proto"
- dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "google.golang.org/protobuf/types/descriptorpb"
)
// TODO: replace this alias configuration with desc.RegisterImportPath?
@@ -68,7 +68,7 @@
// name cannot be loaded but is a known standard name, an alias will be tried,
// so the standard files can be loaded even if linked against older "known bad"
// versions of packages.
-func LoadFileDescriptor(file string) (*dpb.FileDescriptorProto, error) {
+func LoadFileDescriptor(file string) (*descriptorpb.FileDescriptorProto, error) {
fdb := proto.FileDescriptor(file)
aliased := false
if fdb == nil {
@@ -102,12 +102,12 @@
// Registered file descriptors are first "proto encoded" (e.g. binary format
// for the descriptor protos) and then gzipped. So this function gunzips and
// then unmarshals into a descriptor proto.
-func DecodeFileDescriptor(element string, fdb []byte) (*dpb.FileDescriptorProto, error) {
+func DecodeFileDescriptor(element string, fdb []byte) (*descriptorpb.FileDescriptorProto, error) {
raw, err := decompress(fdb)
if err != nil {
return nil, fmt.Errorf("failed to decompress %q descriptor: %v", element, err)
}
- fd := dpb.FileDescriptorProto{}
+ fd := descriptorpb.FileDescriptorProto{}
if err := proto.Unmarshal(raw, &fd); err != nil {
return nil, fmt.Errorf("bad descriptor for %q: %v", element, err)
}
diff --git a/vendor/github.com/jhump/protoreflect/internal/unrecognized.go b/vendor/github.com/jhump/protoreflect/internal/unrecognized.go
index c903d4b..25376c7 100644
--- a/vendor/github.com/jhump/protoreflect/internal/unrecognized.go
+++ b/vendor/github.com/jhump/protoreflect/internal/unrecognized.go
@@ -1,86 +1,20 @@
package internal
import (
- "reflect"
-
"github.com/golang/protobuf/proto"
)
-var typeOfBytes = reflect.TypeOf([]byte(nil))
-
// GetUnrecognized fetches the bytes of unrecognized fields for the given message.
func GetUnrecognized(msg proto.Message) []byte {
- val := reflect.Indirect(reflect.ValueOf(msg))
- u := val.FieldByName("XXX_unrecognized")
- if u.IsValid() && u.Type() == typeOfBytes {
- return u.Interface().([]byte)
- }
-
- // Fallback to reflection for API v2 messages
- get, _, _, ok := unrecognizedGetSetMethods(val)
- if !ok {
- return nil
- }
-
- return get.Call([]reflect.Value(nil))[0].Convert(typeOfBytes).Interface().([]byte)
+ return proto.MessageReflect(msg).GetUnknown()
}
// SetUnrecognized adds the given bytes to the unrecognized fields for the given message.
func SetUnrecognized(msg proto.Message, data []byte) {
- val := reflect.Indirect(reflect.ValueOf(msg))
- u := val.FieldByName("XXX_unrecognized")
- if u.IsValid() && u.Type() == typeOfBytes {
- // Just store the bytes in the unrecognized field
- ub := u.Interface().([]byte)
- ub = append(ub, data...)
- u.Set(reflect.ValueOf(ub))
- return
- }
-
- // Fallback to reflection for API v2 messages
- get, set, argType, ok := unrecognizedGetSetMethods(val)
- if !ok {
- return
- }
-
- existing := get.Call([]reflect.Value(nil))[0].Convert(typeOfBytes).Interface().([]byte)
+ refl := proto.MessageReflect(msg)
+ existing := refl.GetUnknown()
if len(existing) > 0 {
data = append(existing, data...)
}
- set.Call([]reflect.Value{reflect.ValueOf(data).Convert(argType)})
-}
-
-func unrecognizedGetSetMethods(val reflect.Value) (get reflect.Value, set reflect.Value, argType reflect.Type, ok bool) {
- // val could be an APIv2 message. We use reflection to interact with
- // this message so that we don't have a hard dependency on the new
- // version of the protobuf package.
- refMethod := val.MethodByName("ProtoReflect")
- if !refMethod.IsValid() {
- if val.CanAddr() {
- refMethod = val.Addr().MethodByName("ProtoReflect")
- }
- if !refMethod.IsValid() {
- return
- }
- }
- refType := refMethod.Type()
- if refType.NumIn() != 0 || refType.NumOut() != 1 {
- return
- }
- ref := refMethod.Call([]reflect.Value(nil))
- getMethod, setMethod := ref[0].MethodByName("GetUnknown"), ref[0].MethodByName("SetUnknown")
- if !getMethod.IsValid() || !setMethod.IsValid() {
- return
- }
- getType := getMethod.Type()
- setType := setMethod.Type()
- if getType.NumIn() != 0 || getType.NumOut() != 1 || setType.NumIn() != 1 || setType.NumOut() != 0 {
- return
- }
- arg := setType.In(0)
- if !arg.ConvertibleTo(typeOfBytes) || getType.Out(0) != arg {
- return
- }
-
- return getMethod, setMethod, arg, true
+ refl.SetUnknown(data)
}