From 89d49632e5cfc3deacea3376477821536d1d4c1e Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Tue, 4 Jun 2019 16:20:00 -0700 Subject: [PATCH] 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 --- internal/impl/codec_extension.go | 98 +++++++++++++- internal/impl/encode.go | 24 ++-- internal/impl/legacy_extension_test.go | 2 +- internal/impl/legacy_test.go | 2 +- internal/impl/message.go | 2 +- internal/impl/message_field_extension.go | 162 +++++------------------ internal/impl/pointer_reflect.go | 4 +- internal/impl/pointer_unsafe.go | 54 ++++---- runtime/protoimpl/impl.go | 4 +- 9 files changed, 167 insertions(+), 185 deletions(-) diff --git a/internal/impl/codec_extension.go b/internal/impl/codec_extension.go index 714dec77..69d5a96f 100644 --- a/internal/impl/codec_extension.go +++ b/internal/impl/codec_extension.go @@ -5,7 +5,11 @@ package impl import ( + "sync" + "sync/atomic" + "google.golang.org/protobuf/internal/encoding/wire" + pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) @@ -15,29 +19,109 @@ type extensionFieldInfo struct { 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 // than a sync.Map. mi.extensionFieldInfosMu.RLock() - e, ok := mi.extensionFieldInfos[desc] + e, ok := mi.extensionFieldInfos[xt] mi.extensionFieldInfosMu.RUnlock() if ok { return e } - etype := extensionTypeFromDesc(desc) - wiretag := wire.EncodeTag(etype.Number(), wireTypes[etype.Kind()]) + wiretag := wire.EncodeTag(xt.Number(), wireTypes[xt.Kind()]) e = &extensionFieldInfo{ wiretag: wiretag, tagsize: wire.SizeVarint(wiretag), - funcs: encoderFuncsForValue(etype, etype.GoType()), + funcs: encoderFuncsForValue(xt, xt.GoType()), } mi.extensionFieldInfosMu.Lock() 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() 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 +} diff --git a/internal/impl/encode.go b/internal/impl/encode.go index e3ba7cff..52ad7996 100644 --- a/internal/impl/encode.go +++ b/internal/impl/encode.go @@ -130,21 +130,21 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt 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 { return 0 } - for _, e := range *ext { - ei := mi.extensionFieldInfo(e.Desc) - if ei.funcs.size == nil { + for _, x := range *ext { + xi := mi.extensionFieldInfo(x.GetType()) + if xi.funcs.size == nil { continue } - n += ei.funcs.size(e.value, ei.tagsize, opts) + n += xi.funcs.size(x.GetValue(), xi.tagsize, opts) } 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 { return b, nil } @@ -155,9 +155,9 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *legacyExtensionMap, opts case 1: // Fast-path for one extension: Don't bother sorting the keys. var err error - for _, e := range *ext { - ei := mi.extensionFieldInfo(e.Desc) - b, err = ei.funcs.marshal(b, e.value, ei.wiretag, opts) + for _, x := range *ext { + xi := mi.extensionFieldInfo(x.GetType()) + b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts) } return b, err default: @@ -171,9 +171,9 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *legacyExtensionMap, opts var err error var nerr errors.NonFatal for _, k := range keys { - e := (*ext)[int32(k)] - ei := mi.extensionFieldInfo(e.Desc) - b, err = ei.funcs.marshal(b, e.value, ei.wiretag, opts) + x := (*ext)[int32(k)] + xi := mi.extensionFieldInfo(x.GetType()) + b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts) if !nerr.Merge(err) { return b, err } diff --git a/internal/impl/legacy_extension_test.go b/internal/impl/legacy_extension_test.go index 13a2c6d5..6ccfa40c 100644 --- a/internal/impl/legacy_extension_test.go +++ b/internal/impl/legacy_extension_test.go @@ -18,7 +18,7 @@ import ( type legacyExtendedMessage struct { XXX_unrecognized []byte - XXX_InternalExtensions map[int32]pimpl.ExtensionFieldV1 + XXX_InternalExtensions map[int32]pimpl.ExtensionField } func (*legacyExtendedMessage) Reset() {} diff --git a/internal/impl/legacy_test.go b/internal/impl/legacy_test.go index d6ca9418..c1ba55eb 100644 --- a/internal/impl/legacy_test.go +++ b/internal/impl/legacy_test.go @@ -27,7 +27,7 @@ import ( type legacyTestMessage struct { XXX_unrecognized []byte - XXX_InternalExtensions map[int32]pimpl.ExtensionFieldV1 + XXX_InternalExtensions map[int32]pimpl.ExtensionField } func (*legacyTestMessage) Reset() {} diff --git a/internal/impl/message.go b/internal/impl/message.go index d64ee7fa..6db60f12 100644 --- a/internal/impl/message.go +++ b/internal/impl/message.go @@ -48,7 +48,7 @@ type MessageInfo struct { sizecacheOffset offset unknownOffset offset extensionFieldInfosMu sync.RWMutex - extensionFieldInfos map[*piface.ExtensionDescV1]*extensionFieldInfo + extensionFieldInfos map[pref.ExtensionType]*extensionFieldInfo } var prefMessageType = reflect.TypeOf((*pref.Message)(nil)).Elem() diff --git a/internal/impl/message_field_extension.go b/internal/impl/message_field_extension.go index 3c403af9..b5377757 100644 --- a/internal/impl/message_field_extension.go +++ b/internal/impl/message_field_extension.go @@ -6,11 +6,8 @@ package impl import ( "reflect" - "sync" - "sync/atomic" pref "google.golang.org/protobuf/reflect/protoreflect" - piface "google.golang.org/protobuf/runtime/protoiface" ) 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 { fx, _ := t.FieldByName("XXX_extensions") @@ -40,7 +37,7 @@ func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyEx fieldOffset := offsetOf(fx) return func(p *messageDataType) *legacyExtensionMap { 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) { - p.x.Range(func(num pref.FieldNumber, _ ExtensionFieldV1) bool { + p.x.Range(func(num pref.FieldNumber, _ ExtensionField) bool { if p.Has(pref.FieldNumber(num)) { n++ } @@ -64,7 +61,7 @@ func (p legacyExtensionFields) Has(n pref.FieldNumber) bool { if !x.HasValue() { return false } - t := extensionTypeFromDesc(x.Desc) + t := x.GetType() d := t.Descriptor() if d.IsList() { 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 { x := p.x.Get(n) - if x.Desc == nil { + if !x.HasType() { return pref.Value{} } - t := extensionTypeFromDesc(x.Desc) + t := x.GetType() d := t.Descriptor() if !x.HasValue() { // 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) { x := p.x.Get(n) - if x.Desc == nil { + if !x.HasType() { panic("no extension descriptor registered") } - t := extensionTypeFromDesc(x.Desc) + t := x.GetType() x.SetEagerValue(t.InterfaceOf(v)) p.x.Set(n, x) } func (p legacyExtensionFields) Clear(n pref.FieldNumber) { x := p.x.Get(n) - if x.Desc == nil { + if !x.HasType() { return } - t := extensionTypeFromDesc(x.Desc) + t := x.GetType() d := t.Descriptor() if d.IsList() { 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) { - p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool { + p.x.Range(func(n pref.FieldNumber, x ExtensionField) bool { if p.Has(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 { x := p.x.Get(n) - if x.Desc == nil { + if !x.HasType() { panic("no extension descriptor registered") } - xt := extensionTypeFromDesc(x.Desc) + xt := x.GetType() return xt.New().Message() } @@ -144,8 +141,8 @@ func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes { type legacyExtensionTypes legacyExtensionFields func (p legacyExtensionTypes) Len() (n int) { - p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool { - if x.Desc != nil { + p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool { + if x.HasType() { n++ } return true @@ -162,10 +159,10 @@ func (p legacyExtensionTypes) Register(t pref.ExtensionType) { panic("invalid extension field number") } x := p.x.Get(d.Number()) - if x.Desc != nil { + if x.HasType() { panic("extension descriptor already registered") } - x.Desc = extensionDescFromType(t) + x.SetType(t) if d.IsList() { // If the field is repeated, initialize the entry with an empty 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 { x := p.x.Get(n) - if x.Desc != nil { - return extensionTypeFromDesc(x.Desc) + if x.HasType() { + return x.GetType() } return nil } func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) { - p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool { - if x.Desc != nil && x.Desc.Name == string(s) { - t = extensionTypeFromDesc(x.Desc) + p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool { + if x.HasType() && x.GetType().FullName() == s { + t = x.GetType() return false } 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) { - p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool { - if x.Desc != nil { - if !f(extensionTypeFromDesc(x.Desc)) { + p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool { + if x.HasType() { + if !f(x.GetType()) { return false } } @@ -223,106 +220,7 @@ func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) { }) } -func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 { - 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 +type legacyExtensionMap map[int32]ExtensionField func (m legacyExtensionMap) Len() int { return len(m) @@ -331,19 +229,19 @@ func (m legacyExtensionMap) Has(n pref.FieldNumber) bool { _, ok := m[int32(n)] return ok } -func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 { +func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionField { 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 { - *m = make(map[int32]ExtensionFieldV1) + *m = make(map[int32]ExtensionField) } (*m)[int32(n)] = x } func (m *legacyExtensionMap) Clear(n pref.FieldNumber) { 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 { if !f(pref.FieldNumber(n), x) { return diff --git a/internal/impl/pointer_reflect.go b/internal/impl/pointer_reflect.go index b851b1b0..207c20bf 100644 --- a/internal/impl/pointer_reflect.go +++ b/internal/impl/pointer_reflect.go @@ -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) Bytes() *[]byte { return p.v.Interface().(*[]byte) } func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) } -func (p pointer) Extensions() *legacyExtensionMap { - return (*legacyExtensionMap)(p.v.Interface().(*map[int32]ExtensionFieldV1)) +func (p pointer) Extensions() *map[int32]ExtensionField { + return p.v.Interface().(*map[int32]ExtensionField) } func (p pointer) Elem() pointer { diff --git a/internal/impl/pointer_unsafe.go b/internal/impl/pointer_unsafe.go index f04a5615..39f1995e 100644 --- a/internal/impl/pointer_unsafe.go +++ b/internal/impl/pointer_unsafe.go @@ -73,33 +73,33 @@ func (p pointer) AsIfaceOf(t reflect.Type) interface{} { return p.AsValueOf(t).Interface() } -func (p pointer) Bool() *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) Int32() *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) Int64() *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) Uint32() *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) Uint64() *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) Float32() *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) Float64() *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) String() *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) Bytes() *[]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) Bool() *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) Int32() *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) Int64() *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) Uint32() *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) Uint64() *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) Float32() *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) Float64() *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) String() *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) Bytes() *[]byte { return (*[]byte)(p.p) } +func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) } +func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) } func (p pointer) Elem() pointer { return pointer{p: *(*unsafe.Pointer)(p.p)} diff --git a/runtime/protoimpl/impl.go b/runtime/protoimpl/impl.go index fac3cfce..e28bfc20 100644 --- a/runtime/protoimpl/impl.go +++ b/runtime/protoimpl/impl.go @@ -62,11 +62,11 @@ type ( FileBuilder = fileinit.FileBuilder // TODO: Change these to more efficient data structures. - ExtensionFields = map[int32]impl.ExtensionFieldV1 + ExtensionFields = map[int32]impl.ExtensionField UnknownFields = []byte SizeCache = int32 - ExtensionFieldV1 = impl.ExtensionFieldV1 + ExtensionFieldV1 = impl.ExtensionField ) var X impl.Export