mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-03-10 16:14:39 +00:00
internal/impl: abstract away ExtensionDescV1 as the underlying descriptor
Add ExtensionField.{SetType,GetType} to hide the fact that the underlying descriptor is actually an ExtensionDescV1. Change-Id: I1d0595484ced0a88d2df0852a732fdf0fe9aa232 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/180538 Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
ea2076d064
commit
89d49632e5
@ -5,7 +5,11 @@
|
|||||||
package impl
|
package impl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"google.golang.org/protobuf/internal/encoding/wire"
|
"google.golang.org/protobuf/internal/encoding/wire"
|
||||||
|
pref "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
piface "google.golang.org/protobuf/runtime/protoiface"
|
piface "google.golang.org/protobuf/runtime/protoiface"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,29 +19,109 @@ type extensionFieldInfo struct {
|
|||||||
funcs ifaceCoderFuncs
|
funcs ifaceCoderFuncs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mi *MessageInfo) extensionFieldInfo(desc *piface.ExtensionDescV1) *extensionFieldInfo {
|
func (mi *MessageInfo) extensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
|
||||||
// As of this time (Go 1.12, linux/amd64), an RWMutex benchmarks as faster
|
// As of this time (Go 1.12, linux/amd64), an RWMutex benchmarks as faster
|
||||||
// than a sync.Map.
|
// than a sync.Map.
|
||||||
mi.extensionFieldInfosMu.RLock()
|
mi.extensionFieldInfosMu.RLock()
|
||||||
e, ok := mi.extensionFieldInfos[desc]
|
e, ok := mi.extensionFieldInfos[xt]
|
||||||
mi.extensionFieldInfosMu.RUnlock()
|
mi.extensionFieldInfosMu.RUnlock()
|
||||||
if ok {
|
if ok {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
etype := extensionTypeFromDesc(desc)
|
wiretag := wire.EncodeTag(xt.Number(), wireTypes[xt.Kind()])
|
||||||
wiretag := wire.EncodeTag(etype.Number(), wireTypes[etype.Kind()])
|
|
||||||
e = &extensionFieldInfo{
|
e = &extensionFieldInfo{
|
||||||
wiretag: wiretag,
|
wiretag: wiretag,
|
||||||
tagsize: wire.SizeVarint(wiretag),
|
tagsize: wire.SizeVarint(wiretag),
|
||||||
funcs: encoderFuncsForValue(etype, etype.GoType()),
|
funcs: encoderFuncsForValue(xt, xt.GoType()),
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.extensionFieldInfosMu.Lock()
|
mi.extensionFieldInfosMu.Lock()
|
||||||
if mi.extensionFieldInfos == nil {
|
if mi.extensionFieldInfos == nil {
|
||||||
mi.extensionFieldInfos = make(map[*piface.ExtensionDescV1]*extensionFieldInfo)
|
mi.extensionFieldInfos = make(map[pref.ExtensionType]*extensionFieldInfo)
|
||||||
}
|
}
|
||||||
mi.extensionFieldInfos[desc] = e
|
mi.extensionFieldInfos[xt] = e
|
||||||
mi.extensionFieldInfosMu.Unlock()
|
mi.extensionFieldInfosMu.Unlock()
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExtensionField struct {
|
||||||
|
// Desc is the descriptor information for the extension field.
|
||||||
|
// It must be populated if value is populated.
|
||||||
|
Desc *piface.ExtensionDescV1 // TODO: unexport and switch to protoreflect.ExtensionType
|
||||||
|
|
||||||
|
// value is either the value of GetValue,
|
||||||
|
// or a *lazyExtensionValue that then returns the value of GetValue.
|
||||||
|
value interface{} // TODO: switch to protoreflect.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f ExtensionField) HasType() bool {
|
||||||
|
return f.Desc != nil
|
||||||
|
}
|
||||||
|
func (f ExtensionField) GetType() pref.ExtensionType {
|
||||||
|
return legacyExtensionTypeFromDesc(f.Desc)
|
||||||
|
}
|
||||||
|
func (f *ExtensionField) SetType(t pref.ExtensionType) {
|
||||||
|
f.Desc = legacyExtensionDescFromType(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasValue reports whether a value is set for the extension field.
|
||||||
|
// This may be called concurrently.
|
||||||
|
func (f ExtensionField) HasValue() bool {
|
||||||
|
return f.value != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetValue returns the concrete value for the extension field.
|
||||||
|
// Let the type of Desc.ExtensionType be the "API type" and
|
||||||
|
// the type of GetValue be the "storage type".
|
||||||
|
// The API type and storage type are the same except:
|
||||||
|
// * for scalars (except []byte), where the API type uses *T,
|
||||||
|
// while the storage type uses T.
|
||||||
|
// * for repeated fields, where the API type uses []T,
|
||||||
|
// while the storage type uses *[]T.
|
||||||
|
//
|
||||||
|
// The reason for the divergence is so that the storage type more naturally
|
||||||
|
// matches what is expected of when retrieving the values through the
|
||||||
|
// protobuf reflection APIs.
|
||||||
|
//
|
||||||
|
// GetValue is only populated if Desc is also populated.
|
||||||
|
// This may be called concurrently.
|
||||||
|
//
|
||||||
|
// TODO: switch interface{} to protoreflect.Value
|
||||||
|
func (f ExtensionField) GetValue() interface{} {
|
||||||
|
if f, ok := f.value.(*lazyExtensionValue); ok {
|
||||||
|
return f.GetValue()
|
||||||
|
}
|
||||||
|
return f.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEagerValue sets the current value of the extension.
|
||||||
|
// This must not be called concurrently.
|
||||||
|
func (f *ExtensionField) SetEagerValue(v interface{}) {
|
||||||
|
f.value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLazyValue sets a value that is to be lazily evaluated upon first use.
|
||||||
|
// The returned value must not be nil.
|
||||||
|
// This must not be called concurrently.
|
||||||
|
func (f *ExtensionField) SetLazyValue(v func() interface{}) {
|
||||||
|
f.value = &lazyExtensionValue{value: v}
|
||||||
|
}
|
||||||
|
|
||||||
|
type lazyExtensionValue struct {
|
||||||
|
once uint32 // atomically set if value is valid
|
||||||
|
mu sync.Mutex // protects value
|
||||||
|
value interface{} // either the value itself or a func() interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *lazyExtensionValue) GetValue() interface{} {
|
||||||
|
if atomic.LoadUint32(&v.once) == 0 {
|
||||||
|
v.mu.Lock()
|
||||||
|
if f, ok := v.value.(func() interface{}); ok {
|
||||||
|
v.value = f()
|
||||||
|
}
|
||||||
|
atomic.StoreUint32(&v.once, 1)
|
||||||
|
v.mu.Unlock()
|
||||||
|
}
|
||||||
|
return v.value
|
||||||
|
}
|
||||||
|
@ -130,21 +130,21 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt
|
|||||||
return b, nerr.E
|
return b, nerr.E
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mi *MessageInfo) sizeExtensions(ext *legacyExtensionMap, opts marshalOptions) (n int) {
|
func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) {
|
||||||
if ext == nil {
|
if ext == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
for _, e := range *ext {
|
for _, x := range *ext {
|
||||||
ei := mi.extensionFieldInfo(e.Desc)
|
xi := mi.extensionFieldInfo(x.GetType())
|
||||||
if ei.funcs.size == nil {
|
if xi.funcs.size == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
n += ei.funcs.size(e.value, ei.tagsize, opts)
|
n += xi.funcs.size(x.GetValue(), xi.tagsize, opts)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mi *MessageInfo) appendExtensions(b []byte, ext *legacyExtensionMap, opts marshalOptions) ([]byte, error) {
|
func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, opts marshalOptions) ([]byte, error) {
|
||||||
if ext == nil {
|
if ext == nil {
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
@ -155,9 +155,9 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *legacyExtensionMap, opts
|
|||||||
case 1:
|
case 1:
|
||||||
// Fast-path for one extension: Don't bother sorting the keys.
|
// Fast-path for one extension: Don't bother sorting the keys.
|
||||||
var err error
|
var err error
|
||||||
for _, e := range *ext {
|
for _, x := range *ext {
|
||||||
ei := mi.extensionFieldInfo(e.Desc)
|
xi := mi.extensionFieldInfo(x.GetType())
|
||||||
b, err = ei.funcs.marshal(b, e.value, ei.wiretag, opts)
|
b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts)
|
||||||
}
|
}
|
||||||
return b, err
|
return b, err
|
||||||
default:
|
default:
|
||||||
@ -171,9 +171,9 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *legacyExtensionMap, opts
|
|||||||
var err error
|
var err error
|
||||||
var nerr errors.NonFatal
|
var nerr errors.NonFatal
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
e := (*ext)[int32(k)]
|
x := (*ext)[int32(k)]
|
||||||
ei := mi.extensionFieldInfo(e.Desc)
|
xi := mi.extensionFieldInfo(x.GetType())
|
||||||
b, err = ei.funcs.marshal(b, e.value, ei.wiretag, opts)
|
b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts)
|
||||||
if !nerr.Merge(err) {
|
if !nerr.Merge(err) {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
type legacyExtendedMessage struct {
|
type legacyExtendedMessage struct {
|
||||||
XXX_unrecognized []byte
|
XXX_unrecognized []byte
|
||||||
XXX_InternalExtensions map[int32]pimpl.ExtensionFieldV1
|
XXX_InternalExtensions map[int32]pimpl.ExtensionField
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*legacyExtendedMessage) Reset() {}
|
func (*legacyExtendedMessage) Reset() {}
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
|
|
||||||
type legacyTestMessage struct {
|
type legacyTestMessage struct {
|
||||||
XXX_unrecognized []byte
|
XXX_unrecognized []byte
|
||||||
XXX_InternalExtensions map[int32]pimpl.ExtensionFieldV1
|
XXX_InternalExtensions map[int32]pimpl.ExtensionField
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*legacyTestMessage) Reset() {}
|
func (*legacyTestMessage) Reset() {}
|
||||||
|
@ -48,7 +48,7 @@ type MessageInfo struct {
|
|||||||
sizecacheOffset offset
|
sizecacheOffset offset
|
||||||
unknownOffset offset
|
unknownOffset offset
|
||||||
extensionFieldInfosMu sync.RWMutex
|
extensionFieldInfosMu sync.RWMutex
|
||||||
extensionFieldInfos map[*piface.ExtensionDescV1]*extensionFieldInfo
|
extensionFieldInfos map[pref.ExtensionType]*extensionFieldInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefMessageType = reflect.TypeOf((*pref.Message)(nil)).Elem()
|
var prefMessageType = reflect.TypeOf((*pref.Message)(nil)).Elem()
|
||||||
|
@ -6,11 +6,8 @@ package impl
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
pref "google.golang.org/protobuf/reflect/protoreflect"
|
pref "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
piface "google.golang.org/protobuf/runtime/protoiface"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
|
func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
|
||||||
@ -26,7 +23,7 @@ func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extType = reflect.TypeOf(map[int32]ExtensionFieldV1{})
|
var extType = reflect.TypeOf(map[int32]ExtensionField{})
|
||||||
|
|
||||||
func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyExtensionMap {
|
func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyExtensionMap {
|
||||||
fx, _ := t.FieldByName("XXX_extensions")
|
fx, _ := t.FieldByName("XXX_extensions")
|
||||||
@ -40,7 +37,7 @@ func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyEx
|
|||||||
fieldOffset := offsetOf(fx)
|
fieldOffset := offsetOf(fx)
|
||||||
return func(p *messageDataType) *legacyExtensionMap {
|
return func(p *messageDataType) *legacyExtensionMap {
|
||||||
v := p.p.Apply(fieldOffset).AsValueOf(fx.Type).Interface()
|
v := p.p.Apply(fieldOffset).AsValueOf(fx.Type).Interface()
|
||||||
return (*legacyExtensionMap)(v.(*map[int32]ExtensionFieldV1))
|
return (*legacyExtensionMap)(v.(*map[int32]ExtensionField))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +47,7 @@ type legacyExtensionFields struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p legacyExtensionFields) Len() (n int) {
|
func (p legacyExtensionFields) Len() (n int) {
|
||||||
p.x.Range(func(num pref.FieldNumber, _ ExtensionFieldV1) bool {
|
p.x.Range(func(num pref.FieldNumber, _ ExtensionField) bool {
|
||||||
if p.Has(pref.FieldNumber(num)) {
|
if p.Has(pref.FieldNumber(num)) {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
@ -64,7 +61,7 @@ func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
|
|||||||
if !x.HasValue() {
|
if !x.HasValue() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
t := extensionTypeFromDesc(x.Desc)
|
t := x.GetType()
|
||||||
d := t.Descriptor()
|
d := t.Descriptor()
|
||||||
if d.IsList() {
|
if d.IsList() {
|
||||||
return t.ValueOf(x.GetValue()).List().Len() > 0
|
return t.ValueOf(x.GetValue()).List().Len() > 0
|
||||||
@ -74,10 +71,10 @@ func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
|
|||||||
|
|
||||||
func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
|
func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
|
||||||
x := p.x.Get(n)
|
x := p.x.Get(n)
|
||||||
if x.Desc == nil {
|
if !x.HasType() {
|
||||||
return pref.Value{}
|
return pref.Value{}
|
||||||
}
|
}
|
||||||
t := extensionTypeFromDesc(x.Desc)
|
t := x.GetType()
|
||||||
d := t.Descriptor()
|
d := t.Descriptor()
|
||||||
if !x.HasValue() {
|
if !x.HasValue() {
|
||||||
// NOTE: x.Value is never nil for Lists since they are always populated
|
// NOTE: x.Value is never nil for Lists since they are always populated
|
||||||
@ -92,20 +89,20 @@ func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
|
|||||||
|
|
||||||
func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
|
func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
|
||||||
x := p.x.Get(n)
|
x := p.x.Get(n)
|
||||||
if x.Desc == nil {
|
if !x.HasType() {
|
||||||
panic("no extension descriptor registered")
|
panic("no extension descriptor registered")
|
||||||
}
|
}
|
||||||
t := extensionTypeFromDesc(x.Desc)
|
t := x.GetType()
|
||||||
x.SetEagerValue(t.InterfaceOf(v))
|
x.SetEagerValue(t.InterfaceOf(v))
|
||||||
p.x.Set(n, x)
|
p.x.Set(n, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
|
func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
|
||||||
x := p.x.Get(n)
|
x := p.x.Get(n)
|
||||||
if x.Desc == nil {
|
if !x.HasType() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t := extensionTypeFromDesc(x.Desc)
|
t := x.GetType()
|
||||||
d := t.Descriptor()
|
d := t.Descriptor()
|
||||||
if d.IsList() {
|
if d.IsList() {
|
||||||
t.ValueOf(x.GetValue()).List().Truncate(0)
|
t.ValueOf(x.GetValue()).List().Truncate(0)
|
||||||
@ -120,7 +117,7 @@ func (p legacyExtensionFields) WhichOneof(pref.Name) pref.FieldNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
|
func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
|
||||||
p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool {
|
p.x.Range(func(n pref.FieldNumber, x ExtensionField) bool {
|
||||||
if p.Has(n) {
|
if p.Has(n) {
|
||||||
return f(n, p.Get(n))
|
return f(n, p.Get(n))
|
||||||
}
|
}
|
||||||
@ -130,10 +127,10 @@ func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool)
|
|||||||
|
|
||||||
func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
|
func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
|
||||||
x := p.x.Get(n)
|
x := p.x.Get(n)
|
||||||
if x.Desc == nil {
|
if !x.HasType() {
|
||||||
panic("no extension descriptor registered")
|
panic("no extension descriptor registered")
|
||||||
}
|
}
|
||||||
xt := extensionTypeFromDesc(x.Desc)
|
xt := x.GetType()
|
||||||
return xt.New().Message()
|
return xt.New().Message()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,8 +141,8 @@ func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
|
|||||||
type legacyExtensionTypes legacyExtensionFields
|
type legacyExtensionTypes legacyExtensionFields
|
||||||
|
|
||||||
func (p legacyExtensionTypes) Len() (n int) {
|
func (p legacyExtensionTypes) Len() (n int) {
|
||||||
p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
|
p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool {
|
||||||
if x.Desc != nil {
|
if x.HasType() {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -162,10 +159,10 @@ func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
|
|||||||
panic("invalid extension field number")
|
panic("invalid extension field number")
|
||||||
}
|
}
|
||||||
x := p.x.Get(d.Number())
|
x := p.x.Get(d.Number())
|
||||||
if x.Desc != nil {
|
if x.HasType() {
|
||||||
panic("extension descriptor already registered")
|
panic("extension descriptor already registered")
|
||||||
}
|
}
|
||||||
x.Desc = extensionDescFromType(t)
|
x.SetType(t)
|
||||||
if d.IsList() {
|
if d.IsList() {
|
||||||
// If the field is repeated, initialize the entry with an empty list
|
// If the field is repeated, initialize the entry with an empty list
|
||||||
// so that future Get operations can return a mutable and concrete list.
|
// so that future Get operations can return a mutable and concrete list.
|
||||||
@ -195,16 +192,16 @@ func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
|
|||||||
|
|
||||||
func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
|
func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
|
||||||
x := p.x.Get(n)
|
x := p.x.Get(n)
|
||||||
if x.Desc != nil {
|
if x.HasType() {
|
||||||
return extensionTypeFromDesc(x.Desc)
|
return x.GetType()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
|
func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
|
||||||
p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
|
p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool {
|
||||||
if x.Desc != nil && x.Desc.Name == string(s) {
|
if x.HasType() && x.GetType().FullName() == s {
|
||||||
t = extensionTypeFromDesc(x.Desc)
|
t = x.GetType()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -213,9 +210,9 @@ func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
|
func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
|
||||||
p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
|
p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool {
|
||||||
if x.Desc != nil {
|
if x.HasType() {
|
||||||
if !f(extensionTypeFromDesc(x.Desc)) {
|
if !f(x.GetType()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,106 +220,7 @@ func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
|
type legacyExtensionMap map[int32]ExtensionField
|
||||||
if xt, ok := typ.(interface {
|
|
||||||
ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
|
|
||||||
}); ok {
|
|
||||||
if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
|
|
||||||
return desc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Export{}.ExtensionDescFromType(typ)
|
|
||||||
}
|
|
||||||
|
|
||||||
func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
|
|
||||||
if desc.Type != nil {
|
|
||||||
return desc.Type
|
|
||||||
}
|
|
||||||
return Export{}.ExtensionTypeFromDesc(desc)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExtensionFieldV1 struct {
|
|
||||||
// TODO: We should turn this into a type alias to an unnamed type,
|
|
||||||
// which means that v1 can have the same struct, and we no longer have to
|
|
||||||
// export this from the v2 API.
|
|
||||||
|
|
||||||
// When an extension is stored in a message using SetExtension
|
|
||||||
// only desc and value are set. When the message is marshaled
|
|
||||||
// Raw will be set to the encoded form of the message.
|
|
||||||
//
|
|
||||||
// When a message is unmarshaled and contains extensions, each
|
|
||||||
// extension will have only Raw set. When such an extension is
|
|
||||||
// accessed using GetExtension (or GetExtensions) desc and value
|
|
||||||
// will be set.
|
|
||||||
Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
|
|
||||||
|
|
||||||
// value is either the value of GetValue,
|
|
||||||
// or a *lazyExtensionValue that then returns the value of GetValue.
|
|
||||||
value interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasValue reports whether a value is set for the extension field.
|
|
||||||
// This may be called concurrently.
|
|
||||||
func (f ExtensionFieldV1) HasValue() bool {
|
|
||||||
return f.value != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetValue returns the concrete value for the extension field.
|
|
||||||
// Let the type of Desc.ExtensionType be the "API type" and
|
|
||||||
// the type of GetValue be the "storage type".
|
|
||||||
// The API type and storage type are the same except:
|
|
||||||
// * for scalars (except []byte), where the API type uses *T,
|
|
||||||
// while the storage type uses T.
|
|
||||||
// * for repeated fields, where the API type uses []T,
|
|
||||||
// while the storage type uses *[]T.
|
|
||||||
//
|
|
||||||
// The reason for the divergence is so that the storage type more naturally
|
|
||||||
// matches what is expected of when retrieving the values through the
|
|
||||||
// protobuf reflection APIs.
|
|
||||||
//
|
|
||||||
// GetValue is only populated if Desc is also populated.
|
|
||||||
// This may be called concurrently.
|
|
||||||
//
|
|
||||||
// TODO: switch interface{} to protoreflect.Value
|
|
||||||
func (f ExtensionFieldV1) GetValue() interface{} {
|
|
||||||
if f, ok := f.value.(*lazyExtensionValue); ok {
|
|
||||||
return f.GetValue()
|
|
||||||
}
|
|
||||||
return f.value
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetEagerValue sets the current value of the extension.
|
|
||||||
// This must not be called concurrently.
|
|
||||||
func (f *ExtensionFieldV1) SetEagerValue(v interface{}) {
|
|
||||||
f.value = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLazyValue sets a value that is to be lazily evaluated upon first use.
|
|
||||||
// The returned value must not be nil.
|
|
||||||
// This must not be called concurrently.
|
|
||||||
func (f *ExtensionFieldV1) SetLazyValue(v func() interface{}) {
|
|
||||||
f.value = &lazyExtensionValue{value: v}
|
|
||||||
}
|
|
||||||
|
|
||||||
type lazyExtensionValue struct {
|
|
||||||
once uint32 // atomically set if value is valid
|
|
||||||
mu sync.Mutex // protects value
|
|
||||||
value interface{} // either the value itself or a func() interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *lazyExtensionValue) GetValue() interface{} {
|
|
||||||
if atomic.LoadUint32(&v.once) == 0 {
|
|
||||||
v.mu.Lock()
|
|
||||||
if f, ok := v.value.(func() interface{}); ok {
|
|
||||||
v.value = f()
|
|
||||||
}
|
|
||||||
atomic.StoreUint32(&v.once, 1)
|
|
||||||
v.mu.Unlock()
|
|
||||||
}
|
|
||||||
return v.value
|
|
||||||
}
|
|
||||||
|
|
||||||
type legacyExtensionMap map[int32]ExtensionFieldV1
|
|
||||||
|
|
||||||
func (m legacyExtensionMap) Len() int {
|
func (m legacyExtensionMap) Len() int {
|
||||||
return len(m)
|
return len(m)
|
||||||
@ -331,19 +229,19 @@ func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
|
|||||||
_, ok := m[int32(n)]
|
_, ok := m[int32(n)]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
|
func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionField {
|
||||||
return m[int32(n)]
|
return m[int32(n)]
|
||||||
}
|
}
|
||||||
func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
|
func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionField) {
|
||||||
if *m == nil {
|
if *m == nil {
|
||||||
*m = make(map[int32]ExtensionFieldV1)
|
*m = make(map[int32]ExtensionField)
|
||||||
}
|
}
|
||||||
(*m)[int32(n)] = x
|
(*m)[int32(n)] = x
|
||||||
}
|
}
|
||||||
func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
|
func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
|
||||||
delete(*m, int32(n))
|
delete(*m, int32(n))
|
||||||
}
|
}
|
||||||
func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
|
func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionField) bool) {
|
||||||
for n, x := range m {
|
for n, x := range m {
|
||||||
if !f(pref.FieldNumber(n), x) {
|
if !f(pref.FieldNumber(n), x) {
|
||||||
return
|
return
|
||||||
|
@ -98,8 +98,8 @@ func (p pointer) StringPtr() **string { return p.v.Interface().(**string) }
|
|||||||
func (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) }
|
func (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) }
|
||||||
func (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) }
|
func (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) }
|
||||||
func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) }
|
func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) }
|
||||||
func (p pointer) Extensions() *legacyExtensionMap {
|
func (p pointer) Extensions() *map[int32]ExtensionField {
|
||||||
return (*legacyExtensionMap)(p.v.Interface().(*map[int32]ExtensionFieldV1))
|
return p.v.Interface().(*map[int32]ExtensionField)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pointer) Elem() pointer {
|
func (p pointer) Elem() pointer {
|
||||||
|
@ -73,33 +73,33 @@ func (p pointer) AsIfaceOf(t reflect.Type) interface{} {
|
|||||||
return p.AsValueOf(t).Interface()
|
return p.AsValueOf(t).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pointer) Bool() *bool { return (*bool)(p.p) }
|
func (p pointer) Bool() *bool { return (*bool)(p.p) }
|
||||||
func (p pointer) BoolPtr() **bool { return (**bool)(p.p) }
|
func (p pointer) BoolPtr() **bool { return (**bool)(p.p) }
|
||||||
func (p pointer) BoolSlice() *[]bool { return (*[]bool)(p.p) }
|
func (p pointer) BoolSlice() *[]bool { return (*[]bool)(p.p) }
|
||||||
func (p pointer) Int32() *int32 { return (*int32)(p.p) }
|
func (p pointer) Int32() *int32 { return (*int32)(p.p) }
|
||||||
func (p pointer) Int32Ptr() **int32 { return (**int32)(p.p) }
|
func (p pointer) Int32Ptr() **int32 { return (**int32)(p.p) }
|
||||||
func (p pointer) Int32Slice() *[]int32 { return (*[]int32)(p.p) }
|
func (p pointer) Int32Slice() *[]int32 { return (*[]int32)(p.p) }
|
||||||
func (p pointer) Int64() *int64 { return (*int64)(p.p) }
|
func (p pointer) Int64() *int64 { return (*int64)(p.p) }
|
||||||
func (p pointer) Int64Ptr() **int64 { return (**int64)(p.p) }
|
func (p pointer) Int64Ptr() **int64 { return (**int64)(p.p) }
|
||||||
func (p pointer) Int64Slice() *[]int64 { return (*[]int64)(p.p) }
|
func (p pointer) Int64Slice() *[]int64 { return (*[]int64)(p.p) }
|
||||||
func (p pointer) Uint32() *uint32 { return (*uint32)(p.p) }
|
func (p pointer) Uint32() *uint32 { return (*uint32)(p.p) }
|
||||||
func (p pointer) Uint32Ptr() **uint32 { return (**uint32)(p.p) }
|
func (p pointer) Uint32Ptr() **uint32 { return (**uint32)(p.p) }
|
||||||
func (p pointer) Uint32Slice() *[]uint32 { return (*[]uint32)(p.p) }
|
func (p pointer) Uint32Slice() *[]uint32 { return (*[]uint32)(p.p) }
|
||||||
func (p pointer) Uint64() *uint64 { return (*uint64)(p.p) }
|
func (p pointer) Uint64() *uint64 { return (*uint64)(p.p) }
|
||||||
func (p pointer) Uint64Ptr() **uint64 { return (**uint64)(p.p) }
|
func (p pointer) Uint64Ptr() **uint64 { return (**uint64)(p.p) }
|
||||||
func (p pointer) Uint64Slice() *[]uint64 { return (*[]uint64)(p.p) }
|
func (p pointer) Uint64Slice() *[]uint64 { return (*[]uint64)(p.p) }
|
||||||
func (p pointer) Float32() *float32 { return (*float32)(p.p) }
|
func (p pointer) Float32() *float32 { return (*float32)(p.p) }
|
||||||
func (p pointer) Float32Ptr() **float32 { return (**float32)(p.p) }
|
func (p pointer) Float32Ptr() **float32 { return (**float32)(p.p) }
|
||||||
func (p pointer) Float32Slice() *[]float32 { return (*[]float32)(p.p) }
|
func (p pointer) Float32Slice() *[]float32 { return (*[]float32)(p.p) }
|
||||||
func (p pointer) Float64() *float64 { return (*float64)(p.p) }
|
func (p pointer) Float64() *float64 { return (*float64)(p.p) }
|
||||||
func (p pointer) Float64Ptr() **float64 { return (**float64)(p.p) }
|
func (p pointer) Float64Ptr() **float64 { return (**float64)(p.p) }
|
||||||
func (p pointer) Float64Slice() *[]float64 { return (*[]float64)(p.p) }
|
func (p pointer) Float64Slice() *[]float64 { return (*[]float64)(p.p) }
|
||||||
func (p pointer) String() *string { return (*string)(p.p) }
|
func (p pointer) String() *string { return (*string)(p.p) }
|
||||||
func (p pointer) StringPtr() **string { return (**string)(p.p) }
|
func (p pointer) StringPtr() **string { return (**string)(p.p) }
|
||||||
func (p pointer) StringSlice() *[]string { return (*[]string)(p.p) }
|
func (p pointer) StringSlice() *[]string { return (*[]string)(p.p) }
|
||||||
func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) }
|
func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) }
|
||||||
func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) }
|
func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) }
|
||||||
func (p pointer) Extensions() *legacyExtensionMap { return (*legacyExtensionMap)(p.p) }
|
func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }
|
||||||
|
|
||||||
func (p pointer) Elem() pointer {
|
func (p pointer) Elem() pointer {
|
||||||
return pointer{p: *(*unsafe.Pointer)(p.p)}
|
return pointer{p: *(*unsafe.Pointer)(p.p)}
|
||||||
|
@ -62,11 +62,11 @@ type (
|
|||||||
FileBuilder = fileinit.FileBuilder
|
FileBuilder = fileinit.FileBuilder
|
||||||
|
|
||||||
// TODO: Change these to more efficient data structures.
|
// TODO: Change these to more efficient data structures.
|
||||||
ExtensionFields = map[int32]impl.ExtensionFieldV1
|
ExtensionFields = map[int32]impl.ExtensionField
|
||||||
UnknownFields = []byte
|
UnknownFields = []byte
|
||||||
SizeCache = int32
|
SizeCache = int32
|
||||||
|
|
||||||
ExtensionFieldV1 = impl.ExtensionFieldV1
|
ExtensionFieldV1 = impl.ExtensionField
|
||||||
)
|
)
|
||||||
|
|
||||||
var X impl.Export
|
var X impl.Export
|
||||||
|
Loading…
x
Reference in New Issue
Block a user