internal/impl: move legacy files into impl

The internal/legacy package was originally separated out from internal/impl
to avoid a cyclic dependency on descriptor proto. However, the dependency
that legacy has on descriptor has long been dropped such that we can
now merge the two packages together again.

All legacy related logic are in a file with a legacy prefix.

Change-Id: I2424fc0f50721696ad06fa7cebb9bdd0babea13c
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/178542
Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
Joe Tsai 2019-05-22 13:42:54 -04:00
parent 1c28304cc5
commit 21ade498bd
16 changed files with 475 additions and 596 deletions

View File

@ -11,6 +11,7 @@ import (
"google.golang.org/protobuf/encoding/prototext"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/prototype"
piface "google.golang.org/protobuf/runtime/protoiface"
)
// Export is a zero-length named type that exists only to export a set of
@ -26,7 +27,7 @@ func (Export) EnumOf(e enum) pref.Enum {
if ev, ok := e.(pref.Enum); ok {
return ev
}
return legacyWrapper.EnumOf(e)
return legacyWrapEnum(reflect.ValueOf(e))
}
// EnumTypeOf returns the protoreflect.EnumType for e.
@ -39,7 +40,7 @@ func (Export) EnumTypeOf(e enum) pref.EnumType {
},
}
}
return legacyWrapper.EnumTypeOf(e)
return legacyLoadEnumType(reflect.TypeOf(e))
}
// EnumDescriptorOf returns the protoreflect.EnumDescriptor for e.
@ -47,7 +48,7 @@ func (Export) EnumDescriptorOf(e enum) pref.EnumDescriptor {
if ev, ok := e.(pref.Enum); ok {
return ev.Descriptor()
}
return legacyWrapper.EnumDescriptorOf(e)
return LegacyLoadEnumDesc(reflect.TypeOf(e))
}
// EnumStringOf returns the enum value as a string, either as the name if
@ -69,7 +70,7 @@ func (Export) MessageOf(m message) pref.Message {
if mv, ok := m.(pref.ProtoMessage); ok {
return mv.ProtoReflect()
}
return legacyWrapper.MessageOf(m)
return legacyWrapMessage(reflect.ValueOf(m)).ProtoReflect()
}
// MessageTypeOf returns the protoreflect.MessageType for m.
@ -82,7 +83,7 @@ func (Export) MessageTypeOf(m message) pref.MessageType {
},
}
}
return legacyWrapper.MessageTypeOf(m)
return legacyLoadMessageInfo(reflect.TypeOf(m)).PBType
}
// MessageDescriptorOf returns the protoreflect.MessageDescriptor for m.
@ -90,7 +91,7 @@ func (Export) MessageDescriptorOf(m message) pref.MessageDescriptor {
if mv, ok := m.(pref.ProtoMessage); ok {
return mv.ProtoReflect().Descriptor()
}
return legacyWrapper.MessageDescriptorOf(m)
return LegacyLoadMessageDesc(reflect.TypeOf(m))
}
// MessageStringOf returns the message value as a string,
@ -99,3 +100,13 @@ func (Export) MessageStringOf(m pref.ProtoMessage) string {
b, _ := prototext.MarshalOptions{AllowPartial: true}.Marshal(m)
return string(b)
}
// ExtensionDescFromType returns the legacy protoiface.ExtensionDescV1 for t.
func (Export) ExtensionDescFromType(t pref.ExtensionType) *piface.ExtensionDescV1 {
return legacyExtensionDescFromType(t)
}
// ExtensionTypeFromDesc returns the v2 protoreflect.ExtensionType for d.
func (Export) ExtensionTypeFromDesc(d *piface.ExtensionDescV1) pref.ExtensionType {
return legacyExtensionTypeFromDesc(d)
}

View File

@ -82,11 +82,11 @@ func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCode
} else {
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
m := legacyWrapper.MessageOf(p.AsValueOf(ft).Elem().Interface()).Interface()
m := legacyWrapMessage(p.AsValueOf(ft).Elem())
return sizeMessage(m, tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
m := legacyWrapper.MessageOf(p.AsValueOf(ft).Elem().Interface()).Interface()
m := legacyWrapMessage(p.AsValueOf(ft).Elem())
return appendMessage(b, m, wiretag, opts)
},
}
@ -141,11 +141,11 @@ func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderF
} else {
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
m := legacyWrapper.MessageOf(p.AsValueOf(ft).Elem().Interface()).Interface()
m := legacyWrapMessage(p.AsValueOf(ft).Elem())
return sizeGroup(m, tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
m := legacyWrapper.MessageOf(p.AsValueOf(ft).Elem().Interface()).Interface()
m := legacyWrapMessage(p.AsValueOf(ft).Elem())
return appendGroup(b, m, wiretag, opts)
},
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy
package impl
import (
"fmt"
@ -16,85 +16,85 @@ import (
"google.golang.org/protobuf/reflect/prototype"
)
// wrapEnum wraps v as a protoreflect.Enum,
// legacyWrapEnum wraps v as a protoreflect.Enum,
// where v must be a int32 kind and not implement the v2 API already.
func wrapEnum(v reflect.Value) pref.Enum {
et := loadEnumType(v.Type())
func legacyWrapEnum(v reflect.Value) pref.Enum {
et := legacyLoadEnumType(v.Type())
return et.New(pref.EnumNumber(v.Int()))
}
var enumTypeCache sync.Map // map[reflect.Type]protoreflect.EnumType
var legacyEnumTypeCache sync.Map // map[reflect.Type]protoreflect.EnumType
// loadEnumType dynamically loads a protoreflect.EnumType for t,
// legacyLoadEnumType dynamically loads a protoreflect.EnumType for t,
// where t must be an int32 kind and not implement the v2 API already.
func loadEnumType(t reflect.Type) pref.EnumType {
func legacyLoadEnumType(t reflect.Type) pref.EnumType {
// Fast-path: check if a EnumType is cached for this concrete type.
if et, ok := enumTypeCache.Load(t); ok {
if et, ok := legacyEnumTypeCache.Load(t); ok {
return et.(pref.EnumType)
}
// Slow-path: derive enum descriptor and initialize EnumType.
var et pref.EnumType
var m sync.Map // map[protoreflect.EnumNumber]proto.Enum
ed := LoadEnumDesc(t)
ed := LegacyLoadEnumDesc(t)
et = &prototype.Enum{
EnumDescriptor: ed,
NewEnum: func(n pref.EnumNumber) pref.Enum {
if e, ok := m.Load(n); ok {
return e.(pref.Enum)
}
e := &enumWrapper{num: n, pbTyp: et, goTyp: t}
e := &legacyEnumWrapper{num: n, pbTyp: et, goTyp: t}
m.Store(n, e)
return e
},
}
if et, ok := enumTypeCache.LoadOrStore(t, et); ok {
if et, ok := legacyEnumTypeCache.LoadOrStore(t, et); ok {
return et.(pref.EnumType)
}
return et
}
type enumWrapper struct {
type legacyEnumWrapper struct {
num pref.EnumNumber
pbTyp pref.EnumType
goTyp reflect.Type
}
// TODO: Remove this.
func (e *enumWrapper) Type() pref.EnumType {
func (e *legacyEnumWrapper) Type() pref.EnumType {
return e.pbTyp
}
func (e *enumWrapper) Descriptor() pref.EnumDescriptor {
func (e *legacyEnumWrapper) Descriptor() pref.EnumDescriptor {
return e.pbTyp.Descriptor()
}
func (e *enumWrapper) Number() pref.EnumNumber {
func (e *legacyEnumWrapper) Number() pref.EnumNumber {
return e.num
}
func (e *enumWrapper) ProtoReflect() pref.Enum {
func (e *legacyEnumWrapper) ProtoReflect() pref.Enum {
return e
}
func (e *enumWrapper) ProtoUnwrap() interface{} {
func (e *legacyEnumWrapper) ProtoUnwrap() interface{} {
v := reflect.New(e.goTyp).Elem()
v.SetInt(int64(e.num))
return v.Interface()
}
var (
_ pref.Enum = (*enumWrapper)(nil)
_ pvalue.Unwrapper = (*enumWrapper)(nil)
_ pref.Enum = (*legacyEnumWrapper)(nil)
_ pvalue.Unwrapper = (*legacyEnumWrapper)(nil)
)
var enumDescCache sync.Map // map[reflect.Type]protoreflect.EnumDescriptor
var legacyEnumDescCache sync.Map // map[reflect.Type]protoreflect.EnumDescriptor
var enumNumberType = reflect.TypeOf(pref.EnumNumber(0))
var legacyEnumNumberType = reflect.TypeOf(pref.EnumNumber(0))
// LoadEnumDesc returns an EnumDescriptor derived from the Go type,
// LegacyLoadEnumDesc returns an EnumDescriptor derived from the Go type,
// which must be an int32 kind and not implement the v2 API already.
//
// This is exported for testing purposes.
func LoadEnumDesc(t reflect.Type) pref.EnumDescriptor {
func LegacyLoadEnumDesc(t reflect.Type) pref.EnumDescriptor {
// Fast-path: check if an EnumDescriptor is cached for this concrete type.
if ed, ok := enumDescCache.Load(t); ok {
if ed, ok := legacyEnumDescCache.Load(t); ok {
return ed.(pref.EnumDescriptor)
}
@ -102,7 +102,7 @@ func LoadEnumDesc(t reflect.Type) pref.EnumDescriptor {
if t.Kind() != reflect.Int32 || t.PkgPath() == "" {
panic(fmt.Sprintf("got %v, want named int32 kind", t))
}
if t == enumNumberType {
if t == legacyEnumNumberType {
panic(fmt.Sprintf("cannot be %v", t))
}
@ -114,7 +114,7 @@ func LoadEnumDesc(t reflect.Type) pref.EnumDescriptor {
}
if ed, ok := ev.(enumV1); ok {
b, idxs := ed.EnumDescriptor()
fd := loadFileDesc(b)
fd := legacyLoadFileDesc(b)
// Derive syntax.
switch fd.GetSyntax() {
@ -125,7 +125,7 @@ func LoadEnumDesc(t reflect.Type) pref.EnumDescriptor {
}
// Derive the full name and correct enum descriptor.
var ed *enumDescriptorProto
var ed *legacyEnumDescriptorProto
e.FullName = pref.FullName(fd.GetPackage())
if len(idxs) == 1 {
ed = fd.EnumType[idxs[0]]
@ -160,7 +160,7 @@ func LoadEnumDesc(t reflect.Type) pref.EnumDescriptor {
// most operations continue to work. For example, prototext and protojson
// will be unable to parse a message with an enum value by name.
e.Syntax = pref.Proto2
e.FullName = deriveFullName(t)
e.FullName = legacyDeriveFullName(t)
e.Values = []ptype.EnumValue{{Name: "INVALID", Number: math.MinInt32}}
}
@ -168,7 +168,7 @@ func LoadEnumDesc(t reflect.Type) pref.EnumDescriptor {
if err != nil {
panic(err)
}
if ed, ok := enumDescCache.LoadOrStore(t, ed); ok {
if ed, ok := legacyEnumDescCache.LoadOrStore(t, ed); ok {
return ed.(pref.EnumDescriptor)
}
return ed

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy
package impl
import (
"fmt"
@ -11,7 +11,6 @@ import (
"google.golang.org/protobuf/internal/descfmt"
ptag "google.golang.org/protobuf/internal/encoding/tag"
pimpl "google.golang.org/protobuf/internal/impl"
ptype "google.golang.org/protobuf/internal/prototype"
pvalue "google.golang.org/protobuf/internal/value"
pref "google.golang.org/protobuf/reflect/protoreflect"
@ -20,9 +19,9 @@ import (
piface "google.golang.org/protobuf/runtime/protoiface"
)
// extensionDescKey is a comparable version of protoiface.ExtensionDescV1
// legacyExtensionDescKey is a comparable version of protoiface.ExtensionDescV1
// suitable for use as a key in a map.
type extensionDescKey struct {
type legacyExtensionDescKey struct {
typeV2 pref.ExtensionType
extendedType reflect.Type
extensionType reflect.Type
@ -32,8 +31,8 @@ type extensionDescKey struct {
filename string
}
func extensionDescKeyOf(d *piface.ExtensionDescV1) extensionDescKey {
return extensionDescKey{
func legacyExtensionDescKeyOf(d *piface.ExtensionDescV1) legacyExtensionDescKey {
return legacyExtensionDescKey{
d.Type,
reflect.TypeOf(d.ExtendedType),
reflect.TypeOf(d.ExtensionType),
@ -42,13 +41,13 @@ func extensionDescKeyOf(d *piface.ExtensionDescV1) extensionDescKey {
}
var (
extensionTypeCache sync.Map // map[extensionDescKey]protoreflect.ExtensionType
extensionDescCache sync.Map // map[protoreflect.ExtensionType]*protoiface.ExtensionDescV1
legacyExtensionTypeCache sync.Map // map[legacyExtensionDescKey]protoreflect.ExtensionType
legacyExtensionDescCache sync.Map // map[protoreflect.ExtensionType]*protoiface.ExtensionDescV1
)
// extensionDescFromType converts a v2 protoreflect.ExtensionType to a
// legacyExtensionDescFromType converts a v2 protoreflect.ExtensionType to a
// protoiface.ExtensionDescV1. The returned ExtensionDesc must not be mutated.
func extensionDescFromType(xt pref.ExtensionType) *piface.ExtensionDescV1 {
func legacyExtensionDescFromType(xt pref.ExtensionType) *piface.ExtensionDescV1 {
// Fast-path: check whether an extension desc is already nested within.
if xt, ok := xt.(interface {
ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
@ -60,7 +59,7 @@ func extensionDescFromType(xt pref.ExtensionType) *piface.ExtensionDescV1 {
// Fast-path: check the cache for whether this ExtensionType has already
// been converted to a legacy descriptor.
if d, ok := extensionDescCache.Load(xt); ok {
if d, ok := legacyExtensionDescCache.Load(xt); ok {
return d.(*piface.ExtensionDescV1)
}
@ -113,7 +112,7 @@ func extensionDescFromType(xt pref.ExtensionType) *piface.ExtensionDescV1 {
}
if ed, ok := reflect.Zero(t).Interface().(enumV1); ok && protoPkg == "" {
b, _ := ed.EnumDescriptor()
protoPkg = loadFileDesc(b).GetPackage()
protoPkg = legacyLoadFileDesc(b).GetPackage()
}
if protoPkg != "" {
@ -137,17 +136,17 @@ func extensionDescFromType(xt pref.ExtensionType) *piface.ExtensionDescV1 {
Tag: ptag.Marshal(xt.Descriptor(), enumName),
Filename: filename,
}
if d, ok := extensionDescCache.LoadOrStore(xt, d); ok {
if d, ok := legacyExtensionDescCache.LoadOrStore(xt, d); ok {
return d.(*piface.ExtensionDescV1)
}
return d
}
// extensionTypeFromDesc converts a protoiface.ExtensionDescV1 to a
// legacyExtensionTypeFromDesc converts a protoiface.ExtensionDescV1 to a
// v2 protoreflect.ExtensionType. The returned descriptor type takes ownership
// of the input extension desc. The input must not be mutated so long as the
// returned type is still in use.
func extensionTypeFromDesc(d *piface.ExtensionDescV1) pref.ExtensionType {
func legacyExtensionTypeFromDesc(d *piface.ExtensionDescV1) pref.ExtensionType {
// Fast-path: check whether an extension type is already nested within.
if d.Type != nil {
return d.Type
@ -155,8 +154,8 @@ func extensionTypeFromDesc(d *piface.ExtensionDescV1) pref.ExtensionType {
// Fast-path: check the cache for whether this ExtensionType has already
// been converted from a legacy descriptor.
dk := extensionDescKeyOf(d)
if t, ok := extensionTypeCache.Load(dk); ok {
dk := legacyExtensionDescKeyOf(d)
if t, ok := legacyExtensionTypeCache.Load(dk); ok {
return t.(pref.ExtensionType)
}
@ -177,13 +176,13 @@ func extensionTypeFromDesc(d *piface.ExtensionDescV1) pref.ExtensionType {
if e, ok := reflect.Zero(t).Interface().(pref.Enum); ok {
ed = e.Descriptor()
} else {
ed = LoadEnumDesc(t)
ed = LegacyLoadEnumDesc(t)
}
case pref.MessageKind, pref.GroupKind:
if m, ok := reflect.Zero(t).Interface().(pref.ProtoMessage); ok {
md = m.ProtoReflect().Descriptor()
} else {
md = LoadMessageDesc(t)
md = LegacyLoadMessageDesc(t)
}
}
xd, err := ptype.NewExtension(&ptype.StandaloneExtension{
@ -195,26 +194,27 @@ func extensionTypeFromDesc(d *piface.ExtensionDescV1) pref.ExtensionType {
Options: f.Options,
EnumType: ed,
MessageType: md,
ExtendedType: pimpl.Export{}.MessageDescriptorOf(d.ExtendedType),
ExtendedType: Export{}.MessageDescriptorOf(d.ExtendedType),
})
if err != nil {
panic(err)
}
xt := ExtensionTypeOf(xd, t)
xt := LegacyExtensionTypeOf(xd, t)
// Cache the conversion for both directions.
extensionDescCache.LoadOrStore(xt, d)
if xt, ok := extensionTypeCache.LoadOrStore(dk, xt); ok {
legacyExtensionDescCache.LoadOrStore(xt, d)
if xt, ok := legacyExtensionTypeCache.LoadOrStore(dk, xt); ok {
return xt.(pref.ExtensionType)
}
return xt
}
// 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.
// LegacyExtensionTypeOf returns a protoreflect.ExtensionType where the
// element type of the field is t. The type t must be provided if the field
// is an enum or message.
//
// This is exported for testing purposes.
func ExtensionTypeOf(xd pref.ExtensionDescriptor, t reflect.Type) pref.ExtensionType {
func LegacyExtensionTypeOf(xd pref.ExtensionDescriptor, t reflect.Type) pref.ExtensionType {
var conv pvalue.Converter
var isLegacy bool
xt := &prototype.Extension{ExtensionDescriptor: xd}
@ -234,7 +234,7 @@ func ExtensionTypeOf(xd pref.ExtensionDescriptor, t reflect.Type) pref.Extension
}
// Wrap ExtensionType such that GoType presents the legacy Go type.
xt2 := &extensionType{ExtensionType: xt}
xt2 := &legacyExtensionType{ExtensionType: xt}
if xd.Cardinality() != pref.Repeated {
xt2.typ = t
xt2.new = func() pref.Value {
@ -276,7 +276,7 @@ func ExtensionTypeOf(xd pref.ExtensionDescriptor, t reflect.Type) pref.Extension
return xt2
}
type extensionType struct {
type legacyExtensionType struct {
pref.ExtensionType
typ reflect.Type
new func() pref.Value
@ -284,8 +284,8 @@ type extensionType struct {
interfaceOf func(pref.Value) interface{}
}
func (x *extensionType) GoType() reflect.Type { return x.typ }
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) { descfmt.FormatDesc(s, r, x.Descriptor()) }
func (x *legacyExtensionType) GoType() reflect.Type { return x.typ }
func (x *legacyExtensionType) New() pref.Value { return x.new() }
func (x *legacyExtensionType) ValueOf(v interface{}) pref.Value { return x.valueOf(v) }
func (x *legacyExtensionType) InterfaceOf(v pref.Value) interface{} { return x.interfaceOf(v) }
func (x *legacyExtensionType) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, x.Descriptor()) }

View File

@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy_test
package impl_test
import (
"reflect"
"testing"
pimpl "google.golang.org/protobuf/internal/impl"
plegacy "google.golang.org/protobuf/internal/legacy"
ptype "google.golang.org/protobuf/internal/prototype"
pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
@ -17,15 +16,15 @@ import (
proto2_20180125 "google.golang.org/protobuf/internal/testprotos/legacy/proto2.v1.0.0-20180125-92554152"
)
type legacyTestMessage struct {
type legacyExtendedMessage struct {
XXX_unrecognized []byte
XXX_InternalExtensions map[int32]pimpl.ExtensionFieldV1
}
func (*legacyTestMessage) Reset() {}
func (*legacyTestMessage) String() string { return "" }
func (*legacyTestMessage) ProtoMessage() {}
func (*legacyTestMessage) ExtensionRangeArray() []piface.ExtensionRangeV1 {
func (*legacyExtendedMessage) Reset() {}
func (*legacyExtendedMessage) String() string { return "" }
func (*legacyExtendedMessage) ProtoMessage() {}
func (*legacyExtendedMessage) ExtensionRangeArray() []piface.ExtensionRangeV1 {
return []piface.ExtensionRangeV1{{Start: 10000, End: 20000}}
}
@ -34,23 +33,23 @@ func mustMakeExtensionType(x *ptype.StandaloneExtension, v interface{}) pref.Ext
if err != nil {
panic(err)
}
return plegacy.ExtensionTypeOf(xd, reflect.TypeOf(v))
return pimpl.LegacyExtensionTypeOf(xd, reflect.TypeOf(v))
}
var (
parentDesc = pimpl.Export{}.MessageDescriptorOf((*legacyTestMessage)(nil))
messageV1Desc = pimpl.Export{}.MessageDescriptorOf((*proto2_20180125.Message_ChildMessage)(nil))
extParentDesc = pimpl.Export{}.MessageDescriptorOf((*legacyExtendedMessage)(nil))
extMessageV1Desc = 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: messageV1Desc,
ExtendedType: parentDesc,
MessageType: extMessageV1Desc,
ExtendedType: extParentDesc,
}, (*proto2_20180125.Message_ChildMessage)(nil))
wantDesc = &piface.ExtensionDescV1{
ExtendedType: (*legacyTestMessage)(nil),
ExtendedType: (*legacyExtendedMessage)(nil),
ExtensionType: (*proto2_20180125.Message_ChildMessage)(nil),
Field: 10007,
Name: "fizz.buzz.optional_message_v1",
@ -61,14 +60,14 @@ var (
func BenchmarkConvert(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
xd := plegacy.Export{}.ExtensionDescFromType(wantType)
gotType := plegacy.Export{}.ExtensionTypeFromDesc(xd)
xd := pimpl.Export{}.ExtensionDescFromType(wantType)
gotType := pimpl.Export{}.ExtensionTypeFromDesc(xd)
if gotType != wantType {
b.Fatalf("ExtensionType mismatch: got %p, want %p", gotType, wantType)
}
xt := plegacy.Export{}.ExtensionTypeFromDesc(wantDesc)
gotDesc := plegacy.Export{}.ExtensionDescFromType(xt)
xt := pimpl.Export{}.ExtensionTypeFromDesc(wantDesc)
gotDesc := pimpl.Export{}.ExtensionDescFromType(xt)
if gotDesc != wantDesc {
b.Fatalf("ExtensionDesc mismatch: got %p, want %p", gotDesc, wantDesc)
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy
package impl
import (
"bytes"
@ -28,18 +28,18 @@ type (
}
)
var fileDescCache sync.Map // map[*byte]*descriptorpb.FileDescriptorProto
var legacyFileDescCache sync.Map // map[*byte]*descriptorpb.FileDescriptorProto
// loadFileDesc unmarshals b as a compressed FileDescriptorProto message.
// legacyLoadFileDesc unmarshals b as a compressed FileDescriptorProto message.
//
// This assumes that b is immutable and that b does not refer to part of a
// concatenated series of GZIP files (which would require shenanigans that
// rely on the concatenation properties of both protobufs and GZIP).
// File descriptors generated by protoc-gen-go do not rely on that property.
func loadFileDesc(b []byte) *fileDescriptorProto {
func legacyLoadFileDesc(b []byte) *legacyFileDescriptorProto {
// Fast-path: check whether we already have a cached file descriptor.
if fd, ok := fileDescCache.Load(&b[0]); ok {
return fd.(*fileDescriptorProto)
if fd, ok := legacyFileDescCache.Load(&b[0]); ok {
return fd.(*legacyFileDescriptorProto)
}
// Slow-path: decompress and unmarshal the file descriptor proto.
@ -51,9 +51,9 @@ func loadFileDesc(b []byte) *fileDescriptorProto {
if err != nil {
panic(err)
}
fd := parseFileDescProto(b)
if fd, ok := fileDescCache.LoadOrStore(&b[0], fd); ok {
return fd.(*fileDescriptorProto)
fd := legacyParseFileDescProto(b)
if fd, ok := legacyFileDescCache.LoadOrStore(&b[0], fd); ok {
return fd.(*legacyFileDescriptorProto)
}
return fd
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy_test
package impl_test
import (
"bytes"
@ -11,9 +11,9 @@ import (
"reflect"
"testing"
cmp "github.com/google/go-cmp/cmp"
legacy "google.golang.org/protobuf/internal/legacy"
pragma "google.golang.org/protobuf/internal/pragma"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/internal/impl"
"google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/proto"
pdesc "google.golang.org/protobuf/reflect/protodesc"
pref "google.golang.org/protobuf/reflect/protoreflect"
@ -59,343 +59,343 @@ func TestDescriptor(t *testing.T) {
fileDescP2_20160225 := mustLoadFileDesc(new(proto2_20160225.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20160225.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20160225.SiblingEnum(0))),
want: fileDescP2_20160225.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20160225.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20160225.Message_ChildEnum(0))),
want: fileDescP2_20160225.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.SiblingMessage))),
want: fileDescP2_20160225.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_ChildMessage))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message))),
want: fileDescP2_20160225.Messages().ByName("Message"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_NamedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_NamedGroup))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("NamedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_OptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_OptionalGroup))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("OptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_RequiredGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_RequiredGroup))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("RequiredGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_RepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_RepeatedGroup))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("RepeatedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_OneofGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_OneofGroup))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("OneofGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_ExtensionOptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_ExtensionOptionalGroup))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("ExtensionOptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_ExtensionRepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160225.Message_ExtensionRepeatedGroup))),
want: fileDescP2_20160225.Messages().ByName("Message").Messages().ByName("ExtensionRepeatedGroup"),
}}...)
fileDescP3_20160225 := mustLoadFileDesc(new(proto3_20160225.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20160225.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20160225.SiblingEnum(0))),
want: fileDescP3_20160225.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20160225.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20160225.Message_ChildEnum(0))),
want: fileDescP3_20160225.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20160225.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20160225.SiblingMessage))),
want: fileDescP3_20160225.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20160225.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20160225.Message_ChildMessage))),
want: fileDescP3_20160225.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20160225.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20160225.Message))),
want: fileDescP3_20160225.Messages().ByName("Message"),
}}...)
fileDescP2_20160519 := mustLoadFileDesc(new(proto2_20160519.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20160519.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20160519.SiblingEnum(0))),
want: fileDescP2_20160519.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20160519.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20160519.Message_ChildEnum(0))),
want: fileDescP2_20160519.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.SiblingMessage))),
want: fileDescP2_20160519.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_ChildMessage))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message))),
want: fileDescP2_20160519.Messages().ByName("Message"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_NamedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_NamedGroup))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("NamedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_OptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_OptionalGroup))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("OptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_RequiredGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_RequiredGroup))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("RequiredGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_RepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_RepeatedGroup))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("RepeatedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_OneofGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_OneofGroup))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("OneofGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_ExtensionOptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_ExtensionOptionalGroup))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("ExtensionOptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_ExtensionRepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20160519.Message_ExtensionRepeatedGroup))),
want: fileDescP2_20160519.Messages().ByName("Message").Messages().ByName("ExtensionRepeatedGroup"),
}}...)
fileDescP3_20160519 := mustLoadFileDesc(new(proto3_20160519.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20160519.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20160519.SiblingEnum(0))),
want: fileDescP3_20160519.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20160519.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20160519.Message_ChildEnum(0))),
want: fileDescP3_20160519.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20160519.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20160519.SiblingMessage))),
want: fileDescP3_20160519.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20160519.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20160519.Message_ChildMessage))),
want: fileDescP3_20160519.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20160519.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20160519.Message))),
want: fileDescP3_20160519.Messages().ByName("Message"),
}}...)
fileDescP2_20180125 := mustLoadFileDesc(new(proto2_20180125.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20180125.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20180125.SiblingEnum(0))),
want: fileDescP2_20180125.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20180125.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20180125.Message_ChildEnum(0))),
want: fileDescP2_20180125.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.SiblingMessage))),
want: fileDescP2_20180125.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_ChildMessage))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message))),
want: fileDescP2_20180125.Messages().ByName("Message"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_NamedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_NamedGroup))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("NamedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_OptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_OptionalGroup))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("OptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_RequiredGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_RequiredGroup))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("RequiredGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_RepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_RepeatedGroup))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("RepeatedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_OneofGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_OneofGroup))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("OneofGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_ExtensionOptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_ExtensionOptionalGroup))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("ExtensionOptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_ExtensionRepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180125.Message_ExtensionRepeatedGroup))),
want: fileDescP2_20180125.Messages().ByName("Message").Messages().ByName("ExtensionRepeatedGroup"),
}}...)
fileDescP3_20180125 := mustLoadFileDesc(new(proto3_20180125.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20180125.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20180125.SiblingEnum(0))),
want: fileDescP3_20180125.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20180125.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20180125.Message_ChildEnum(0))),
want: fileDescP3_20180125.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180125.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180125.SiblingMessage))),
want: fileDescP3_20180125.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180125.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180125.Message_ChildMessage))),
want: fileDescP3_20180125.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180125.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180125.Message))),
want: fileDescP3_20180125.Messages().ByName("Message"),
}}...)
fileDescP2_20180430 := mustLoadFileDesc(new(proto2_20180430.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20180430.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20180430.SiblingEnum(0))),
want: fileDescP2_20180430.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20180430.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20180430.Message_ChildEnum(0))),
want: fileDescP2_20180430.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.SiblingMessage))),
want: fileDescP2_20180430.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_ChildMessage))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message))),
want: fileDescP2_20180430.Messages().ByName("Message"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_NamedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_NamedGroup))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("NamedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_OptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_OptionalGroup))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("OptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_RequiredGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_RequiredGroup))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("RequiredGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_RepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_RepeatedGroup))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("RepeatedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_OneofGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_OneofGroup))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("OneofGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_ExtensionOptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_ExtensionOptionalGroup))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("ExtensionOptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_ExtensionRepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180430.Message_ExtensionRepeatedGroup))),
want: fileDescP2_20180430.Messages().ByName("Message").Messages().ByName("ExtensionRepeatedGroup"),
}}...)
fileDescP3_20180430 := mustLoadFileDesc(new(proto3_20180430.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20180430.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20180430.SiblingEnum(0))),
want: fileDescP3_20180430.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20180430.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20180430.Message_ChildEnum(0))),
want: fileDescP3_20180430.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180430.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180430.SiblingMessage))),
want: fileDescP3_20180430.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180430.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180430.Message_ChildMessage))),
want: fileDescP3_20180430.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180430.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180430.Message))),
want: fileDescP3_20180430.Messages().ByName("Message"),
}}...)
fileDescP2_20180814 := mustLoadFileDesc(new(proto2_20180814.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20180814.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20180814.SiblingEnum(0))),
want: fileDescP2_20180814.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20180814.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20180814.Message_ChildEnum(0))),
want: fileDescP2_20180814.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.SiblingMessage))),
want: fileDescP2_20180814.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_ChildMessage))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message))),
want: fileDescP2_20180814.Messages().ByName("Message"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_NamedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_NamedGroup))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("NamedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_OptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_OptionalGroup))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("OptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_RequiredGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_RequiredGroup))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("RequiredGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_RepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_RepeatedGroup))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("RepeatedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_OneofGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_OneofGroup))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("OneofGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_ExtensionOptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_ExtensionOptionalGroup))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("ExtensionOptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_ExtensionRepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20180814.Message_ExtensionRepeatedGroup))),
want: fileDescP2_20180814.Messages().ByName("Message").Messages().ByName("ExtensionRepeatedGroup"),
}}...)
fileDescP3_20180814 := mustLoadFileDesc(new(proto3_20180814.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20180814.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20180814.SiblingEnum(0))),
want: fileDescP3_20180814.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20180814.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20180814.Message_ChildEnum(0))),
want: fileDescP3_20180814.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180814.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180814.SiblingMessage))),
want: fileDescP3_20180814.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180814.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180814.Message_ChildMessage))),
want: fileDescP3_20180814.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20180814.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20180814.Message))),
want: fileDescP3_20180814.Messages().ByName("Message"),
}}...)
fileDescP2_20181126 := mustLoadFileDesc(new(proto2_20181126.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20181126.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20181126.SiblingEnum(0))),
want: fileDescP2_20181126.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto2_20181126.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto2_20181126.Message_ChildEnum(0))),
want: fileDescP2_20181126.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.SiblingMessage))),
want: fileDescP2_20181126.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_ChildMessage))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message))),
want: fileDescP2_20181126.Messages().ByName("Message"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_NamedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_NamedGroup))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("NamedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_OptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_OptionalGroup))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("OptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_RequiredGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_RequiredGroup))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("RequiredGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_RepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_RepeatedGroup))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("RepeatedGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_OneofGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_OneofGroup))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("OneofGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_ExtensionOptionalGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_ExtensionOptionalGroup))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("ExtensionOptionalGroup"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_ExtensionRepeatedGroup))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto2_20181126.Message_ExtensionRepeatedGroup))),
want: fileDescP2_20181126.Messages().ByName("Message").Messages().ByName("ExtensionRepeatedGroup"),
}}...)
fileDescP3_20181126 := mustLoadFileDesc(new(proto3_20181126.Message).Descriptor())
tests = append(tests, []struct{ got, want pref.Descriptor }{{
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20181126.SiblingEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20181126.SiblingEnum(0))),
want: fileDescP3_20181126.Enums().ByName("SiblingEnum"),
}, {
got: legacy.LoadEnumDesc(reflect.TypeOf(proto3_20181126.Message_ChildEnum(0))),
got: impl.LegacyLoadEnumDesc(reflect.TypeOf(proto3_20181126.Message_ChildEnum(0))),
want: fileDescP3_20181126.Messages().ByName("Message").Enums().ByName("ChildEnum"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20181126.SiblingMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20181126.SiblingMessage))),
want: fileDescP3_20181126.Messages().ByName("SiblingMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20181126.Message_ChildMessage))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20181126.Message_ChildMessage))),
want: fileDescP3_20181126.Messages().ByName("Message").Messages().ByName("ChildMessage"),
}, {
got: legacy.LoadMessageDesc(reflect.TypeOf(new(proto3_20181126.Message))),
got: impl.LegacyLoadMessageDesc(reflect.TypeOf(new(proto3_20181126.Message))),
want: fileDescP3_20181126.Messages().ByName("Message"),
}}...)

View File

@ -1,42 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package impl
import (
"reflect"
pvalue "google.golang.org/protobuf/internal/value"
pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
)
// TODO: Add a default LegacyWrapper that panics with a more helpful message?
var legacyWrapper LegacyWrapper
// RegisterLegacyWrapper registers a set of constructor functions that are
// called when a legacy enum or message is encountered that does not natively
// support the protobuf reflection APIs.
func RegisterLegacyWrapper(w LegacyWrapper) {
legacyWrapper = w
}
// LegacyWrapper is a set of wrapper methods that wraps legacy v1 Go types
// to implement the v2 reflection APIs.
type LegacyWrapper interface {
NewConverter(reflect.Type, pref.Kind) pvalue.Converter
EnumOf(interface{}) pref.Enum
EnumTypeOf(interface{}) pref.EnumType
EnumDescriptorOf(interface{}) pref.EnumDescriptor
MessageOf(interface{}) pref.Message
MessageTypeOf(interface{}) pref.MessageType
MessageDescriptorOf(interface{}) pref.MessageDescriptor
// TODO: Remove these eventually.
// See the TODOs in internal/impl/legacy_extension.go.
ExtensionDescFromType(pref.ExtensionType) *piface.ExtensionDescV1
ExtensionTypeFromDesc(*piface.ExtensionDescV1) pref.ExtensionType
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy
package impl
import (
"fmt"
@ -12,32 +12,31 @@ import (
"unicode"
ptag "google.golang.org/protobuf/internal/encoding/tag"
pimpl "google.golang.org/protobuf/internal/impl"
ptype "google.golang.org/protobuf/internal/prototype"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/prototype"
)
// wrapMessage wraps v as a protoreflect.ProtoMessage,
// legacyWrapMessage wraps v as a protoreflect.ProtoMessage,
// where v must be a *struct kind and not implement the v2 API already.
func wrapMessage(v reflect.Value) pref.ProtoMessage {
mt := loadMessageInfo(v.Type())
func legacyWrapMessage(v reflect.Value) pref.ProtoMessage {
mt := legacyLoadMessageInfo(v.Type())
return mt.MessageOf(v.Interface()).Interface()
}
var messageTypeCache sync.Map // map[reflect.Type]*MessageInfo
var legacyMessageTypeCache sync.Map // map[reflect.Type]*MessageInfo
// loadMessageInfo dynamically loads a *MessageInfo for t,
// legacyLoadMessageInfo dynamically loads a *MessageInfo for t,
// where t must be a *struct kind and not implement the v2 API already.
func loadMessageInfo(t reflect.Type) *pimpl.MessageInfo {
func legacyLoadMessageInfo(t reflect.Type) *MessageInfo {
// Fast-path: check if a MessageInfo is cached for this concrete type.
if mt, ok := messageTypeCache.Load(t); ok {
return mt.(*pimpl.MessageInfo)
if mt, ok := legacyMessageTypeCache.Load(t); ok {
return mt.(*MessageInfo)
}
// Slow-path: derive message descriptor and initialize MessageInfo.
md := LoadMessageDesc(t)
mt := new(pimpl.MessageInfo)
md := LegacyLoadMessageDesc(t)
mt := new(MessageInfo)
mt.GoType = t
mt.PBType = &prototype.Message{
MessageDescriptor: md,
@ -45,32 +44,34 @@ func loadMessageInfo(t reflect.Type) *pimpl.MessageInfo {
return mt.MessageOf(reflect.New(t.Elem()).Interface())
},
}
if mt, ok := messageTypeCache.LoadOrStore(t, mt); ok {
return mt.(*pimpl.MessageInfo)
if mt, ok := legacyMessageTypeCache.LoadOrStore(t, mt); ok {
return mt.(*MessageInfo)
}
return mt
}
var messageDescLock sync.Mutex
var messageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor
var (
legacyMessageDescLock sync.Mutex
legacyMessageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor
)
// LoadMessageDesc returns an MessageDescriptor derived from the Go type,
// LegacyLoadMessageDesc returns an MessageDescriptor derived from the Go type,
// which must be a *struct kind and not implement the v2 API already.
//
// This is exported for testing purposes.
func LoadMessageDesc(t reflect.Type) pref.MessageDescriptor {
return messageDescSet{}.Load(t)
func LegacyLoadMessageDesc(t reflect.Type) pref.MessageDescriptor {
return legacyMessageDescSet{}.Load(t)
}
type messageDescSet struct {
type legacyMessageDescSet struct {
visited map[reflect.Type]*ptype.StandaloneMessage
descs []*ptype.StandaloneMessage
types []reflect.Type
}
func (ms messageDescSet) Load(t reflect.Type) pref.MessageDescriptor {
func (ms legacyMessageDescSet) Load(t reflect.Type) pref.MessageDescriptor {
// Fast-path: check if a MessageDescriptor is cached for this concrete type.
if mi, ok := messageDescCache.Load(t); ok {
if mi, ok := legacyMessageDescCache.Load(t); ok {
return mi.(pref.MessageDescriptor)
}
@ -79,9 +80,9 @@ func (ms messageDescSet) Load(t reflect.Type) pref.MessageDescriptor {
// Hold a global lock during message creation to ensure that each Go type
// maps to exactly one MessageDescriptor. After obtaining the lock, we must
// check again whether the message has already been handled.
messageDescLock.Lock()
defer messageDescLock.Unlock()
if mi, ok := messageDescCache.Load(t); ok {
legacyMessageDescLock.Lock()
defer legacyMessageDescLock.Unlock()
if mi, ok := legacyMessageDescCache.Load(t); ok {
return mi.(pref.MessageDescriptor)
}
@ -101,13 +102,13 @@ func (ms messageDescSet) Load(t reflect.Type) pref.MessageDescriptor {
// pseudo-messages (has a descriptor, but no generated Go type).
// Avoid caching these fake messages.
if t := ms.types[i]; t.Kind() != reflect.Map {
messageDescCache.Store(t, md)
legacyMessageDescCache.Store(t, md)
}
}
return mds[0]
}
func (ms *messageDescSet) processMessage(t reflect.Type) pref.MessageDescriptor {
func (ms *legacyMessageDescSet) processMessage(t reflect.Type) pref.MessageDescriptor {
// Fast-path: Obtain a placeholder if the message is already processed.
if m, ok := ms.visited[t]; ok {
return ptype.PlaceholderMessage(m.FullName)
@ -126,7 +127,7 @@ func (ms *messageDescSet) processMessage(t reflect.Type) pref.MessageDescriptor
}
if md, ok := mv.(messageV1); ok {
b, idxs := md.Descriptor()
fd := loadFileDesc(b)
fd := legacyLoadFileDesc(b)
// Derive syntax.
switch fd.GetSyntax() {
@ -148,7 +149,7 @@ func (ms *messageDescSet) processMessage(t reflect.Type) pref.MessageDescriptor
// obtain the full name is through the registry. However, this is
// unreliable as some generated messages register with a fork of
// golang/protobuf, so the registry may not have this information.
m.FullName = deriveFullName(t.Elem())
m.FullName = legacyDeriveFullName(t.Elem())
m.Syntax = pref.Proto2
// Try to determine if the message is using proto3 by checking scalars.
@ -223,7 +224,7 @@ func (ms *messageDescSet) processMessage(t reflect.Type) pref.MessageDescriptor
return ptype.PlaceholderMessage(m.FullName)
}
func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, goType reflect.Type, parent *ptype.StandaloneMessage) ptype.Field {
func (ms *legacyMessageDescSet) parseField(tag, tagKey, tagVal string, goType reflect.Type, parent *ptype.StandaloneMessage) ptype.Field {
t := goType
isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct
isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
@ -237,7 +238,7 @@ func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, goType reflect.
if ev, ok := reflect.Zero(t).Interface().(pref.Enum); ok {
f.EnumType = ev.Descriptor()
} else {
f.EnumType = LoadEnumDesc(t)
f.EnumType = LegacyLoadEnumDesc(t)
}
}
if f.MessageType == nil && (f.Kind == pref.MessageKind || f.Kind == pref.GroupKind) {
@ -246,7 +247,7 @@ func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, goType reflect.
} else if t.Kind() == reflect.Map {
m := &ptype.StandaloneMessage{
Syntax: parent.Syntax,
FullName: parent.FullName.Append(mapEntryName(f.Name)),
FullName: parent.FullName.Append(legacyMapEntryName(f.Name)),
IsMapEntry: true,
Fields: []ptype.Field{
ms.parseField(tagKey, "", "", t.Key(), nil),
@ -255,7 +256,7 @@ func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, goType reflect.
}
ms.visit(m, t)
f.MessageType = ptype.PlaceholderMessage(m.FullName)
} else if mv, ok := messageDescCache.Load(t); ok {
} else if mv, ok := legacyMessageDescCache.Load(t); ok {
f.MessageType = mv.(pref.MessageDescriptor)
} else {
f.MessageType = ms.processMessage(t)
@ -264,7 +265,7 @@ func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, goType reflect.
return f
}
func (ms *messageDescSet) visit(m *ptype.StandaloneMessage, t reflect.Type) {
func (ms *legacyMessageDescSet) visit(m *ptype.StandaloneMessage, t reflect.Type) {
if ms.visited == nil {
ms.visited = make(map[reflect.Type]*ptype.StandaloneMessage)
}
@ -275,10 +276,10 @@ func (ms *messageDescSet) visit(m *ptype.StandaloneMessage, t reflect.Type) {
ms.types = append(ms.types, t)
}
// deriveFullName derives a fully qualified protobuf name for the given Go type
// legacyDeriveFullName derives a fully qualified protobuf name for the given Go type
// The provided name is not guaranteed to be stable nor universally unique.
// It should be sufficiently unique within a program.
func deriveFullName(t reflect.Type) pref.FullName {
func legacyDeriveFullName(t reflect.Type) pref.FullName {
sanitize := func(r rune) rune {
switch {
case r == '/':
@ -304,9 +305,9 @@ func deriveFullName(t reflect.Type) pref.FullName {
return pref.FullName(strings.Join(ss, "."))
}
// mapEntryName derives the message name for a map field of a given name.
// legacyMapEntryName derives the message name for a map field of a given name.
// This is identical to MapEntryName from parser.cc in the protoc source.
func mapEntryName(s pref.Name) pref.Name {
func legacyMapEntryName(s pref.Name) pref.Name {
var b []byte
nextUpper := true
for i := 0; i < len(s); i++ {

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy
package impl
import (
"google.golang.org/protobuf/internal/encoding/wire"
@ -14,21 +14,21 @@ import (
//
// TODO: Consider unifying this with the parser in fileinit.
type fileDescriptorProto struct {
type legacyFileDescriptorProto struct {
Syntax string
Package string
EnumType []*enumDescriptorProto
MessageType []*descriptorProto
EnumType []*legacyEnumDescriptorProto
MessageType []*legacyDescriptorProto
}
func (fd fileDescriptorProto) GetSyntax() string { return fd.Syntax }
func (fd fileDescriptorProto) GetPackage() string { return fd.Package }
func (fd legacyFileDescriptorProto) GetSyntax() string { return fd.Syntax }
func (fd legacyFileDescriptorProto) GetPackage() string { return fd.Package }
func parseFileDescProto(b []byte) *fileDescriptorProto {
fd := &fileDescriptorProto{}
func legacyParseFileDescProto(b []byte) *legacyFileDescriptorProto {
fd := &legacyFileDescriptorProto{}
for len(b) > 0 {
num, typ, n := wire.ConsumeTag(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch typ {
case wire.BytesType:
@ -40,37 +40,37 @@ func parseFileDescProto(b []byte) *fileDescriptorProto {
case fieldnum.FileDescriptorProto_Package:
fd.Package = string(v)
case fieldnum.FileDescriptorProto_EnumType:
fd.EnumType = append(fd.EnumType, parseEnumDescProto(v))
fd.EnumType = append(fd.EnumType, legacyParseEnumDescProto(v))
case fieldnum.FileDescriptorProto_MessageType:
fd.MessageType = append(fd.MessageType, parseDescProto(v))
}
default:
n := wire.ConsumeFieldValue(num, typ, b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
}
}
return fd
}
type descriptorProto struct {
type legacyDescriptorProto struct {
Name string
NestedType []*descriptorProto
EnumType []*enumDescriptorProto
NestedType []*legacyDescriptorProto
EnumType []*legacyEnumDescriptorProto
}
func (md descriptorProto) GetName() string { return md.Name }
func (md legacyDescriptorProto) GetName() string { return md.Name }
func parseDescProto(b []byte) *descriptorProto {
md := &descriptorProto{}
func parseDescProto(b []byte) *legacyDescriptorProto {
md := &legacyDescriptorProto{}
for len(b) > 0 {
num, typ, n := wire.ConsumeTag(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch typ {
case wire.BytesType:
v, n := wire.ConsumeBytes(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch num {
case fieldnum.DescriptorProto_Name:
@ -78,68 +78,68 @@ func parseDescProto(b []byte) *descriptorProto {
case fieldnum.DescriptorProto_NestedType:
md.NestedType = append(md.NestedType, parseDescProto(v))
case fieldnum.DescriptorProto_EnumType:
md.EnumType = append(md.EnumType, parseEnumDescProto(v))
md.EnumType = append(md.EnumType, legacyParseEnumDescProto(v))
}
default:
n := wire.ConsumeFieldValue(num, typ, b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
}
}
return md
}
type enumDescriptorProto struct {
type legacyEnumDescriptorProto struct {
Name string
Value []*enumValueDescriptorProto
Value []*legacyEnumValueDescriptorProto
}
func (ed enumDescriptorProto) GetName() string { return ed.Name }
func (ed legacyEnumDescriptorProto) GetName() string { return ed.Name }
func parseEnumDescProto(b []byte) *enumDescriptorProto {
ed := &enumDescriptorProto{}
func legacyParseEnumDescProto(b []byte) *legacyEnumDescriptorProto {
ed := &legacyEnumDescriptorProto{}
for len(b) > 0 {
num, typ, n := wire.ConsumeTag(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch typ {
case wire.BytesType:
v, n := wire.ConsumeBytes(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch num {
case fieldnum.EnumDescriptorProto_Name:
ed.Name = string(v)
case fieldnum.EnumDescriptorProto_Value:
ed.Value = append(ed.Value, parseEnumValueDescProto(v))
ed.Value = append(ed.Value, legacyParseEnumValueDescProto(v))
}
default:
n := wire.ConsumeFieldValue(num, typ, b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
}
}
return ed
}
type enumValueDescriptorProto struct {
type legacyEnumValueDescriptorProto struct {
Name string
Number int32
}
func (ed enumValueDescriptorProto) GetName() string { return ed.Name }
func (ed enumValueDescriptorProto) GetNumber() int32 { return ed.Number }
func (ed legacyEnumValueDescriptorProto) GetName() string { return ed.Name }
func (ed legacyEnumValueDescriptorProto) GetNumber() int32 { return ed.Number }
func parseEnumValueDescProto(b []byte) *enumValueDescriptorProto {
vd := &enumValueDescriptorProto{}
func legacyParseEnumValueDescProto(b []byte) *legacyEnumValueDescriptorProto {
vd := &legacyEnumValueDescriptorProto{}
for len(b) > 0 {
num, typ, n := wire.ConsumeTag(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch typ {
case wire.VarintType:
v, n := wire.ConsumeVarint(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch num {
case fieldnum.EnumValueDescriptorProto_Number:
@ -147,7 +147,7 @@ func parseEnumValueDescProto(b []byte) *enumValueDescriptorProto {
}
case wire.BytesType:
v, n := wire.ConsumeBytes(b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
switch num {
case fieldnum.EnumDescriptorProto_Name:
@ -155,14 +155,14 @@ func parseEnumValueDescProto(b []byte) *enumValueDescriptorProto {
}
default:
n := wire.ConsumeFieldValue(num, typ, b)
parseCheck(n)
legacyParseCheck(n)
b = b[n:]
}
}
return vd
}
func parseCheck(n int) {
func legacyParseCheck(n int) {
if n < 0 {
panic(wire.ParseError(n))
}

View File

@ -8,13 +8,13 @@ import (
"bytes"
"math"
"reflect"
"sync"
"testing"
cmp "github.com/google/go-cmp/cmp"
cmpopts "github.com/google/go-cmp/cmp/cmpopts"
pack "google.golang.org/protobuf/internal/encoding/pack"
pimpl "google.golang.org/protobuf/internal/impl"
plegacy "google.golang.org/protobuf/internal/legacy"
pragma "google.golang.org/protobuf/internal/pragma"
ptype "google.golang.org/protobuf/internal/prototype"
scalar "google.golang.org/protobuf/internal/scalar"
@ -172,20 +172,12 @@ func TestLegacyUnknown(t *testing.T) {
}
}
func mustMakeExtensionType(x *ptype.StandaloneExtension, v interface{}) pref.ExtensionType {
xd, err := ptype.NewExtension(x)
if err != nil {
panic(xd)
}
return plegacy.ExtensionTypeOf(xd, reflect.TypeOf(v))
}
var (
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()
testParentDesc = pimpl.Export{}.MessageDescriptorOf((*legacyTestMessage)(nil))
testEnumV1Desc = pimpl.Export{}.EnumDescriptorOf(proto2_20180125.Message_ChildEnum(0))
testMessageV1Desc = pimpl.Export{}.MessageDescriptorOf((*proto2_20180125.Message_ChildMessage)(nil))
testEnumV2Desc = enumProto2Type.Descriptor()
testMessageV2Desc = enumMessagesType.PBType.Descriptor()
extensionTypes = []pref.ExtensionType{
mustMakeExtensionType(&ptype.StandaloneExtension{
@ -194,7 +186,7 @@ var (
Cardinality: pref.Optional,
Kind: pref.BoolKind,
Default: pref.ValueOf(true),
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_int32",
@ -202,7 +194,7 @@ var (
Cardinality: pref.Optional,
Kind: pref.Int32Kind,
Default: pref.ValueOf(int32(-12345)),
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_uint32",
@ -210,7 +202,7 @@ var (
Cardinality: pref.Optional,
Kind: pref.Uint32Kind,
Default: pref.ValueOf(uint32(3200)),
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_float",
@ -218,7 +210,7 @@ var (
Cardinality: pref.Optional,
Kind: pref.FloatKind,
Default: pref.ValueOf(float32(3.14159)),
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_string",
@ -226,7 +218,7 @@ var (
Cardinality: pref.Optional,
Kind: pref.StringKind,
Default: pref.ValueOf(string("hello, \"world!\"\n")),
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_bytes",
@ -234,7 +226,7 @@ var (
Cardinality: pref.Optional,
Kind: pref.BytesKind,
Default: pref.ValueOf([]byte("dead\xde\xad\xbe\xefbeef")),
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_enum_v1",
@ -242,16 +234,16 @@ var (
Cardinality: pref.Optional,
Kind: pref.EnumKind,
Default: pref.ValueOf(pref.EnumNumber(0)),
EnumType: enumV1Desc,
ExtendedType: parentDesc,
EnumType: testEnumV1Desc,
ExtendedType: testParentDesc,
}, proto2_20180125.Message_ChildEnum(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_message_v1",
Number: 10007,
Cardinality: pref.Optional,
Kind: pref.MessageKind,
MessageType: messageV1Desc,
ExtendedType: parentDesc,
MessageType: testMessageV1Desc,
ExtendedType: testParentDesc,
}, (*proto2_20180125.Message_ChildMessage)(nil)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_enum_v2",
@ -259,90 +251,90 @@ var (
Cardinality: pref.Optional,
Kind: pref.EnumKind,
Default: pref.ValueOf(pref.EnumNumber(57005)),
EnumType: enumV2Desc,
ExtendedType: parentDesc,
EnumType: testEnumV2Desc,
ExtendedType: testParentDesc,
}, EnumProto2(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.optional_message_v2",
Number: 10009,
Cardinality: pref.Optional,
Kind: pref.MessageKind,
MessageType: messageV2Desc,
ExtendedType: parentDesc,
MessageType: testMessageV2Desc,
ExtendedType: testParentDesc,
}, (*EnumMessages)(nil)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_bool",
Number: 10010,
Cardinality: pref.Repeated,
Kind: pref.BoolKind,
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_int32",
Number: 10011,
Cardinality: pref.Repeated,
Kind: pref.Int32Kind,
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_uint32",
Number: 10012,
Cardinality: pref.Repeated,
Kind: pref.Uint32Kind,
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_float",
Number: 10013,
Cardinality: pref.Repeated,
Kind: pref.FloatKind,
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_string",
Number: 10014,
Cardinality: pref.Repeated,
Kind: pref.StringKind,
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_bytes",
Number: 10015,
Cardinality: pref.Repeated,
Kind: pref.BytesKind,
ExtendedType: parentDesc,
ExtendedType: testParentDesc,
}, nil),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_enum_v1",
Number: 10016,
Cardinality: pref.Repeated,
Kind: pref.EnumKind,
EnumType: enumV1Desc,
ExtendedType: parentDesc,
EnumType: testEnumV1Desc,
ExtendedType: testParentDesc,
}, proto2_20180125.Message_ChildEnum(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_message_v1",
Number: 10017,
Cardinality: pref.Repeated,
Kind: pref.MessageKind,
MessageType: messageV1Desc,
ExtendedType: parentDesc,
MessageType: testMessageV1Desc,
ExtendedType: testParentDesc,
}, (*proto2_20180125.Message_ChildMessage)(nil)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_enum_v2",
Number: 10018,
Cardinality: pref.Repeated,
Kind: pref.EnumKind,
EnumType: enumV2Desc,
ExtendedType: parentDesc,
EnumType: testEnumV2Desc,
ExtendedType: testParentDesc,
}, EnumProto2(0)),
mustMakeExtensionType(&ptype.StandaloneExtension{
FullName: "fizz.buzz.repeated_message_v2",
Number: 10019,
Cardinality: pref.Repeated,
Kind: pref.MessageKind,
MessageType: messageV2Desc,
ExtendedType: parentDesc,
MessageType: testMessageV2Desc,
ExtendedType: testParentDesc,
}, (*EnumMessages)(nil)),
}
@ -646,8 +638,8 @@ func TestExtensionConvert(t *testing.T) {
wantType := extensionTypes[i]
wantDesc := extensionDescs[i]
gotType := plegacy.Export{}.ExtensionTypeFromDesc(wantDesc)
gotDesc := plegacy.Export{}.ExtensionDescFromType(wantType)
gotType := pimpl.Export{}.ExtensionTypeFromDesc(wantDesc)
gotDesc := pimpl.Export{}.ExtensionDescFromType(wantType)
// TODO: We need a test package to compare descriptors.
type list interface {
@ -720,3 +712,88 @@ func TestExtensionConvert(t *testing.T) {
})
}
}
type (
MessageA struct {
A1 *MessageA `protobuf:"bytes,1,req,name=a1"`
A2 *MessageB `protobuf:"bytes,2,req,name=a2"`
A3 Enum `protobuf:"varint,3,opt,name=a3,enum=legacy.Enum"`
}
MessageB struct {
B1 *MessageA `protobuf:"bytes,1,req,name=b1"`
B2 *MessageB `protobuf:"bytes,2,req,name=b2"`
B3 Enum `protobuf:"varint,3,opt,name=b3,enum=legacy.Enum"`
}
Enum int32
)
// TestConcurrentInit tests that concurrent wrapping of multiple legacy types
// results in the exact same descriptor being created.
func TestConcurrentInit(t *testing.T) {
const numParallel = 5
var messageATypes [numParallel]pref.MessageType
var messageBTypes [numParallel]pref.MessageType
var enumDescs [numParallel]pref.EnumDescriptor
// Concurrently load message and enum types.
var wg sync.WaitGroup
for i := 0; i < numParallel; i++ {
i := i
wg.Add(3)
go func() {
defer wg.Done()
messageATypes[i] = pimpl.Export{}.MessageTypeOf((*MessageA)(nil))
}()
go func() {
defer wg.Done()
messageBTypes[i] = pimpl.Export{}.MessageTypeOf((*MessageB)(nil))
}()
go func() {
defer wg.Done()
enumDescs[i] = pimpl.Export{}.EnumDescriptorOf(Enum(0))
}()
}
wg.Wait()
var (
wantMTA = messageATypes[0]
wantMDA = messageATypes[0].Descriptor().Fields().ByNumber(1).Message()
wantMTB = messageBTypes[0]
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.Descriptor().Fields().ByNumber(1).Message(); gotMDA != wantMDA {
t.Error("MessageDescriptor(MessageA) mismatch")
}
if gotMDB := gotMT.Descriptor().Fields().ByNumber(2).Message(); gotMDB != wantMDB {
t.Error("MessageDescriptor(MessageB) mismatch")
}
if gotED := gotMT.Descriptor().Fields().ByNumber(3).Enum(); gotED != wantED {
t.Error("EnumDescriptor(Enum) mismatch")
}
}
for _, gotMT := range messageBTypes[1:] {
if gotMT != wantMTB {
t.Error("MessageType(MessageB) mismatch")
}
if gotMDA := gotMT.Descriptor().Fields().ByNumber(1).Message(); gotMDA != wantMDA {
t.Error("MessageDescriptor(MessageA) mismatch")
}
if gotMDB := gotMT.Descriptor().Fields().ByNumber(2).Message(); gotMDB != wantMDB {
t.Error("MessageDescriptor(MessageB) mismatch")
}
if gotED := gotMT.Descriptor().Fields().ByNumber(3).Enum(); gotED != wantED {
t.Error("EnumDescriptor(Enum) mismatch")
}
}
for _, gotED := range enumDescs[1:] {
if gotED != wantED {
t.Error("EnumType(Enum) mismatch")
}
}
}

View File

@ -12,6 +12,7 @@ import (
"google.golang.org/protobuf/internal/encoding/wire"
pvalue "google.golang.org/protobuf/internal/value"
pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
)
type fieldInfo struct {
@ -42,7 +43,7 @@ func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, ot refle
if !reflect.PtrTo(ot).Implements(ft) {
panic(fmt.Sprintf("invalid type: %v does not implement %v", ot, ft))
}
conv := newConverter(ot.Field(0).Type, fd.Kind())
conv, _ := newConverter(ot.Field(0).Type, fd.Kind())
fieldOffset := offsetOf(fs)
// TODO: Implement unsafe fast path?
return fieldInfo{
@ -97,8 +98,8 @@ func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo
if ft.Kind() != reflect.Map {
panic(fmt.Sprintf("invalid type: got %v, want map kind", ft))
}
keyConv := newConverter(ft.Key(), fd.MapKey().Kind())
valConv := newConverter(ft.Elem(), fd.MapValue().Kind())
keyConv, _ := newConverter(ft.Key(), fd.MapKey().Kind())
valConv, _ := newConverter(ft.Elem(), fd.MapValue().Kind())
wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
fieldOffset := offsetOf(fs)
// TODO: Implement unsafe fast path?
@ -139,7 +140,7 @@ func fieldInfoForList(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo
if ft.Kind() != reflect.Slice {
panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
}
conv := newConverter(ft.Elem(), fd.Kind())
conv, _ := newConverter(ft.Elem(), fd.Kind())
var wiretag uint64
if !fd.IsPacked() {
wiretag = wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
@ -194,7 +195,7 @@ func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField) fieldIn
ft = ft.Elem()
}
}
conv := newConverter(ft, fd.Kind())
conv, _ := newConverter(ft, fd.Kind())
fieldOffset := offsetOf(fs)
wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
// TODO: Implement unsafe fast path?
@ -264,7 +265,7 @@ func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField) fieldIn
func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
ft := fs.Type
conv := newConverter(ft, fd.Kind())
conv, _ := newConverter(ft, fd.Kind())
fieldOffset := offsetOf(fs)
// TODO: Implement unsafe fast path?
wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
@ -338,9 +339,52 @@ func makeOneofInfo(od pref.OneofDescriptor, fs reflect.StructField, wrappersByTy
}
}
func newConverter(t reflect.Type, k pref.Kind) pvalue.Converter {
if legacyWrapper != nil {
return legacyWrapper.NewConverter(t, k)
var (
enumIfaceV2 = reflect.TypeOf((*pref.Enum)(nil)).Elem()
messageIfaceV1 = reflect.TypeOf((*piface.MessageV1)(nil)).Elem()
messageIfaceV2 = reflect.TypeOf((*pref.ProtoMessage)(nil)).Elem()
)
func newConverter(t reflect.Type, k pref.Kind) (conv pvalue.Converter, isLegacy bool) {
switch k {
case pref.EnumKind:
if t.Kind() == reflect.Int32 && !t.Implements(enumIfaceV2) {
return pvalue.Converter{
PBValueOf: func(v reflect.Value) pref.Value {
if v.Type() != t {
panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
}
return pref.ValueOf(pref.EnumNumber(v.Int()))
},
GoValueOf: func(v pref.Value) reflect.Value {
return reflect.ValueOf(v.Enum()).Convert(t)
},
NewEnum: func(n pref.EnumNumber) pref.Enum {
return legacyWrapEnum(reflect.ValueOf(n).Convert(t))
},
}, true
}
case pref.MessageKind, pref.GroupKind:
if t.Kind() == reflect.Ptr && t.Implements(messageIfaceV1) && !t.Implements(messageIfaceV2) {
return pvalue.Converter{
PBValueOf: func(v reflect.Value) pref.Value {
if v.Type() != t {
panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
}
return pref.ValueOf(Export{}.MessageOf(v.Interface()))
},
GoValueOf: func(v pref.Value) reflect.Value {
rv := reflect.ValueOf(v.Message().(pvalue.Unwrapper).ProtoUnwrap())
if rv.Type() != t {
panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
}
return rv
},
NewMessage: func() pref.Message {
return legacyWrapMessage(reflect.New(t.Elem())).ProtoReflect()
},
}, true
}
}
return pvalue.NewConverter(t, k)
return pvalue.NewConverter(t, k), false
}

View File

@ -231,14 +231,14 @@ func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
return desc
}
}
return legacyWrapper.ExtensionDescFromType(typ)
return Export{}.ExtensionDescFromType(typ)
}
func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
if desc.Type != nil {
return desc.Type
}
return legacyWrapper.ExtensionTypeFromDesc(desc)
return Export{}.ExtensionTypeFromDesc(desc)
}
type ExtensionFieldV1 struct {

View File

@ -1,110 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy
import (
"fmt"
"reflect"
pimpl "google.golang.org/protobuf/internal/impl"
pvalue "google.golang.org/protobuf/internal/value"
pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
)
// Export is a zero-length named type that exists only to export a set of
// functions that we do not want to appear in godoc.
type Export struct{}
func (Export) EnumOf(e interface{}) pref.Enum {
return wrapEnum(reflect.ValueOf(e))
}
func (Export) EnumTypeOf(e interface{}) pref.EnumType {
return loadEnumType(reflect.TypeOf(e))
}
func (Export) EnumDescriptorOf(e interface{}) pref.EnumDescriptor {
return LoadEnumDesc(reflect.TypeOf(e))
}
func (Export) MessageOf(m interface{}) pref.Message {
return wrapMessage(reflect.ValueOf(m)).ProtoReflect()
}
func (Export) MessageTypeOf(m interface{}) pref.MessageType {
return loadMessageInfo(reflect.TypeOf(m)).PBType
}
func (Export) MessageDescriptorOf(m interface{}) pref.MessageDescriptor {
return LoadMessageDesc(reflect.TypeOf(m))
}
func (Export) ExtensionDescFromType(t pref.ExtensionType) *piface.ExtensionDescV1 {
return extensionDescFromType(t)
}
func (Export) ExtensionTypeFromDesc(d *piface.ExtensionDescV1) pref.ExtensionType {
return extensionTypeFromDesc(d)
}
var (
enumIfaceV2 = reflect.TypeOf((*pref.Enum)(nil)).Elem()
messageIfaceV1 = reflect.TypeOf((*piface.MessageV1)(nil)).Elem()
messageIfaceV2 = reflect.TypeOf((*pref.ProtoMessage)(nil)).Elem()
)
func (Export) NewConverter(t reflect.Type, k pref.Kind) pvalue.Converter {
c, _ := newConverter(t, k)
return c
}
func newConverter(t reflect.Type, k pref.Kind) (pvalue.Converter, bool) {
switch k {
case pref.EnumKind:
if t.Kind() == reflect.Int32 && !t.Implements(enumIfaceV2) {
return pvalue.Converter{
PBValueOf: func(v reflect.Value) pref.Value {
if v.Type() != t {
panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
}
return pref.ValueOf(pref.EnumNumber(v.Int()))
},
GoValueOf: func(v pref.Value) reflect.Value {
return reflect.ValueOf(v.Enum()).Convert(t)
},
NewEnum: func(n pref.EnumNumber) pref.Enum {
return wrapEnum(reflect.ValueOf(n).Convert(t))
},
}, true
}
case pref.MessageKind, pref.GroupKind:
if t.Kind() == reflect.Ptr && t.Implements(messageIfaceV1) && !t.Implements(messageIfaceV2) {
return pvalue.Converter{
PBValueOf: func(v reflect.Value) pref.Value {
if v.Type() != t {
panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
}
return pref.ValueOf(Export{}.MessageOf(v.Interface()))
},
GoValueOf: func(v pref.Value) reflect.Value {
rv := reflect.ValueOf(v.Message().(pvalue.Unwrapper).ProtoUnwrap())
if rv.Type() != t {
panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
}
return rv
},
NewMessage: func() pref.Message {
return wrapMessage(reflect.New(t.Elem())).ProtoReflect()
},
}, true
}
}
return pvalue.NewConverter(t, k), false
}
func init() {
pimpl.RegisterLegacyWrapper(Export{})
}

View File

@ -1,97 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package legacy
import (
"sync"
"testing"
"google.golang.org/protobuf/reflect/protoreflect"
)
type (
MessageA struct {
A1 *MessageA `protobuf:"bytes,1,req,name=a1"`
A2 *MessageB `protobuf:"bytes,2,req,name=a2"`
A3 Enum `protobuf:"varint,3,opt,name=a3,enum=legacy.Enum"`
}
MessageB struct {
B1 *MessageA `protobuf:"bytes,1,req,name=b1"`
B2 *MessageB `protobuf:"bytes,2,req,name=b2"`
B3 Enum `protobuf:"varint,3,opt,name=b3,enum=legacy.Enum"`
}
Enum int32
)
// TestConcurrentInit tests that concurrent wrapping of multiple legacy types
// results in the exact same descriptor being created.
func TestConcurrentInit(t *testing.T) {
const numParallel = 5
var messageATypes [numParallel]protoreflect.MessageType
var messageBTypes [numParallel]protoreflect.MessageType
var enumDescs [numParallel]protoreflect.EnumDescriptor
// Concurrently load message and enum types.
var wg sync.WaitGroup
for i := 0; i < numParallel; i++ {
i := i
wg.Add(3)
go func() {
defer wg.Done()
messageATypes[i] = Export{}.MessageTypeOf((*MessageA)(nil))
}()
go func() {
defer wg.Done()
messageBTypes[i] = Export{}.MessageTypeOf((*MessageB)(nil))
}()
go func() {
defer wg.Done()
enumDescs[i] = Export{}.EnumDescriptorOf(Enum(0))
}()
}
wg.Wait()
var (
wantMTA = messageATypes[0]
wantMDA = messageATypes[0].Descriptor().Fields().ByNumber(1).Message()
wantMTB = messageBTypes[0]
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.Descriptor().Fields().ByNumber(1).Message(); gotMDA != wantMDA {
t.Error("MessageDescriptor(MessageA) mismatch")
}
if gotMDB := gotMT.Descriptor().Fields().ByNumber(2).Message(); gotMDB != wantMDB {
t.Error("MessageDescriptor(MessageB) mismatch")
}
if gotED := gotMT.Descriptor().Fields().ByNumber(3).Enum(); gotED != wantED {
t.Error("EnumDescriptor(Enum) mismatch")
}
}
for _, gotMT := range messageBTypes[1:] {
if gotMT != wantMTB {
t.Error("MessageType(MessageB) mismatch")
}
if gotMDA := gotMT.Descriptor().Fields().ByNumber(1).Message(); gotMDA != wantMDA {
t.Error("MessageDescriptor(MessageA) mismatch")
}
if gotMDB := gotMT.Descriptor().Fields().ByNumber(2).Message(); gotMDB != wantMDB {
t.Error("MessageDescriptor(MessageB) mismatch")
}
if gotED := gotMT.Descriptor().Fields().ByNumber(3).Enum(); gotED != wantED {
t.Error("EnumDescriptor(Enum) mismatch")
}
}
for _, gotED := range enumDescs[1:] {
if gotED != wantED {
t.Error("EnumType(Enum) mismatch")
}
}
}

View File

@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package protolegacy contains the default implementation for messages
// generated by protoc-gen-go.
//
// WARNING: This package should only ever be imported by the v1 proto package.
// The compatibility agreement covers nothing except for functionality needed
// to provide v1 interoperability. Breakages that occur due to unauthorized
// usages of this package are not the author's responsibility.
// Deprecated: Do not use.
package protolegacy
import "google.golang.org/protobuf/internal/legacy"
// TODO: Remove this.
var X legacy.Export
import "google.golang.org/protobuf/internal/impl"
var X impl.Export