[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 = &registry{}
+
+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)
 }