mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-02-05 06:39:58 +00:00
internal/impl: handle legacy ExtensionDesc form
Add support for an ExtensionDesc with only Field populated as returned by protoV1.ExtensionDescs. Rather than panicking when TypeDescriptor is called, return a placeholder that preserves the name and/or number. Change-Id: I60352a7aec8ccd8a0c1fb08db5891043a441695f Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/193725 Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
6e095998ae
commit
bee625258d
@ -140,10 +140,12 @@ func (xi *ExtensionInfo) lazyInitSlow() {
|
||||
if xi.desc.ExtensionDescriptor == nil {
|
||||
xi.initFromLegacy()
|
||||
}
|
||||
if xi.ExtensionType == nil {
|
||||
xi.initToLegacy()
|
||||
if !xi.desc.ExtensionDescriptor.IsPlaceholder() {
|
||||
if xi.ExtensionType == nil {
|
||||
xi.initToLegacy()
|
||||
}
|
||||
xi.conv = NewConverter(xi.goType, xi.desc)
|
||||
}
|
||||
xi.conv = NewConverter(xi.goType, xi.desc)
|
||||
}
|
||||
|
||||
type extensionTypeDescriptor struct {
|
||||
|
@ -180,7 +180,7 @@ func (OneofMessage) isOneofUnion() {}
|
||||
|
||||
type AberrantEnum int32
|
||||
|
||||
func TestAberrant(t *testing.T) {
|
||||
func TestAberrantMessages(t *testing.T) {
|
||||
want := new(descriptorpb.DescriptorProto)
|
||||
if err := prototext.Unmarshal([]byte(`
|
||||
name: "AberrantMessage"
|
||||
@ -320,3 +320,34 @@ func TestAberrantRace(t *testing.T) {
|
||||
t.Errorf("mismatching exact message descriptors")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAberrantExtensions(t *testing.T) {
|
||||
tests := []struct {
|
||||
in *impl.ExtensionInfo
|
||||
wantName protoreflect.FullName
|
||||
wantNumber protoreflect.FieldNumber
|
||||
wantPlaceholder bool
|
||||
}{{
|
||||
in: &impl.ExtensionInfo{Field: 500},
|
||||
wantNumber: 500,
|
||||
wantPlaceholder: true,
|
||||
}, {
|
||||
in: &impl.ExtensionInfo{Name: "foo.bar.baz"},
|
||||
wantName: "foo.bar.baz",
|
||||
wantPlaceholder: true,
|
||||
}}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run("", func(t *testing.T) {
|
||||
xtd := tt.in.TypeDescriptor()
|
||||
switch {
|
||||
case xtd.FullName() != tt.wantName:
|
||||
t.Errorf("FullName() = %v, want %v", xtd.FullName(), tt.wantName)
|
||||
case xtd.Number() != tt.wantNumber:
|
||||
t.Errorf("Number() = %v, want %v", xtd.Number(), tt.wantNumber)
|
||||
case xtd.IsPlaceholder() != tt.wantPlaceholder:
|
||||
t.Errorf("IsPlaceholder() = %v, want %v", xtd.IsPlaceholder(), tt.wantPlaceholder)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,11 @@ package impl
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"google.golang.org/protobuf/internal/descopts"
|
||||
"google.golang.org/protobuf/internal/encoding/messageset"
|
||||
ptag "google.golang.org/protobuf/internal/encoding/tag"
|
||||
"google.golang.org/protobuf/internal/filedesc"
|
||||
"google.golang.org/protobuf/internal/pragma"
|
||||
pref "google.golang.org/protobuf/reflect/protoreflect"
|
||||
preg "google.golang.org/protobuf/reflect/protoregistry"
|
||||
piface "google.golang.org/protobuf/runtime/protoiface"
|
||||
@ -71,6 +73,17 @@ func (xi *ExtensionInfo) initToLegacy() {
|
||||
// initFromLegacy initializes an ExtensionInfo from
|
||||
// the contents of the deprecated exported fields of the type.
|
||||
func (xi *ExtensionInfo) initFromLegacy() {
|
||||
// The v1 API returns "type incomplete" descriptors where only the
|
||||
// field number is specified. In such a case, use a placeholder.
|
||||
if xi.ExtendedType == nil || xi.ExtensionType == nil {
|
||||
xd := placeholderExtension{
|
||||
name: pref.FullName(xi.Name),
|
||||
number: pref.FieldNumber(xi.Field),
|
||||
}
|
||||
xi.desc = extensionTypeDescriptor{xd, xi}
|
||||
return
|
||||
}
|
||||
|
||||
// Resolve enum or message dependencies.
|
||||
var ed pref.EnumDescriptor
|
||||
var md pref.MessageDescriptor
|
||||
@ -123,3 +136,38 @@ func (xi *ExtensionInfo) initFromLegacy() {
|
||||
xi.goType = tt
|
||||
xi.desc = extensionTypeDescriptor{xd, xi}
|
||||
}
|
||||
|
||||
type placeholderExtension struct {
|
||||
name pref.FullName
|
||||
number pref.FieldNumber
|
||||
}
|
||||
|
||||
func (x placeholderExtension) ParentFile() pref.FileDescriptor { return nil }
|
||||
func (x placeholderExtension) Parent() pref.Descriptor { return nil }
|
||||
func (x placeholderExtension) Index() int { return 0 }
|
||||
func (x placeholderExtension) Syntax() pref.Syntax { return 0 }
|
||||
func (x placeholderExtension) Name() pref.Name { return x.name.Name() }
|
||||
func (x placeholderExtension) FullName() pref.FullName { return x.name }
|
||||
func (x placeholderExtension) IsPlaceholder() bool { return true }
|
||||
func (x placeholderExtension) Options() pref.ProtoMessage { return descopts.Field }
|
||||
func (x placeholderExtension) Number() pref.FieldNumber { return x.number }
|
||||
func (x placeholderExtension) Cardinality() pref.Cardinality { return 0 }
|
||||
func (x placeholderExtension) Kind() pref.Kind { return 0 }
|
||||
func (x placeholderExtension) HasJSONName() bool { return false }
|
||||
func (x placeholderExtension) JSONName() string { return "" }
|
||||
func (x placeholderExtension) IsExtension() bool { return true }
|
||||
func (x placeholderExtension) IsWeak() bool { return false }
|
||||
func (x placeholderExtension) IsPacked() bool { return false }
|
||||
func (x placeholderExtension) IsList() bool { return false }
|
||||
func (x placeholderExtension) IsMap() bool { return false }
|
||||
func (x placeholderExtension) MapKey() pref.FieldDescriptor { return nil }
|
||||
func (x placeholderExtension) MapValue() pref.FieldDescriptor { return nil }
|
||||
func (x placeholderExtension) HasDefault() bool { return false }
|
||||
func (x placeholderExtension) Default() pref.Value { return pref.Value{} }
|
||||
func (x placeholderExtension) DefaultEnumValue() pref.EnumValueDescriptor { return nil }
|
||||
func (x placeholderExtension) ContainingOneof() pref.OneofDescriptor { return nil }
|
||||
func (x placeholderExtension) ContainingMessage() pref.MessageDescriptor { return nil }
|
||||
func (x placeholderExtension) Enum() pref.EnumDescriptor { return nil }
|
||||
func (x placeholderExtension) Message() pref.MessageDescriptor { return nil }
|
||||
func (x placeholderExtension) ProtoType(pref.FieldDescriptor) { return }
|
||||
func (x placeholderExtension) ProtoInternal(pragma.DoNotImplement) { return }
|
||||
|
Loading…
x
Reference in New Issue
Block a user