reflect/protoreflect: add Descriptor specific methods
Added methods:
Enum.Descriptor
Message.Descriptor
EnumType.Descriptor
MessageType.Descriptor
ExtensionType.Descriptor
Message.New
All functionality is switched over to use those methods instead of
implicitly relying on the fact that {Enum,Message}Type implicitly
implement the associated descriptor interface.
This CL does not yet remove {Enum,Message}.Type or prevent
{Enum,Message,Extension}Type from implementating a descriptor.
That is a subsequent CL.
The Message.New method is also added to replace functionality
that will be lost when the Type methods are removed.
Change-Id: I7fefde1673bbd40bfdac489aca05cec9a6c98eb1
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/174918
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/internal/fileinit/desc.go b/internal/fileinit/desc.go
index 1665b30..0e9ef53 100644
--- a/internal/fileinit/desc.go
+++ b/internal/fileinit/desc.go
@@ -302,6 +302,7 @@
}
)
+func (ed *enumDesc) Descriptor() pref.EnumDescriptor { return ed }
func (ed *enumDesc) GoType() reflect.Type { return ed.lazyInit().typ }
func (ed *enumDesc) New(n pref.EnumNumber) pref.Enum { return ed.lazyInit().new(n) }
func (ed *enumDesc) Options() pref.ProtoMessage {
@@ -420,10 +421,11 @@
}
return messageDescriptor{mb}
}
-func (mt messageType) GoType() reflect.Type { return mt.lazyInit().typ }
-func (mt messageType) New() pref.Message { return mt.lazyInit().new() }
-func (mt messageType) Options() pref.ProtoMessage { return mt.options() }
-func (md messageDescriptor) Options() pref.ProtoMessage { return md.options() }
+func (mt messageType) Descriptor() pref.MessageDescriptor { return messageDescriptor{mt.messageDesc} }
+func (mt messageType) GoType() reflect.Type { return mt.lazyInit().typ }
+func (mt messageType) New() pref.Message { return mt.lazyInit().new() }
+func (mt messageType) Options() pref.ProtoMessage { return mt.options() }
+func (md messageDescriptor) Options() pref.ProtoMessage { return md.options() }
func (fd *fieldDesc) Options() pref.ProtoMessage {
return unmarshalOptions(descopts.Field, fd.options)
@@ -482,12 +484,13 @@
jsonName string
isPacked bool
defVal defaultValue
- enumType pref.EnumType
- messageType pref.MessageType
+ enumType pref.EnumDescriptor
+ messageType pref.MessageDescriptor
options []byte
}
)
+func (xd *extensionDesc) Descriptor() pref.ExtensionDescriptor { return xd }
func (xd *extensionDesc) GoType() reflect.Type { return xd.lazyInit().typ }
func (xd *extensionDesc) New() pref.Value { return xd.lazyInit().new() }
func (xd *extensionDesc) ValueOf(v interface{}) pref.Value { return xd.lazyInit().valueOf(v) }
diff --git a/internal/fileinit/desc_lazy.go b/internal/fileinit/desc_lazy.go
index be3ebeb..7382d80 100644
--- a/internal/fileinit/desc_lazy.go
+++ b/internal/fileinit/desc_lazy.go
@@ -116,6 +116,7 @@
case pref.Optional:
switch xd.lazy.kind {
case pref.EnumKind:
+ et := pimpl.Export{}.EnumTypeOf(reflect.Zero(typ).Interface())
xd.lazy.typ = typ
xd.lazy.new = func() pref.Value {
return xd.lazy.defVal.get()
@@ -125,12 +126,13 @@
return pref.ValueOf(ev.Number())
}
xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
- return xd.lazy.enumType.New(pv.Enum())
+ return et.New(pv.Enum())
}
case pref.MessageKind, pref.GroupKind:
+ mt := pimpl.Export{}.MessageTypeOf(reflect.Zero(typ).Interface())
xd.lazy.typ = typ
xd.lazy.new = func() pref.Value {
- return pref.ValueOf(xd.lazy.messageType.New())
+ return pref.ValueOf(mt.New())
}
xd.lazy.valueOf = func(v interface{}) pref.Value {
mv := v.(pref.ProtoMessage).ProtoReflect()
@@ -171,9 +173,9 @@
// Resolve extension field dependency.
switch xd.lazy.kind {
case pref.EnumKind:
- xd.lazy.enumType = file.popEnumDependency().(pref.EnumType)
+ xd.lazy.enumType = file.popEnumDependency()
case pref.MessageKind, pref.GroupKind:
- xd.lazy.messageType = file.popMessageDependency().(pref.MessageType)
+ xd.lazy.messageType = file.popMessageDependency()
}
xd.lazy.defVal.lazyInit(xd.lazy.kind, file.enumValuesOf(xd.lazy.enumType))
}
@@ -241,7 +243,7 @@
if depIdx < len(fd.allEnums)+len(fd.allMessages) {
return &fd.allEnums[depIdx]
} else {
- return pimpl.Export{}.EnumTypeOf(fd.GoTypes[depIdx])
+ return pimpl.Export{}.EnumDescriptorOf(fd.GoTypes[depIdx])
}
}
@@ -250,7 +252,7 @@
if depIdx < len(fd.allEnums)+len(fd.allMessages) {
return fd.allMessages[depIdx-len(fd.allEnums)].asDesc()
} else {
- return pimpl.Export{}.MessageTypeOf(fd.GoTypes[depIdx])
+ return pimpl.Export{}.MessageDescriptorOf(fd.GoTypes[depIdx])
}
}
diff --git a/internal/fileinit/fileinit_test.go b/internal/fileinit/fileinit_test.go
index 213289b..ac1c5e2 100644
--- a/internal/fileinit/fileinit_test.go
+++ b/internal/fileinit/fileinit_test.go
@@ -81,10 +81,10 @@
// visitFields calls f for every field set in m and its children.
func visitFields(m protoreflect.Message, f func(protoreflect.FieldDescriptor)) {
- typ := m.Type()
+ fieldDescs := m.Descriptor().Fields()
k := m.KnownFields()
k.Range(func(num protoreflect.FieldNumber, value protoreflect.Value) bool {
- field := typ.Fields().ByNumber(num)
+ field := fieldDescs.ByNumber(num)
f(field)
switch field.Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind:
diff --git a/internal/impl/export.go b/internal/impl/export.go
index 5dae010..0b53d78 100644
--- a/internal/impl/export.go
+++ b/internal/impl/export.go
@@ -5,10 +5,10 @@
package impl
import (
+ "reflect"
"strconv"
"github.com/golang/protobuf/v2/encoding/textpb"
- ptype "github.com/golang/protobuf/v2/internal/prototype"
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
)
@@ -16,11 +16,12 @@
// functions that we do not want to appear in godoc.
type Export struct{}
+// enum is any enum type generated by protoc-gen-go
+// and must be a named int32 type.
+type enum = interface{}
+
// EnumOf returns the protoreflect.Enum interface over e.
-// If e already implements proto.Enum, then it directly calls the
-// ProtoReflect method, otherwise it wraps the v1 enum to implement
-// the v2 reflective interface.
-func (Export) EnumOf(e interface{}) pref.Enum {
+func (Export) EnumOf(e enum) pref.Enum {
if ev, ok := e.(pref.Enum); ok {
return ev
}
@@ -28,16 +29,34 @@
}
// EnumTypeOf returns the protoreflect.EnumType for e.
-// If e already implements proto.Enum, then it obtains the type by directly
-// calling the ProtoReflect.Type method, otherwise it derives an enum type
-// from the v1 named int32 type.
-func (Export) EnumTypeOf(e interface{}) pref.EnumType {
+func (Export) EnumTypeOf(e enum) pref.EnumType {
if ev, ok := e.(pref.Enum); ok {
- return ev.Type()
+ return &enumType{ev.Descriptor(), reflect.TypeOf(e)}
}
return legacyWrapper.EnumTypeOf(e)
}
+// TODO: This needs to be centralized in a package.
+type enumType struct {
+ // TODO: Remove me as an embedded field.
+ pref.EnumDescriptor
+ typ reflect.Type // must implement protoreflect.Enum
+}
+
+func (t *enumType) Descriptor() pref.EnumDescriptor { return t.EnumDescriptor }
+func (t *enumType) GoType() reflect.Type { return t.typ }
+func (t *enumType) New(n pref.EnumNumber) pref.Enum {
+ return reflect.ValueOf(n).Convert(t.typ).Interface().(pref.Enum)
+}
+
+// EnumDescriptorOf returns the protoreflect.EnumDescriptor for e.
+func (Export) EnumDescriptorOf(e enum) pref.EnumDescriptor {
+ if ev, ok := e.(pref.Enum); ok {
+ return ev.Descriptor()
+ }
+ return legacyWrapper.EnumDescriptorOf(e)
+}
+
// EnumStringOf returns the enum value as a string, either as the name if
// the number is resolvable, or the number formatted as a string.
func (Export) EnumStringOf(ed pref.EnumDescriptor, n pref.EnumNumber) string {
@@ -48,11 +67,12 @@
return strconv.Itoa(int(n))
}
+// message is any message type generated by protoc-gen-go
+// and must be a pointer to a named struct type.
+type message = interface{}
+
// MessageOf returns the protoreflect.Message interface over m.
-// If m already implements proto.Message, then it directly calls the
-// ProtoReflect method, otherwise it wraps the v1 message to implement
-// the v2 reflective interface.
-func (Export) MessageOf(m interface{}) pref.Message {
+func (Export) MessageOf(m message) pref.Message {
if mv, ok := m.(pref.ProtoMessage); ok {
return mv.ProtoReflect()
}
@@ -60,32 +80,32 @@
}
// MessageTypeOf returns the protoreflect.MessageType for m.
-// If m already implements proto.Message, then it obtains the type by directly
-// calling the ProtoReflect.Type method, otherwise it derives a message type
-// from the v1 message struct.
-func (Export) MessageTypeOf(m interface{}) pref.MessageType {
+func (Export) MessageTypeOf(m message) pref.MessageType {
if mv, ok := m.(pref.ProtoMessage); ok {
- return mv.ProtoReflect().Type()
+ return &messageType{mv.ProtoReflect().Descriptor(), reflect.TypeOf(m)}
}
return legacyWrapper.MessageTypeOf(m)
}
-// ExtensionTypeOf returns a protoreflect.ExtensionType where the type of the
-// field is t. The type t must be provided if the field is an enum or message.
-// If t already implements proto.Enum or proto.Message, then this returns
-// an extension type by directly calling prototype.GoExtension.
-// Otherwise, it derives an extension type by wrapping the enum or message
-// using EnumOf or MessageOf.
-func (Export) ExtensionTypeOf(d pref.ExtensionDescriptor, t interface{}) pref.ExtensionType {
- switch t := t.(type) {
- case nil:
- return ptype.GoExtension(d, nil, nil)
- case pref.Enum:
- return ptype.GoExtension(d, t.Type(), nil)
- case pref.ProtoMessage:
- return ptype.GoExtension(d, nil, t.ProtoReflect().Type())
+// TODO: This needs to be centralized in a package.
+type messageType struct {
+ // TODO: Remove me as an embedded field.
+ pref.MessageDescriptor
+ typ reflect.Type // must implement protoreflect.ProtoMessage
+}
+
+func (t *messageType) Descriptor() pref.MessageDescriptor { return t.MessageDescriptor }
+func (t *messageType) GoType() reflect.Type { return t.typ }
+func (t *messageType) New() pref.Message {
+ return reflect.New(t.typ.Elem()).Interface().(pref.ProtoMessage).ProtoReflect()
+}
+
+// MessageDescriptorOf returns the protoreflect.MessageDescriptor for m.
+func (Export) MessageDescriptorOf(m message) pref.MessageDescriptor {
+ if mv, ok := m.(pref.ProtoMessage); ok {
+ return mv.ProtoReflect().Descriptor()
}
- return legacyWrapper.ExtensionTypeOf(d, t)
+ return legacyWrapper.MessageDescriptorOf(m)
}
// MessageStringOf returns the message value as a string,
diff --git a/internal/impl/legacy_extension.go b/internal/impl/legacy_extension.go
index b82379e..a0ae3f0 100644
--- a/internal/impl/legacy_extension.go
+++ b/internal/impl/legacy_extension.go
@@ -63,7 +63,8 @@
return false
}
t := extensionTypeFromDesc(x.Desc)
- if t.Cardinality() == pref.Repeated {
+ d := t.Descriptor()
+ if d.Cardinality() == pref.Repeated {
return t.ValueOf(x.Value).List().Len() > 0
}
return true
@@ -75,13 +76,14 @@
return pref.Value{}
}
t := extensionTypeFromDesc(x.Desc)
+ d := t.Descriptor()
if x.Value == nil {
// NOTE: x.Value is never nil for Lists since they are always populated
// during ExtensionFieldTypes.Register.
- if t.Kind() == pref.MessageKind || t.Kind() == pref.GroupKind {
+ if d.Kind() == pref.MessageKind || d.Kind() == pref.GroupKind {
return pref.Value{}
}
- return t.Default()
+ return d.Default()
}
return t.ValueOf(x.Value)
}
@@ -102,7 +104,8 @@
return
}
t := extensionTypeFromDesc(x.Desc)
- if t.Cardinality() == pref.Repeated {
+ d := t.Descriptor()
+ if d.Cardinality() == pref.Repeated {
t.ValueOf(x.Value).List().Truncate(0)
return
}
@@ -149,31 +152,33 @@
}
func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
- if p.mi.PBType.FullName() != t.Extendee().FullName() {
+ d := t.Descriptor()
+ if p.mi.PBType.Descriptor().FullName() != d.Extendee().FullName() {
panic("extended type mismatch")
}
- if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
+ if !p.mi.PBType.Descriptor().ExtensionRanges().Has(d.Number()) {
panic("invalid extension field number")
}
- x := p.x.Get(t.Number())
+ x := p.x.Get(d.Number())
if x.Desc != nil {
panic("extension descriptor already registered")
}
x.Desc = extensionDescFromType(t)
- if t.Cardinality() == pref.Repeated {
+ if d.Cardinality() == pref.Repeated {
// If the field is repeated, initialize the entry with an empty list
// so that future Get operations can return a mutable and concrete list.
x.Value = t.InterfaceOf(t.New())
}
- p.x.Set(t.Number(), x)
+ p.x.Set(d.Number(), x)
}
func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
- if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
+ d := t.Descriptor()
+ if !p.mi.PBType.Descriptor().ExtensionRanges().Has(d.Number()) {
return
}
- x := p.x.Get(t.Number())
- if t.Cardinality() == pref.Repeated {
+ x := p.x.Get(d.Number())
+ if d.Cardinality() == pref.Repeated {
// Treat an empty repeated field as unpopulated.
v := reflect.ValueOf(x.Value)
if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
@@ -183,7 +188,7 @@
if x.Value != nil {
panic("value for extension descriptor still populated")
}
- p.x.Clear(t.Number())
+ p.x.Clear(d.Number())
}
func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
diff --git a/internal/impl/legacy_test.go b/internal/impl/legacy_test.go
index afe28d2..28ab672 100644
--- a/internal/impl/legacy_test.go
+++ b/internal/impl/legacy_test.go
@@ -12,18 +12,16 @@
pack "github.com/golang/protobuf/v2/internal/encoding/pack"
pimpl "github.com/golang/protobuf/v2/internal/impl"
+ plegacy "github.com/golang/protobuf/v2/internal/legacy"
pragma "github.com/golang/protobuf/v2/internal/pragma"
ptype "github.com/golang/protobuf/v2/internal/prototype"
scalar "github.com/golang/protobuf/v2/internal/scalar"
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
+ preg "github.com/golang/protobuf/v2/reflect/protoregistry"
piface "github.com/golang/protobuf/v2/runtime/protoiface"
cmp "github.com/google/go-cmp/cmp"
cmpopts "github.com/google/go-cmp/cmp/cmpopts"
- // The legacy package must be imported prior to use of any legacy messages.
- // TODO: Remove this when protoV1 registers these hooks for you.
- plegacy "github.com/golang/protobuf/v2/internal/legacy"
-
proto2_20180125 "github.com/golang/protobuf/v2/internal/testprotos/legacy/proto2.v1.0.0-20180125-92554152"
)
@@ -39,6 +37,11 @@
return []piface.ExtensionRangeV1{{Start: 10, End: 20}, {Start: 40, End: 80}, {Start: 10000, End: 20000}}
}
+func init() {
+ mt := pimpl.Export{}.MessageTypeOf(&legacyTestMessage{})
+ preg.GlobalTypes.Register(mt)
+}
+
func TestLegacyUnknown(t *testing.T) {
rawOf := func(toks ...pack.Token) pref.RawFields {
return pref.RawFields(pack.Message(toks).Marshal())
@@ -174,15 +177,15 @@
if err != nil {
panic(xd)
}
- return pimpl.Export{}.ExtensionTypeOf(xd, v)
+ return plegacy.ExtensionTypeOf(xd, reflect.TypeOf(v))
}
var (
- parentType = pimpl.Export{}.MessageTypeOf((*legacyTestMessage)(nil))
- enumV1Type = pimpl.Export{}.EnumTypeOf(proto2_20180125.Message_ChildEnum(0))
- messageV1Type = pimpl.Export{}.MessageTypeOf((*proto2_20180125.Message_ChildMessage)(nil))
- enumV2Type = enumProto2Type
- messageV2Type = enumMessagesType.PBType
+ parentDesc = pimpl.Export{}.MessageDescriptorOf((*legacyTestMessage)(nil))
+ enumV1Desc = pimpl.Export{}.EnumDescriptorOf(proto2_20180125.Message_ChildEnum(0))
+ messageV1Desc = pimpl.Export{}.MessageDescriptorOf((*proto2_20180125.Message_ChildMessage)(nil))
+ enumV2Desc = enumProto2Type.Descriptor()
+ messageV2Desc = enumMessagesType.PBType.Descriptor()
extensionTypes = []pref.ExtensionType{
mustMakeExtensionType(&ptype.StandaloneExtension{
@@ -191,7 +194,7 @@
Cardinality: pref.Optional,
Kind: pref.BoolKind,
Default: pref.ValueOf(true),
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_int32",
@@ -199,7 +202,7 @@
Cardinality: pref.Optional,
Kind: pref.Int32Kind,
Default: pref.ValueOf(int32(-12345)),
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_uint32",
@@ -207,7 +210,7 @@
Cardinality: pref.Optional,
Kind: pref.Uint32Kind,
Default: pref.ValueOf(uint32(3200)),
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_float",
@@ -215,7 +218,7 @@
Cardinality: pref.Optional,
Kind: pref.FloatKind,
Default: pref.ValueOf(float32(3.14159)),
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_string",
@@ -223,7 +226,7 @@
Cardinality: pref.Optional,
Kind: pref.StringKind,
Default: pref.ValueOf(string("hello, \"world!\"\n")),
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_bytes",
@@ -231,7 +234,7 @@
Cardinality: pref.Optional,
Kind: pref.BytesKind,
Default: pref.ValueOf([]byte("dead\xde\xad\xbe\xefbeef")),
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_enum_v1",
@@ -239,16 +242,16 @@
Cardinality: pref.Optional,
Kind: pref.EnumKind,
Default: pref.ValueOf(pref.EnumNumber(0)),
- EnumType: enumV1Type,
- ExtendedType: parentType,
+ EnumType: enumV1Desc,
+ ExtendedType: parentDesc,
}, proto2_20180125.Message_ChildEnum(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_message_v1",
Number: 10007,
Cardinality: pref.Optional,
Kind: pref.MessageKind,
- MessageType: messageV1Type,
- ExtendedType: parentType,
+ MessageType: messageV1Desc,
+ ExtendedType: parentDesc,
}, (*proto2_20180125.Message_ChildMessage)(nil)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_enum_v2",
@@ -256,90 +259,90 @@
Cardinality: pref.Optional,
Kind: pref.EnumKind,
Default: pref.ValueOf(pref.EnumNumber(57005)),
- EnumType: enumV2Type,
- ExtendedType: parentType,
+ EnumType: enumV2Desc,
+ ExtendedType: parentDesc,
}, EnumProto2(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_message_v2",
Number: 10009,
Cardinality: pref.Optional,
Kind: pref.MessageKind,
- MessageType: messageV2Type,
- ExtendedType: parentType,
+ MessageType: messageV2Desc,
+ ExtendedType: parentDesc,
}, (*EnumMessages)(nil)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_bool",
Number: 10010,
Cardinality: pref.Repeated,
Kind: pref.BoolKind,
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_int32",
Number: 10011,
Cardinality: pref.Repeated,
Kind: pref.Int32Kind,
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_uint32",
Number: 10012,
Cardinality: pref.Repeated,
Kind: pref.Uint32Kind,
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_float",
Number: 10013,
Cardinality: pref.Repeated,
Kind: pref.FloatKind,
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_string",
Number: 10014,
Cardinality: pref.Repeated,
Kind: pref.StringKind,
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_bytes",
Number: 10015,
Cardinality: pref.Repeated,
Kind: pref.BytesKind,
- ExtendedType: parentType,
+ ExtendedType: parentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_enum_v1",
Number: 10016,
Cardinality: pref.Repeated,
Kind: pref.EnumKind,
- EnumType: enumV1Type,
- ExtendedType: parentType,
+ EnumType: enumV1Desc,
+ ExtendedType: parentDesc,
}, proto2_20180125.Message_ChildEnum(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_message_v1",
Number: 10017,
Cardinality: pref.Repeated,
Kind: pref.MessageKind,
- MessageType: messageV1Type,
- ExtendedType: parentType,
+ MessageType: messageV1Desc,
+ ExtendedType: parentDesc,
}, (*proto2_20180125.Message_ChildMessage)(nil)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_enum_v2",
Number: 10018,
Cardinality: pref.Repeated,
Kind: pref.EnumKind,
- EnumType: enumV2Type,
- ExtendedType: parentType,
+ EnumType: enumV2Desc,
+ ExtendedType: parentDesc,
}, EnumProto2(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_message_v2",
Number: 10019,
Cardinality: pref.Repeated,
Kind: pref.MessageKind,
- MessageType: messageV2Type,
- ExtendedType: parentType,
+ MessageType: messageV2Desc,
+ ExtendedType: parentDesc,
}, (*EnumMessages)(nil)),
}
@@ -513,19 +516,21 @@
}
for i, xt := range extensionTypes {
var got interface{}
- if v := fs.Get(xt.Number()); v.IsValid() {
+ num := xt.Descriptor().Number()
+ if v := fs.Get(num); v.IsValid() {
got = xt.InterfaceOf(v)
}
want := defaultValues[i]
if diff := cmp.Diff(want, got, opts); diff != "" {
- t.Errorf("KnownFields.Get(%d) mismatch (-want +got):\n%v", xt.Number(), diff)
+ t.Errorf("KnownFields.Get(%d) mismatch (-want +got):\n%v", num, diff)
}
}
// All fields should be unpopulated.
for _, xt := range extensionTypes {
- if fs.Has(xt.Number()) {
- t.Errorf("KnownFields.Has(%d) = true, want false", xt.Number())
+ num := xt.Descriptor().Number()
+ if fs.Has(num) {
+ t.Errorf("KnownFields.Has(%d) = true, want false", num)
}
}
@@ -557,11 +562,11 @@
&[]*EnumMessages{m2b},
}
for i, xt := range extensionTypes {
- fs.Set(xt.Number(), xt.ValueOf(setValues[i]))
+ fs.Set(xt.Descriptor().Number(), xt.ValueOf(setValues[i]))
}
for i, xt := range extensionTypes[len(extensionTypes)/2:] {
v := extensionTypes[i].ValueOf(setValues[i])
- fs.Get(xt.Number()).List().Append(v)
+ fs.Get(xt.Descriptor().Number()).List().Append(v)
}
// Get the values and check for equality.
@@ -588,10 +593,11 @@
&[]*EnumMessages{m2b, m2a},
}
for i, xt := range extensionTypes {
- got := xt.InterfaceOf(fs.Get(xt.Number()))
+ num := xt.Descriptor().Number()
+ got := xt.InterfaceOf(fs.Get(num))
want := getValues[i]
if diff := cmp.Diff(want, got, opts); diff != "" {
- t.Errorf("KnownFields.Get(%d) mismatch (-want +got):\n%v", xt.Number(), diff)
+ t.Errorf("KnownFields.Get(%d) mismatch (-want +got):\n%v", num, diff)
}
}
@@ -604,13 +610,13 @@
// Clear the field for all extension types.
for _, xt := range extensionTypes[:len(extensionTypes)/2] {
- fs.Clear(xt.Number())
+ fs.Clear(xt.Descriptor().Number())
}
for i, xt := range extensionTypes[len(extensionTypes)/2:] {
if i%2 == 0 {
- fs.Clear(xt.Number())
+ fs.Clear(xt.Descriptor().Number())
} else {
- fs.Get(xt.Number()).List().Truncate(0)
+ fs.Get(xt.Descriptor().Number()).List().Truncate(0)
}
}
if n := fs.Len(); n != 0 {
@@ -661,6 +667,13 @@
}
return out
}),
+ // TODO: Add this when ExtensionType no longer implements
+ // ExtensionDescriptor.
+ /*
+ cmp.Transformer("", func(x pref.ExtensionType) pref.ExtensionDescriptor {
+ return x.Descriptor()
+ }),
+ */
cmp.Transformer("", func(x pref.Descriptor) map[string]interface{} {
out := make(map[string]interface{})
v := reflect.ValueOf(x)
diff --git a/internal/impl/message.go b/internal/impl/message.go
index 8879015..5c2ae28 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -113,8 +113,8 @@
// any discrepancies.
func (mi *MessageType) makeKnownFieldsFunc(si structInfo) {
mi.fields = map[pref.FieldNumber]*fieldInfo{}
- for i := 0; i < mi.PBType.Fields().Len(); i++ {
- fd := mi.PBType.Fields().Get(i)
+ for i := 0; i < mi.PBType.Descriptor().Fields().Len(); i++ {
+ fd := mi.PBType.Descriptor().Fields().Get(i)
fs := si.fieldsByNumber[fd.Number()]
var fi fieldInfo
switch {
@@ -133,8 +133,8 @@
}
mi.oneofs = map[pref.Name]*oneofInfo{}
- for i := 0; i < mi.PBType.Oneofs().Len(); i++ {
- od := mi.PBType.Oneofs().Get(i)
+ for i := 0; i < mi.PBType.Descriptor().Oneofs().Len(); i++ {
+ od := mi.PBType.Descriptor().Oneofs().Get(i)
mi.oneofs[od.Name()] = makeOneofInfo(od, si.oneofsByName[od.Name()], si.oneofWrappersByType)
}
}
@@ -203,9 +203,13 @@
type messageReflectWrapper messageDataType
+// TODO: Remove this.
func (m *messageReflectWrapper) Type() pref.MessageType {
return m.mi.PBType
}
+func (m *messageReflectWrapper) Descriptor() pref.MessageDescriptor {
+ return m.mi.PBType.Descriptor()
+}
func (m *messageReflectWrapper) KnownFields() pref.KnownFields {
m.mi.init()
return (*knownFields)(m)
@@ -214,6 +218,9 @@
m.mi.init()
return m.mi.unknownFields((*messageDataType)(m))
}
+func (m *messageReflectWrapper) New() pref.Message {
+ return m.mi.PBType.New()
+}
func (m *messageReflectWrapper) Interface() pref.ProtoMessage {
if m, ok := m.ProtoUnwrap().(pref.ProtoMessage); ok {
return m
@@ -266,7 +273,7 @@
fi.set(fs.p, v)
return
}
- if fs.mi.PBType.ExtensionRanges().Has(n) {
+ if fs.mi.PBType.Descriptor().ExtensionRanges().Has(n) {
fs.extensionFields().Set(n, v)
return
}
@@ -277,7 +284,7 @@
fi.clear(fs.p)
return
}
- if fs.mi.PBType.ExtensionRanges().Has(n) {
+ if fs.mi.PBType.Descriptor().ExtensionRanges().Has(n) {
fs.extensionFields().Clear(n)
return
}
@@ -302,7 +309,7 @@
if fi := fs.mi.fields[n]; fi != nil {
return fi.newMessage()
}
- if fs.mi.PBType.ExtensionRanges().Has(n) {
+ if fs.mi.PBType.Descriptor().ExtensionRanges().Has(n) {
return fs.extensionFields().NewMessage(n)
}
panic(fmt.Sprintf("invalid field: %d", n))
diff --git a/internal/impl/message_test.go b/internal/impl/message_test.go
index b5a9af2..49e3a0a 100644
--- a/internal/impl/message_test.go
+++ b/internal/impl/message_test.go
@@ -228,13 +228,18 @@
},
)}
+// TODO: Remove this.
func (m *ScalarProto2) Type() pref.MessageType { return scalarProto2Type.PBType }
+func (m *ScalarProto2) Descriptor() pref.MessageDescriptor {
+ return scalarProto2Type.PBType.Descriptor()
+}
func (m *ScalarProto2) KnownFields() pref.KnownFields {
return scalarProto2Type.MessageOf(m).KnownFields()
}
func (m *ScalarProto2) UnknownFields() pref.UnknownFields {
return scalarProto2Type.MessageOf(m).UnknownFields()
}
+func (m *ScalarProto2) New() pref.Message { return new(ScalarProto2) }
func (m *ScalarProto2) Interface() pref.ProtoMessage { return m }
func (m *ScalarProto2) ProtoReflect() pref.Message { return m }
@@ -338,13 +343,18 @@
},
)}
+// TODO: Remove this.
func (m *ScalarProto3) Type() pref.MessageType { return scalarProto3Type.PBType }
+func (m *ScalarProto3) Descriptor() pref.MessageDescriptor {
+ return scalarProto3Type.PBType.Descriptor()
+}
func (m *ScalarProto3) KnownFields() pref.KnownFields {
return scalarProto3Type.MessageOf(m).KnownFields()
}
func (m *ScalarProto3) UnknownFields() pref.UnknownFields {
return scalarProto3Type.MessageOf(m).UnknownFields()
}
+func (m *ScalarProto3) New() pref.Message { return new(ScalarProto3) }
func (m *ScalarProto3) Interface() pref.ProtoMessage { return m }
func (m *ScalarProto3) ProtoReflect() pref.Message { return m }
@@ -464,13 +474,16 @@
},
)}
-func (m *ListScalars) Type() pref.MessageType { return listScalarsType.PBType }
+// TODO: Remove this.
+func (m *ListScalars) Type() pref.MessageType { return listScalarsType.PBType }
+func (m *ListScalars) Descriptor() pref.MessageDescriptor { return listScalarsType.PBType.Descriptor() }
func (m *ListScalars) KnownFields() pref.KnownFields {
return listScalarsType.MessageOf(m).KnownFields()
}
func (m *ListScalars) UnknownFields() pref.UnknownFields {
return listScalarsType.MessageOf(m).UnknownFields()
}
+func (m *ListScalars) New() pref.Message { return new(ListScalars) }
func (m *ListScalars) Interface() pref.ProtoMessage { return m }
func (m *ListScalars) ProtoReflect() pref.Message { return m }
@@ -659,13 +672,16 @@
},
)}
-func (m *MapScalars) Type() pref.MessageType { return mapScalarsType.PBType }
+// TODO: Remove this.
+func (m *MapScalars) Type() pref.MessageType { return mapScalarsType.PBType }
+func (m *MapScalars) Descriptor() pref.MessageDescriptor { return mapScalarsType.PBType.Descriptor() }
func (m *MapScalars) KnownFields() pref.KnownFields {
return mapScalarsType.MessageOf(m).KnownFields()
}
func (m *MapScalars) UnknownFields() pref.UnknownFields {
return mapScalarsType.MessageOf(m).UnknownFields()
}
+func (m *MapScalars) New() pref.Message { return new(MapScalars) }
func (m *MapScalars) Interface() pref.ProtoMessage { return m }
func (m *MapScalars) ProtoReflect() pref.Message { return m }
@@ -821,13 +837,18 @@
},
)}
+// TODO: Remove this.
func (m *OneofScalars) Type() pref.MessageType { return oneofScalarsType.PBType }
+func (m *OneofScalars) Descriptor() pref.MessageDescriptor {
+ return oneofScalarsType.PBType.Descriptor()
+}
func (m *OneofScalars) KnownFields() pref.KnownFields {
return oneofScalarsType.MessageOf(m).KnownFields()
}
func (m *OneofScalars) UnknownFields() pref.UnknownFields {
return oneofScalarsType.MessageOf(m).UnknownFields()
}
+func (m *OneofScalars) New() pref.Message { return new(OneofScalars) }
func (m *OneofScalars) Interface() pref.ProtoMessage { return m }
func (m *OneofScalars) ProtoReflect() pref.Message { return m }
@@ -977,9 +998,11 @@
},
)
-func (e EnumProto2) Enum() *EnumProto2 { return &e }
-func (e EnumProto2) Type() pref.EnumType { return enumProto2Type }
-func (e EnumProto2) Number() pref.EnumNumber { return pref.EnumNumber(e) }
+// TODO: Remove this.
+func (e EnumProto2) Type() pref.EnumType { return enumProto2Type }
+func (e EnumProto2) Descriptor() pref.EnumDescriptor { return enumProto2Type.Descriptor() }
+func (e EnumProto2) Enum() *EnumProto2 { return &e }
+func (e EnumProto2) Number() pref.EnumNumber { return pref.EnumNumber(e) }
type EnumProto3 int32
@@ -994,9 +1017,11 @@
},
)
-func (e EnumProto3) Enum() *EnumProto3 { return &e }
-func (e EnumProto3) Type() pref.EnumType { return enumProto3Type }
-func (e EnumProto3) Number() pref.EnumNumber { return pref.EnumNumber(e) }
+// TODO: Remove this.
+func (e EnumProto3) Type() pref.EnumType { return enumProto3Type }
+func (e EnumProto3) Descriptor() pref.EnumDescriptor { return enumProto3Type.Descriptor() }
+func (e EnumProto3) Enum() *EnumProto3 { return &e }
+func (e EnumProto3) Number() pref.EnumNumber { return pref.EnumNumber(e) }
type EnumMessages struct {
EnumP2 *EnumProto2 `protobuf:"1"`
@@ -1015,18 +1040,18 @@
Syntax: pref.Proto2,
FullName: "EnumMessages",
Fields: []ptype.Field{
- {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BEEF"), EnumType: enumProto2Type},
- {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BRAVO"), EnumType: enumProto3Type},
- {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: pimpl.Export{}.MessageOf(new(proto2_20180125.Message)).Type()},
+ {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BEEF"), EnumType: enumProto2Type.Descriptor()},
+ {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BRAVO"), EnumType: enumProto3Type.Descriptor()},
+ {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: pimpl.Export{}.MessageDescriptorOf(new(proto2_20180125.Message))},
{Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: ptype.PlaceholderMessage("EnumMessages")},
- {Name: "f5", Number: 5, Cardinality: pref.Repeated, Kind: pref.EnumKind, EnumType: enumProto2Type},
- {Name: "f6", Number: 6, Cardinality: pref.Repeated, Kind: pref.MessageKind, MessageType: scalarProto2Type.PBType},
+ {Name: "f5", Number: 5, Cardinality: pref.Repeated, Kind: pref.EnumKind, EnumType: enumProto2Type.Descriptor()},
+ {Name: "f6", Number: 6, Cardinality: pref.Repeated, Kind: pref.MessageKind, MessageType: scalarProto2Type.PBType.Descriptor()},
{Name: "f7", Number: 7, Cardinality: pref.Repeated, Kind: pref.MessageKind, MessageType: enumMapDesc},
{Name: "f8", Number: 8, Cardinality: pref.Repeated, Kind: pref.MessageKind, MessageType: messageMapDesc},
- {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BEEF"), OneofName: "union", EnumType: enumProto2Type},
- {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BRAVO"), OneofName: "union", EnumType: enumProto3Type},
- {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.MessageKind, OneofName: "union", MessageType: scalarProto2Type.PBType},
- {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.MessageKind, OneofName: "union", MessageType: scalarProto3Type.PBType},
+ {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BEEF"), OneofName: "union", EnumType: enumProto2Type.Descriptor()},
+ {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.EnumKind, Default: V("BRAVO"), OneofName: "union", EnumType: enumProto3Type.Descriptor()},
+ {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.MessageKind, OneofName: "union", MessageType: scalarProto2Type.PBType.Descriptor()},
+ {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.MessageKind, OneofName: "union", MessageType: scalarProto3Type.PBType.Descriptor()},
},
Oneofs: []ptype.Oneof{{Name: "union"}},
}),
@@ -1040,7 +1065,7 @@
FullName: "EnumMessages.F7Entry",
Fields: []ptype.Field{
{Name: "key", Number: 1, Cardinality: pref.Optional, Kind: pref.StringKind},
- {Name: "value", Number: 2, Cardinality: pref.Optional, Kind: pref.EnumKind, EnumType: enumProto3Type},
+ {Name: "value", Number: 2, Cardinality: pref.Optional, Kind: pref.EnumKind, EnumType: enumProto3Type.Descriptor()},
},
Options: &descriptorpb.MessageOptions{MapEntry: scalar.Bool(true)},
IsMapEntry: true,
@@ -1051,19 +1076,24 @@
FullName: "EnumMessages.F8Entry",
Fields: []ptype.Field{
{Name: "key", Number: 1, Cardinality: pref.Optional, Kind: pref.StringKind},
- {Name: "value", Number: 2, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: scalarProto3Type.PBType},
+ {Name: "value", Number: 2, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: scalarProto3Type.PBType.Descriptor()},
},
Options: &descriptorpb.MessageOptions{MapEntry: scalar.Bool(true)},
IsMapEntry: true,
})
+// TODO: Remove this.
func (m *EnumMessages) Type() pref.MessageType { return enumMessagesType.PBType }
+func (m *EnumMessages) Descriptor() pref.MessageDescriptor {
+ return enumMessagesType.PBType.Descriptor()
+}
func (m *EnumMessages) KnownFields() pref.KnownFields {
return enumMessagesType.MessageOf(m).KnownFields()
}
func (m *EnumMessages) UnknownFields() pref.UnknownFields {
return enumMessagesType.MessageOf(m).UnknownFields()
}
+func (m *EnumMessages) New() pref.Message { return new(EnumMessages) }
func (m *EnumMessages) Interface() pref.ProtoMessage { return m }
func (m *EnumMessages) ProtoReflect() pref.Message { return m }
diff --git a/internal/legacy/enum.go b/internal/legacy/enum.go
index 0ee397f..2a57b0b 100644
--- a/internal/legacy/enum.go
+++ b/internal/legacy/enum.go
@@ -55,12 +55,16 @@
goTyp reflect.Type
}
-func (e *enumWrapper) Number() pref.EnumNumber {
- return e.num
-}
+// TODO: Remove this.
func (e *enumWrapper) Type() pref.EnumType {
return e.pbTyp
}
+func (e *enumWrapper) Descriptor() pref.EnumDescriptor {
+ return e.pbTyp.Descriptor()
+}
+func (e *enumWrapper) Number() pref.EnumNumber {
+ return e.num
+}
func (e *enumWrapper) ProtoReflect() pref.Enum {
return e
}
diff --git a/internal/legacy/export.go b/internal/legacy/export.go
index 054108a..fa4375a 100644
--- a/internal/legacy/export.go
+++ b/internal/legacy/export.go
@@ -25,6 +25,10 @@
return loadEnumType(reflect.TypeOf(e))
}
+func (Export) EnumDescriptorOf(e interface{}) pref.EnumDescriptor {
+ return LoadEnumDesc(reflect.TypeOf(e))
+}
+
func (Export) MessageOf(m interface{}) pvalue.LegacyMessage {
return wrapMessage(reflect.ValueOf(m)).ProtoReflect().(pvalue.LegacyMessage)
}
@@ -33,8 +37,8 @@
return loadMessageType(reflect.TypeOf(m)).PBType
}
-func (Export) ExtensionTypeOf(d pref.ExtensionDescriptor, t interface{}) pref.ExtensionType {
- return extensionTypeOf(d, reflect.TypeOf(t))
+func (Export) MessageDescriptorOf(m interface{}) pref.MessageDescriptor {
+ return LoadMessageDesc(reflect.TypeOf(m))
}
func (Export) ExtensionDescFromType(t pref.ExtensionType) *piface.ExtensionDescV1 {
diff --git a/internal/legacy/extension.go b/internal/legacy/extension.go
index 94ad7b7..e9c8bb7 100644
--- a/internal/legacy/extension.go
+++ b/internal/legacy/extension.go
@@ -15,6 +15,7 @@
pfmt "github.com/golang/protobuf/v2/internal/typefmt"
pvalue "github.com/golang/protobuf/v2/internal/value"
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
+ preg "github.com/golang/protobuf/v2/reflect/protoregistry"
piface "github.com/golang/protobuf/v2/runtime/protoiface"
)
@@ -46,25 +47,25 @@
// extensionDescFromType converts a v2 protoreflect.ExtensionType to a
// protoiface.ExtensionDescV1. The returned ExtensionDesc must not be mutated.
-func extensionDescFromType(t pref.ExtensionType) *piface.ExtensionDescV1 {
+func extensionDescFromType(xt pref.ExtensionType) *piface.ExtensionDescV1 {
// Fast-path: check whether an extension desc is already nested within.
- if t, ok := t.(interface {
+ if xt, ok := xt.(interface {
ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
}); ok {
- if d := t.ProtoLegacyExtensionDesc(); d != nil {
+ if d := xt.ProtoLegacyExtensionDesc(); d != nil {
return d
}
}
// Fast-path: check the cache for whether this ExtensionType has already
// been converted to a legacy descriptor.
- if d, ok := extensionDescCache.Load(t); ok {
+ if d, ok := extensionDescCache.Load(xt); ok {
return d.(*piface.ExtensionDescV1)
}
// Determine the parent type if possible.
var parent piface.MessageV1
- if mt, ok := t.Extendee().(pref.MessageType); ok {
+ if mt, _ := preg.GlobalTypes.FindMessageByName(xt.Descriptor().Extendee().FullName()); mt != nil {
// Create a new parent message and unwrap it if possible.
mv := mt.New().Interface()
t := reflect.TypeOf(mv)
@@ -81,7 +82,7 @@
// Determine the v1 extension type, which is unfortunately not the same as
// the v2 ExtensionType.GoType.
- extType := t.GoType()
+ extType := xt.GoType()
switch extType.Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
extType = reflect.PtrTo(extType) // T -> *T for singular scalar fields
@@ -94,23 +95,21 @@
// Reconstruct the legacy enum full name, which is an odd mixture of the
// proto package name with the Go type name.
var enumName string
- if t.Kind() == pref.EnumKind {
+ if xt.Descriptor().Kind() == pref.EnumKind {
// Derive Go type name.
- // For legacy enums, unwrap the wrapper to get the underlying Go type.
- et := t.Enum().(pref.EnumType)
- var ev interface{} = et.New(0)
- if u, ok := ev.(pvalue.Unwrapper); ok {
- ev = u.ProtoUnwrap()
+ t := extType
+ if t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice {
+ t = t.Elem()
}
- enumName = reflect.TypeOf(ev).Name()
+ enumName = t.Name()
// Derive the proto package name.
// For legacy enums, obtain the proto package from the raw descriptor.
var protoPkg string
- if fd := parentFileDescriptor(et); fd != nil {
+ if fd := parentFileDescriptor(xt.Descriptor().Enum()); fd != nil {
protoPkg = string(fd.Package())
}
- if ed, ok := ev.(enumV1); ok && protoPkg == "" {
+ if ed, ok := reflect.Zero(t).Interface().(enumV1); ok && protoPkg == "" {
b, _ := ed.EnumDescriptor()
protoPkg = loadFileDesc(b).GetPackage()
}
@@ -122,21 +121,21 @@
// Derive the proto file that the extension was declared within.
var filename string
- if fd := parentFileDescriptor(t); fd != nil {
+ if fd := parentFileDescriptor(xt.Descriptor()); fd != nil {
filename = fd.Path()
}
// Construct and return a ExtensionDescV1.
d := &piface.ExtensionDescV1{
- Type: t,
+ Type: xt,
ExtendedType: parent,
ExtensionType: reflect.Zero(extType).Interface(),
- Field: int32(t.Number()),
- Name: string(t.FullName()),
- Tag: ptag.Marshal(t, enumName),
+ Field: int32(xt.Descriptor().Number()),
+ Name: string(xt.Descriptor().FullName()),
+ Tag: ptag.Marshal(xt.Descriptor(), enumName),
Filename: filename,
}
- if d, ok := extensionDescCache.LoadOrStore(t, d); ok {
+ if d, ok := extensionDescCache.LoadOrStore(xt, d); ok {
return d.(*piface.ExtensionDescV1)
}
return d
@@ -169,7 +168,15 @@
f := ptag.Unmarshal(d.Tag, t)
// Construct a v2 ExtensionType.
+ var ed pref.EnumDescriptor
+ var md pref.MessageDescriptor
conv := pvalue.NewLegacyConverter(t, f.Kind, Export{})
+ if conv.EnumType != nil {
+ ed = conv.EnumType.Descriptor()
+ }
+ if conv.MessageType != nil {
+ md = conv.MessageType.Descriptor()
+ }
xd, err := ptype.NewExtension(&ptype.StandaloneExtension{
FullName: pref.FullName(d.Name),
Number: pref.FieldNumber(d.Field),
@@ -177,19 +184,14 @@
Kind: f.Kind,
Default: f.Default,
Options: f.Options,
- EnumType: conv.EnumType,
- MessageType: conv.MessageType,
- ExtendedType: pimpl.Export{}.MessageTypeOf(d.ExtendedType),
+ EnumType: ed,
+ MessageType: md,
+ ExtendedType: pimpl.Export{}.MessageDescriptorOf(d.ExtendedType),
})
if err != nil {
panic(err)
}
- var zv interface{}
- switch xd.Kind() {
- case pref.EnumKind, pref.MessageKind, pref.GroupKind:
- zv = reflect.Zero(t).Interface()
- }
- xt := pimpl.Export{}.ExtensionTypeOf(xd, zv)
+ xt := ExtensionTypeOf(xd, t)
// Cache the conversion for both directions.
extensionDescCache.LoadOrStore(xt, d)
@@ -199,17 +201,26 @@
return xt
}
-// extensionTypeOf returns a protoreflect.ExtensionType where the GoType
-// is the underlying v1 Go type instead of the wrapper types used to present
-// v1 Go types as if they satisfied the v2 API.
+// ExtensionTypeOf returns a protoreflect.ExtensionType where the type of the
+// field is t. The type t must be provided if the field is an enum or message.
//
-// This function is only valid if xd.Kind is an enum or message.
-func extensionTypeOf(xd pref.ExtensionDescriptor, t reflect.Type) pref.ExtensionType {
- // Step 1: Create an ExtensionType where GoType is the wrapper type.
+// This is exported for testing purposes.
+func ExtensionTypeOf(xd pref.ExtensionDescriptor, t reflect.Type) pref.ExtensionType {
+ // Extension types for non-enums and non-messages are simple.
+ switch xd.Kind() {
+ case pref.EnumKind, pref.MessageKind, pref.GroupKind:
+ default:
+ return ptype.GoExtension(xd, nil, nil)
+ }
+
+ // Create an ExtensionType where GoType is the wrapper type.
conv := pvalue.NewLegacyConverter(t, xd.Kind(), Export{})
xt := ptype.GoExtension(xd, conv.EnumType, conv.MessageType)
+ if !conv.IsLegacy {
+ return xt
+ }
- // Step 2: Wrap ExtensionType such that GoType presents the legacy Go type.
+ // Wrap ExtensionType such that GoType presents the legacy Go type.
xt2 := &extensionType{ExtensionType: xt}
if xd.Cardinality() != pref.Repeated {
xt2.typ = t
@@ -264,4 +275,4 @@
func (x *extensionType) New() pref.Value { return x.new() }
func (x *extensionType) ValueOf(v interface{}) pref.Value { return x.valueOf(v) }
func (x *extensionType) InterfaceOf(v pref.Value) interface{} { return x.interfaceOf(v) }
-func (x *extensionType) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, x) }
+func (x *extensionType) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, x.Descriptor()) }
diff --git a/internal/legacy/extension_test.go b/internal/legacy/extension_test.go
index 630c158..cdba627 100644
--- a/internal/legacy/extension_test.go
+++ b/internal/legacy/extension_test.go
@@ -5,17 +5,15 @@
package legacy_test
import (
+ "reflect"
"testing"
pimpl "github.com/golang/protobuf/v2/internal/impl"
+ plegacy "github.com/golang/protobuf/v2/internal/legacy"
ptype "github.com/golang/protobuf/v2/internal/prototype"
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
piface "github.com/golang/protobuf/v2/runtime/protoiface"
- // The legacy package must be imported prior to use of any legacy messages.
- // TODO: Remove this when protoV1 registers these hooks for you.
- plegacy "github.com/golang/protobuf/v2/internal/legacy"
-
proto2_20180125 "github.com/golang/protobuf/v2/internal/testprotos/legacy/proto2.v1.0.0-20180125-92554152"
)
@@ -34,22 +32,22 @@
func mustMakeExtensionType(x *ptype.StandaloneExtension, v interface{}) pref.ExtensionType {
xd, err := ptype.NewExtension(x)
if err != nil {
- panic(xd)
+ panic(err)
}
- return pimpl.Export{}.ExtensionTypeOf(xd, v)
+ return plegacy.ExtensionTypeOf(xd, reflect.TypeOf(v))
}
var (
- parentType = pimpl.Export{}.MessageTypeOf((*legacyTestMessage)(nil))
- messageV1Type = pimpl.Export{}.MessageTypeOf((*proto2_20180125.Message_ChildMessage)(nil))
+ parentDesc = pimpl.Export{}.MessageDescriptorOf((*legacyTestMessage)(nil))
+ messageV1Desc = pimpl.Export{}.MessageDescriptorOf((*proto2_20180125.Message_ChildMessage)(nil))
wantType = mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_message_v1",
Number: 10007,
Cardinality: pref.Optional,
Kind: pref.MessageKind,
- MessageType: messageV1Type,
- ExtendedType: parentType,
+ MessageType: messageV1Desc,
+ ExtendedType: parentDesc,
}, (*proto2_20180125.Message_ChildMessage)(nil))
wantDesc = &piface.ExtensionDescV1{
ExtendedType: (*legacyTestMessage)(nil),
diff --git a/internal/legacy/legacy_test.go b/internal/legacy/legacy_test.go
index 3bac3b3..9bb484c 100644
--- a/internal/legacy/legacy_test.go
+++ b/internal/legacy/legacy_test.go
@@ -31,7 +31,7 @@
const numParallel = 5
var messageATypes [numParallel]protoreflect.MessageType
var messageBTypes [numParallel]protoreflect.MessageType
- var enumTypes [numParallel]protoreflect.EnumType
+ var enumDescs [numParallel]protoreflect.EnumDescriptor
// Concurrently load message and enum types.
var wg sync.WaitGroup
@@ -48,31 +48,30 @@
}()
go func() {
defer wg.Done()
- enumTypes[i] = Export{}.EnumTypeOf(Enum(0))
+ enumDescs[i] = Export{}.EnumDescriptorOf(Enum(0))
}()
}
wg.Wait()
var (
wantMTA = messageATypes[0]
- wantMDA = messageATypes[0].Fields().ByNumber(1).Message()
+ wantMDA = messageATypes[0].Descriptor().Fields().ByNumber(1).Message()
wantMTB = messageBTypes[0]
- wantMDB = messageBTypes[0].Fields().ByNumber(2).Message()
- wantET = enumTypes[0]
- wantED = messageATypes[0].Fields().ByNumber(3).Enum()
+ wantMDB = messageBTypes[0].Descriptor().Fields().ByNumber(2).Message()
+ wantED = messageATypes[0].Descriptor().Fields().ByNumber(3).Enum()
)
for _, gotMT := range messageATypes[1:] {
if gotMT != wantMTA {
t.Error("MessageType(MessageA) mismatch")
}
- if gotMDA := gotMT.Fields().ByNumber(1).Message(); gotMDA != wantMDA {
+ if gotMDA := gotMT.Descriptor().Fields().ByNumber(1).Message(); gotMDA != wantMDA {
t.Error("MessageDescriptor(MessageA) mismatch")
}
- if gotMDB := gotMT.Fields().ByNumber(2).Message(); gotMDB != wantMDB {
+ if gotMDB := gotMT.Descriptor().Fields().ByNumber(2).Message(); gotMDB != wantMDB {
t.Error("MessageDescriptor(MessageB) mismatch")
}
- if gotED := gotMT.Fields().ByNumber(3).Enum(); gotED != wantED {
+ if gotED := gotMT.Descriptor().Fields().ByNumber(3).Enum(); gotED != wantED {
t.Error("EnumDescriptor(Enum) mismatch")
}
}
@@ -80,18 +79,18 @@
if gotMT != wantMTB {
t.Error("MessageType(MessageB) mismatch")
}
- if gotMDA := gotMT.Fields().ByNumber(1).Message(); gotMDA != wantMDA {
+ if gotMDA := gotMT.Descriptor().Fields().ByNumber(1).Message(); gotMDA != wantMDA {
t.Error("MessageDescriptor(MessageA) mismatch")
}
- if gotMDB := gotMT.Fields().ByNumber(2).Message(); gotMDB != wantMDB {
+ if gotMDB := gotMT.Descriptor().Fields().ByNumber(2).Message(); gotMDB != wantMDB {
t.Error("MessageDescriptor(MessageB) mismatch")
}
- if gotED := gotMT.Fields().ByNumber(3).Enum(); gotED != wantED {
+ if gotED := gotMT.Descriptor().Fields().ByNumber(3).Enum(); gotED != wantED {
t.Error("EnumDescriptor(Enum) mismatch")
}
}
- for _, gotET := range enumTypes[1:] {
- if gotET != wantET {
+ for _, gotED := range enumDescs[1:] {
+ if gotED != wantED {
t.Error("EnumType(Enum) mismatch")
}
}
diff --git a/internal/legacy/message.go b/internal/legacy/message.go
index 01bc053..ee242ca 100644
--- a/internal/legacy/message.go
+++ b/internal/legacy/message.go
@@ -232,14 +232,14 @@
// Populate EnumType and MessageType.
if f.EnumType == nil && f.Kind == pref.EnumKind {
if ev, ok := reflect.Zero(t).Interface().(pref.Enum); ok {
- f.EnumType = ev.Type()
+ f.EnumType = ev.Descriptor()
} else {
f.EnumType = LoadEnumDesc(t)
}
}
if f.MessageType == nil && (f.Kind == pref.MessageKind || f.Kind == pref.GroupKind) {
if mv, ok := reflect.Zero(t).Interface().(pref.ProtoMessage); ok {
- f.MessageType = mv.ProtoReflect().Type()
+ f.MessageType = mv.ProtoReflect().Descriptor()
} else if t.Kind() == reflect.Map {
m := &ptype.StandaloneMessage{
Syntax: parent.Syntax,
diff --git a/internal/prototype/go_type.go b/internal/prototype/go_type.go
index 8dba537..6c88a7c 100644
--- a/internal/prototype/go_type.go
+++ b/internal/prototype/go_type.go
@@ -31,6 +31,9 @@
typ reflect.Type
}
+func (t *goEnum) Descriptor() protoreflect.EnumDescriptor {
+ return t.EnumDescriptor
+}
func (t *goEnum) GoType() reflect.Type {
t.New(0) // initialize t.typ
return t.typ
@@ -66,6 +69,9 @@
typ reflect.Type
}
+func (t *goMessage) Descriptor() protoreflect.MessageDescriptor {
+ return t.MessageDescriptor
+}
func (t *goMessage) GoType() reflect.Type {
t.New() // initialize t.typ
return t.typ
@@ -162,11 +168,20 @@
interfaceOf func(v protoreflect.Value) interface{}
}
+func (t *goExtension) Descriptor() protoreflect.ExtensionDescriptor {
+ return t.ExtensionDescriptor
+}
func (t *goExtension) EnumType() protoreflect.EnumDescriptor {
- return t.enumType
+ if t.enumType == nil {
+ return nil
+ }
+ return t.enumType.Descriptor()
}
func (t *goExtension) MessageType() protoreflect.MessageDescriptor {
- return t.messageType
+ if t.messageType == nil {
+ return nil
+ }
+ return t.messageType.Descriptor()
}
func (t *goExtension) GoType() reflect.Type {
t.lazyInit()
diff --git a/internal/testprotos/conformance/conformance.pb.go b/internal/testprotos/conformance/conformance.pb.go
index 6a718fc..90a1076 100644
--- a/internal/testprotos/conformance/conformance.pb.go
+++ b/internal/testprotos/conformance/conformance.pb.go
@@ -42,9 +42,14 @@
}
func (x WireFormat) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (WireFormat) Descriptor() protoreflect.EnumDescriptor {
+ return file_conformance_conformance_proto_enumTypes[0].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (WireFormat) Type() protoreflect.EnumType {
return file_conformance_conformance_proto_enumTypes[0]
}
@@ -98,9 +103,14 @@
}
func (x TestCategory) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestCategory) Descriptor() protoreflect.EnumDescriptor {
+ return file_conformance_conformance_proto_enumTypes[1].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestCategory) Type() protoreflect.EnumType {
return file_conformance_conformance_proto_enumTypes[1]
}
diff --git a/internal/testprotos/conformance/test_messages_proto2.pb.go b/internal/testprotos/conformance/test_messages_proto2.pb.go
index 04e0621..cde3e92 100644
--- a/internal/testprotos/conformance/test_messages_proto2.pb.go
+++ b/internal/testprotos/conformance/test_messages_proto2.pb.go
@@ -42,9 +42,14 @@
}
func (x ForeignEnumProto2) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (ForeignEnumProto2) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_test_messages_proto2_proto_enumTypes[0].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (ForeignEnumProto2) Type() protoreflect.EnumType {
return file_google_protobuf_test_messages_proto2_proto_enumTypes[0]
}
@@ -55,7 +60,7 @@
// Deprecated: Do not use.
func (x *ForeignEnumProto2) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Type(), b)
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
@@ -100,9 +105,14 @@
}
func (x TestAllTypesProto2_NestedEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestAllTypesProto2_NestedEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_test_messages_proto2_proto_enumTypes[1].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestAllTypesProto2_NestedEnum) Type() protoreflect.EnumType {
return file_google_protobuf_test_messages_proto2_proto_enumTypes[1]
}
@@ -113,7 +123,7 @@
// Deprecated: Do not use.
func (x *TestAllTypesProto2_NestedEnum) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Type(), b)
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
diff --git a/internal/testprotos/conformance/test_messages_proto3.pb.go b/internal/testprotos/conformance/test_messages_proto3.pb.go
index 28233e5..c49c66d 100644
--- a/internal/testprotos/conformance/test_messages_proto3.pb.go
+++ b/internal/testprotos/conformance/test_messages_proto3.pb.go
@@ -37,9 +37,14 @@
}
func (x ForeignEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (ForeignEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_test_messages_proto3_proto_enumTypes[0].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (ForeignEnum) Type() protoreflect.EnumType {
return file_google_protobuf_test_messages_proto3_proto_enumTypes[0]
}
@@ -79,9 +84,14 @@
}
func (x TestAllTypesProto3_NestedEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestAllTypesProto3_NestedEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_test_messages_proto3_proto_enumTypes[1].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestAllTypesProto3_NestedEnum) Type() protoreflect.EnumType {
return file_google_protobuf_test_messages_proto3_proto_enumTypes[1]
}
@@ -127,9 +137,14 @@
}
func (x TestAllTypesProto3_AliasedEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestAllTypesProto3_AliasedEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_test_messages_proto3_proto_enumTypes[2].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestAllTypesProto3_AliasedEnum) Type() protoreflect.EnumType {
return file_google_protobuf_test_messages_proto3_proto_enumTypes[2]
}
diff --git a/internal/testprotos/test/test.pb.go b/internal/testprotos/test/test.pb.go
index 8217a9a..7d512da 100644
--- a/internal/testprotos/test/test.pb.go
+++ b/internal/testprotos/test/test.pb.go
@@ -43,9 +43,14 @@
}
func (x ForeignEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (ForeignEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_test_test_proto_enumTypes[0].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (ForeignEnum) Type() protoreflect.EnumType {
return file_test_test_proto_enumTypes[0]
}
@@ -56,7 +61,7 @@
// Deprecated: Do not use.
func (x *ForeignEnum) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Type(), b)
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
@@ -92,9 +97,14 @@
}
func (x TestReservedEnumFields) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestReservedEnumFields) Descriptor() protoreflect.EnumDescriptor {
+ return file_test_test_proto_enumTypes[1].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestReservedEnumFields) Type() protoreflect.EnumType {
return file_test_test_proto_enumTypes[1]
}
@@ -105,7 +115,7 @@
// Deprecated: Do not use.
func (x *TestReservedEnumFields) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Type(), b)
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
@@ -150,9 +160,14 @@
}
func (x TestAllTypes_NestedEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestAllTypes_NestedEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_test_test_proto_enumTypes[2].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestAllTypes_NestedEnum) Type() protoreflect.EnumType {
return file_test_test_proto_enumTypes[2]
}
@@ -163,7 +178,7 @@
// Deprecated: Do not use.
func (x *TestAllTypes_NestedEnum) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Type(), b)
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
@@ -198,9 +213,14 @@
}
func (x TestDeprecatedMessage_DeprecatedEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestDeprecatedMessage_DeprecatedEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_test_test_proto_enumTypes[3].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestDeprecatedMessage_DeprecatedEnum) Type() protoreflect.EnumType {
return file_test_test_proto_enumTypes[3]
}
@@ -211,7 +231,7 @@
// Deprecated: Do not use.
func (x *TestDeprecatedMessage_DeprecatedEnum) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Type(), b)
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
diff --git a/internal/testprotos/test/test_import.pb.go b/internal/testprotos/test/test_import.pb.go
index 3b9766f..1682ef5 100644
--- a/internal/testprotos/test/test_import.pb.go
+++ b/internal/testprotos/test/test_import.pb.go
@@ -36,9 +36,14 @@
}
func (x ImportEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (ImportEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_test_test_import_proto_enumTypes[0].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (ImportEnum) Type() protoreflect.EnumType {
return file_test_test_import_proto_enumTypes[0]
}
@@ -49,7 +54,7 @@
// Deprecated: Do not use.
func (x *ImportEnum) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Type(), b)
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
diff --git a/internal/testprotos/test3/test.pb.go b/internal/testprotos/test3/test.pb.go
index d871a2e..262f7c9 100644
--- a/internal/testprotos/test3/test.pb.go
+++ b/internal/testprotos/test3/test.pb.go
@@ -39,9 +39,14 @@
}
func (x ForeignEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (ForeignEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_test3_test_proto_enumTypes[0].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (ForeignEnum) Type() protoreflect.EnumType {
return file_test3_test_proto_enumTypes[0]
}
@@ -81,9 +86,14 @@
}
func (x TestAllTypes_NestedEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (TestAllTypes_NestedEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_test3_test_proto_enumTypes[1].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (TestAllTypes_NestedEnum) Type() protoreflect.EnumType {
return file_test3_test_proto_enumTypes[1]
}
diff --git a/internal/testprotos/test3/test_import.pb.go b/internal/testprotos/test3/test_import.pb.go
index 385827b..3ea92b6 100644
--- a/internal/testprotos/test3/test_import.pb.go
+++ b/internal/testprotos/test3/test_import.pb.go
@@ -30,9 +30,14 @@
}
func (x ImportEnum) String() string {
- return protoimpl.X.EnumStringOf(x.Type(), protoreflect.EnumNumber(x))
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
+func (ImportEnum) Descriptor() protoreflect.EnumDescriptor {
+ return file_test3_test_import_proto_enumTypes[0].Descriptor()
+}
+
+// Deprecated: Use Descriptor instead.
func (ImportEnum) Type() protoreflect.EnumType {
return file_test3_test_import_proto_enumTypes[0]
}
diff --git a/internal/value/convert.go b/internal/value/convert.go
index 3bf5488..4852b40 100644
--- a/internal/value/convert.go
+++ b/internal/value/convert.go
@@ -56,11 +56,11 @@
LegacyWrapper interface {
EnumOf(interface{}) LegacyEnum
EnumTypeOf(interface{}) pref.EnumType
+ EnumDescriptorOf(interface{}) pref.EnumDescriptor
MessageOf(interface{}) LegacyMessage
MessageTypeOf(interface{}) pref.MessageType
-
- ExtensionTypeOf(pref.ExtensionDescriptor, interface{}) pref.ExtensionType
+ MessageDescriptorOf(interface{}) pref.MessageDescriptor
// TODO: Remove these eventually.
// See the TODOs in internal/impl/legacy_extension.go.
@@ -121,31 +121,14 @@
return makeScalarConverter(t, bytesType)
}
case pref.EnumKind:
- // Handle v2 enums, which must satisfy the proto.Enum interface.
- if t.Kind() != reflect.Ptr && t.Implements(enumIfaceV2) {
- et := reflect.Zero(t).Interface().(pref.Enum).Type()
- return Converter{
- PBValueOf: func(v reflect.Value) pref.Value {
- if v.Type() != t {
- panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
- }
- e := v.Interface().(pref.Enum)
- return pref.ValueOf(e.Number())
- },
- GoValueOf: func(v pref.Value) reflect.Value {
- rv := reflect.ValueOf(et.New(v.Enum()))
- if rv.Type() != t {
- panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
- }
- return rv
- },
- EnumType: et,
+ // Handle enums, which must be a named int32 type.
+ if t.PkgPath() != "" && t.Kind() == reflect.Int32 {
+ var et pref.EnumType
+ if t.Implements(enumIfaceV2) {
+ et = &enumType{reflect.Zero(t).Interface().(pref.Enum).Descriptor(), t}
+ } else {
+ et = w.EnumTypeOf(reflect.Zero(t).Interface())
}
- }
-
- // Handle v1 enums, which we identify as simply a named int32 type.
- if w != nil && t.PkgPath() != "" && t.Kind() == reflect.Int32 {
- et := w.EnumTypeOf(reflect.Zero(t).Interface())
return Converter{
PBValueOf: func(v reflect.Value) pref.Value {
if v.Type() != t {
@@ -157,13 +140,14 @@
return reflect.ValueOf(v.Enum()).Convert(t)
},
EnumType: et,
- IsLegacy: true,
+ IsLegacy: !t.Implements(enumIfaceV2),
}
}
case pref.MessageKind, pref.GroupKind:
// Handle v2 messages, which must satisfy the proto.Message interface.
if t.Kind() == reflect.Ptr && t.Implements(messageIfaceV2) {
- mt := reflect.Zero(t).Interface().(pref.ProtoMessage).ProtoReflect().Type()
+ md := reflect.Zero(t).Interface().(pref.ProtoMessage).ProtoReflect().Descriptor()
+ mt := &messageType{md, t}
return Converter{
PBValueOf: func(v reflect.Value) pref.Value {
if v.Type() != t {
@@ -240,3 +224,29 @@
MessageType pref.MessageType
IsLegacy bool
}
+
+// TODO: This needs to be centralized in a package.
+type enumType struct {
+ // TODO: Remove me as an embedded field.
+ pref.EnumDescriptor
+ typ reflect.Type // must implement protoreflect.Enum
+}
+
+func (t *enumType) Descriptor() pref.EnumDescriptor { return t.EnumDescriptor }
+func (t *enumType) GoType() reflect.Type { return t.typ }
+func (t *enumType) New(n pref.EnumNumber) pref.Enum {
+ return reflect.ValueOf(n).Convert(t.typ).Interface().(pref.Enum)
+}
+
+// TODO: This needs to be centralized in a package.
+type messageType struct {
+ // TODO: Remove me as an embedded field.
+ pref.MessageDescriptor
+ typ reflect.Type // must implement protoreflect.ProtoMessage
+}
+
+func (t *messageType) Descriptor() pref.MessageDescriptor { return t.MessageDescriptor }
+func (t *messageType) GoType() reflect.Type { return t.typ }
+func (t *messageType) New() pref.Message {
+ return reflect.New(t.typ.Elem()).Interface().(pref.ProtoMessage).ProtoReflect()
+}