protobuf-go/internal/impl/extension.go

176 lines
4.9 KiB
Go
Raw Normal View History

all: unify protoV1.ExtensionDesc and proto.ExtensionType Change protoV1.ExtensionDesc to directly implement ExtensionType rather than delegating to one. Unify the previous types protoiface.ExtensionDescV1 and filetype.Extension in impl.ExtensionInfo. The protoV1.ExtensionDesc type becomes an alias to ExtensionInfo. This gives us: - Just one implementation of ExtensionType. - Generated foopb.E_Ext vars are canonical ExtensionTypes. - Generated foopb.E_Ext vars are also v1.ExtensionDescs for backwards compatibility. - Conversion between legacy and modern representations happens transparently when lazily initializing an ExtensionInfo. Overall, a simplification for users of generated code, since they can mostly ignore the ExtensionDesc/ExtentionType distinction and use the same value in either the old or new API. This is change 3/5 in a series of commits changing protoV1.ExtensionDesc to directly implement protoreflect.ExtensionType. 1. [v2] Add protoimpl.ExtensionInfo as an alias for protoiface.ExtensionDescV1. 2. [v1] Update references to protoimpl.ExtensionInfo to use protoiface.ExtensionInfo. 3. [v2] Create protoimpl.ExtensionInfo (an alias to a new type in the impl package) and remove protoiface.ExtensionDescV1. 4. [v1] Remove unneeded explicit conversions between ExtensionDesc and ExtensionType (since the former now directly implements the latter). 5. [v2] Remove stub conversion functions. Change-Id: I96ee890541ec11b2412e1a72c9d7b96e4d7f66b4 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/189563 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-08 15:45:59 -07:00
// 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 impl
import (
"reflect"
"sync"
"sync/atomic"
pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
)
// ExtensionInfo implements ExtensionType.
//
// This type contains a number of exported fields for legacy compatibility.
// The only non-deprecated use of this type is through the methods of the
// ExtensionType interface.
type ExtensionInfo struct {
// An ExtensionInfo may exist in several stages of initialization.
//
// extensionInfoUninitialized: Some or all of the legacy exported
// fields may be set, but none of the unexported fields have been
// initialized. This is the starting state for an ExtensionInfo
// in legacy generated code.
//
// extensionInfoDescInit: The desc and tdesc fields have been
// set, but the descriptor is not otherwise initialized. Legacy
// exported fields may or may not be set. This is the starting state
// for an ExtensionInfo in new generated code. Calling the Descriptor
// method will not trigger lazy initialization, although any other
// method will.
//
// extensionInfoFullInit: The ExtensionInfo is fully initialized.
// This state is only entered after lazy initialization is complete.
init uint32
mu sync.Mutex
desc pref.ExtensionDescriptor
tdesc extensionTypeDescriptor
goType reflect.Type
conv Converter
// ExtendedType is a typed nil-pointer to the parent message type that
// is being extended. It is possible for this to be unpopulated in v2
// since the message may no longer implement the MessageV1 interface.
//
// Deprecated: Use the ExtendedType method instead.
ExtendedType piface.MessageV1
// ExtensionType is zero value of the extension type.
//
// For historical reasons, reflect.TypeOf(ExtensionType) and Type.GoType
// may not be identical:
// * for scalars (except []byte), where ExtensionType uses *T,
// while Type.GoType uses T.
// * for repeated fields, where ExtensionType uses []T,
// while Type.GoType uses *[]T.
//
// Deprecated: Use the GoType method instead.
ExtensionType interface{}
// Field is the field number of the extension.
//
// Deprecated: Use the Descriptor().Number method instead.
Field int32
// Name is the fully qualified name of extension.
//
// Deprecated: Use the Descriptor().FullName method instead.
Name string
// Tag is the protobuf struct tag used in the v1 API.
//
// Deprecated: Do not use.
Tag string
// Filename is the proto filename in which the extension is defined.
//
// Deprecated: Use Descriptor().ParentFile().Path() instead.
Filename string
}
// Stages of initialization: See the ExtensionInfo.init field.
const (
extensionInfoUninitialized = 0
extensionInfoDescInit = 1
extensionInfoFullInit = 2
)
func InitExtensionInfo(xi *ExtensionInfo, xd pref.ExtensionDescriptor, goType reflect.Type) {
if xi.desc != nil {
return
}
xi.desc = xd
xi.goType = goType
xi.tdesc.ExtensionDescriptor = xi.desc
xi.tdesc.xi = xi
xi.init = extensionInfoDescInit
}
func (xi *ExtensionInfo) New() pref.Value {
return xi.lazyInit().New()
}
func (xi *ExtensionInfo) Zero() pref.Value {
return xi.lazyInit().Zero()
}
func (xi *ExtensionInfo) ValueOf(v interface{}) pref.Value {
return xi.lazyInit().PBValueOf(reflect.ValueOf(v))
}
func (xi *ExtensionInfo) InterfaceOf(v pref.Value) interface{} {
return xi.lazyInit().GoValueOf(v).Interface()
}
func (xi *ExtensionInfo) IsValidValue(v pref.Value) bool {
return xi.lazyInit().IsValidPB(v)
}
func (xi *ExtensionInfo) IsValidInterface(v interface{}) bool {
return xi.lazyInit().IsValidGo(reflect.ValueOf(v))
}
all: unify protoV1.ExtensionDesc and proto.ExtensionType Change protoV1.ExtensionDesc to directly implement ExtensionType rather than delegating to one. Unify the previous types protoiface.ExtensionDescV1 and filetype.Extension in impl.ExtensionInfo. The protoV1.ExtensionDesc type becomes an alias to ExtensionInfo. This gives us: - Just one implementation of ExtensionType. - Generated foopb.E_Ext vars are canonical ExtensionTypes. - Generated foopb.E_Ext vars are also v1.ExtensionDescs for backwards compatibility. - Conversion between legacy and modern representations happens transparently when lazily initializing an ExtensionInfo. Overall, a simplification for users of generated code, since they can mostly ignore the ExtensionDesc/ExtentionType distinction and use the same value in either the old or new API. This is change 3/5 in a series of commits changing protoV1.ExtensionDesc to directly implement protoreflect.ExtensionType. 1. [v2] Add protoimpl.ExtensionInfo as an alias for protoiface.ExtensionDescV1. 2. [v1] Update references to protoimpl.ExtensionInfo to use protoiface.ExtensionInfo. 3. [v2] Create protoimpl.ExtensionInfo (an alias to a new type in the impl package) and remove protoiface.ExtensionDescV1. 4. [v1] Remove unneeded explicit conversions between ExtensionDesc and ExtensionType (since the former now directly implements the latter). 5. [v2] Remove stub conversion functions. Change-Id: I96ee890541ec11b2412e1a72c9d7b96e4d7f66b4 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/189563 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-08 15:45:59 -07:00
func (xi *ExtensionInfo) GoType() reflect.Type {
xi.lazyInit()
return xi.goType
}
func (xi *ExtensionInfo) TypeDescriptor() pref.ExtensionTypeDescriptor {
all: unify protoV1.ExtensionDesc and proto.ExtensionType Change protoV1.ExtensionDesc to directly implement ExtensionType rather than delegating to one. Unify the previous types protoiface.ExtensionDescV1 and filetype.Extension in impl.ExtensionInfo. The protoV1.ExtensionDesc type becomes an alias to ExtensionInfo. This gives us: - Just one implementation of ExtensionType. - Generated foopb.E_Ext vars are canonical ExtensionTypes. - Generated foopb.E_Ext vars are also v1.ExtensionDescs for backwards compatibility. - Conversion between legacy and modern representations happens transparently when lazily initializing an ExtensionInfo. Overall, a simplification for users of generated code, since they can mostly ignore the ExtensionDesc/ExtentionType distinction and use the same value in either the old or new API. This is change 3/5 in a series of commits changing protoV1.ExtensionDesc to directly implement protoreflect.ExtensionType. 1. [v2] Add protoimpl.ExtensionInfo as an alias for protoiface.ExtensionDescV1. 2. [v1] Update references to protoimpl.ExtensionInfo to use protoiface.ExtensionInfo. 3. [v2] Create protoimpl.ExtensionInfo (an alias to a new type in the impl package) and remove protoiface.ExtensionDescV1. 4. [v1] Remove unneeded explicit conversions between ExtensionDesc and ExtensionType (since the former now directly implements the latter). 5. [v2] Remove stub conversion functions. Change-Id: I96ee890541ec11b2412e1a72c9d7b96e4d7f66b4 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/189563 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-08 15:45:59 -07:00
if atomic.LoadUint32(&xi.init) == extensionInfoUninitialized {
xi.lazyInitSlow()
}
return &xi.tdesc
}
func (xi *ExtensionInfo) lazyInit() Converter {
if atomic.LoadUint32(&xi.init) != extensionInfoFullInit {
xi.lazyInitSlow()
}
return xi.conv
}
func (xi *ExtensionInfo) lazyInitSlow() {
xi.mu.Lock()
defer xi.mu.Unlock()
if xi.init == extensionInfoFullInit {
return
}
atomic.StoreUint32(&xi.init, extensionInfoFullInit)
if xi.desc == nil {
xi.initFromLegacy()
} else if xi.desc.Cardinality() == pref.Repeated {
// Cardinality is initialized lazily, so we defer consulting it until here.
xi.goType = reflect.SliceOf(xi.goType)
all: unify protoV1.ExtensionDesc and proto.ExtensionType Change protoV1.ExtensionDesc to directly implement ExtensionType rather than delegating to one. Unify the previous types protoiface.ExtensionDescV1 and filetype.Extension in impl.ExtensionInfo. The protoV1.ExtensionDesc type becomes an alias to ExtensionInfo. This gives us: - Just one implementation of ExtensionType. - Generated foopb.E_Ext vars are canonical ExtensionTypes. - Generated foopb.E_Ext vars are also v1.ExtensionDescs for backwards compatibility. - Conversion between legacy and modern representations happens transparently when lazily initializing an ExtensionInfo. Overall, a simplification for users of generated code, since they can mostly ignore the ExtensionDesc/ExtentionType distinction and use the same value in either the old or new API. This is change 3/5 in a series of commits changing protoV1.ExtensionDesc to directly implement protoreflect.ExtensionType. 1. [v2] Add protoimpl.ExtensionInfo as an alias for protoiface.ExtensionDescV1. 2. [v1] Update references to protoimpl.ExtensionInfo to use protoiface.ExtensionInfo. 3. [v2] Create protoimpl.ExtensionInfo (an alias to a new type in the impl package) and remove protoiface.ExtensionDescV1. 4. [v1] Remove unneeded explicit conversions between ExtensionDesc and ExtensionType (since the former now directly implements the latter). 5. [v2] Remove stub conversion functions. Change-Id: I96ee890541ec11b2412e1a72c9d7b96e4d7f66b4 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/189563 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-08 15:45:59 -07:00
}
xi.conv = NewConverter(xi.goType, xi.desc)
xi.tdesc.ExtensionDescriptor = xi.desc
xi.tdesc.xi = xi
if xi.ExtensionType == nil {
xi.initToLegacy()
}
}
type extensionTypeDescriptor struct {
pref.ExtensionDescriptor
xi *ExtensionInfo
}
func (xtd *extensionTypeDescriptor) Type() pref.ExtensionType {
return xtd.xi
}
func (xtd *extensionTypeDescriptor) Descriptor() pref.ExtensionDescriptor {
return xtd.ExtensionDescriptor
}