package impl
import (
)
type extensionFieldInfo struct {
wiretag uint64
tagsize int
unmarshalNeedsValue bool
funcs valueCoderFuncs
validation validationInfo
}
var legacyExtensionFieldInfoCache sync.Map
func ( protoreflect.ExtensionType) *extensionFieldInfo {
if , := .(*ExtensionInfo); {
.lazyInit()
return .info
}
return legacyLoadExtensionFieldInfo()
}
func ( protoreflect.ExtensionType) *extensionFieldInfo {
if , := legacyExtensionFieldInfoCache.Load(); {
return .(*extensionFieldInfo)
}
:= makeExtensionFieldInfo(.TypeDescriptor())
if , := legacyMessageTypeCache.LoadOrStore(, ); {
return .(*extensionFieldInfo)
}
return
}
func ( protoreflect.ExtensionDescriptor) *extensionFieldInfo {
var uint64
if !.IsPacked() {
= protowire.EncodeTag(.Number(), wireTypes[.Kind()])
} else {
= protowire.EncodeTag(.Number(), protowire.BytesType)
}
:= &extensionFieldInfo{
wiretag: ,
tagsize: protowire.SizeVarint(),
funcs: encoderFuncsForValue(),
}
switch .Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.EnumKind:
.unmarshalNeedsValue = true
default:
if .Cardinality() == protoreflect.Repeated {
.unmarshalNeedsValue = true
}
}
return
}
type lazyExtensionValue struct {
atomicOnce uint32
mu sync.Mutex
xi *extensionFieldInfo
value protoreflect.Value
b []byte
fn func() protoreflect.Value
}
type ExtensionField struct {
typ protoreflect.ExtensionType
value protoreflect.Value
lazy *lazyExtensionValue
}
func ( *ExtensionField) ( protoreflect.ExtensionType, *extensionFieldInfo, protowire.Number, protowire.Type, []byte) {
if .lazy == nil {
.lazy = &lazyExtensionValue{xi: }
}
.typ =
.lazy.xi =
.lazy.b = protowire.AppendTag(.lazy.b, , )
.lazy.b = append(.lazy.b, ...)
}
func ( *ExtensionField) ( protoreflect.ExtensionType) bool {
if .typ == nil {
return true
}
if .typ == && .lazy != nil && atomic.LoadUint32(&.lazy.atomicOnce) == 0 {
return true
}
return false
}
func ( *ExtensionField) () {
.lazy.mu.Lock()
defer .lazy.mu.Unlock()
if atomic.LoadUint32(&.lazy.atomicOnce) == 1 {
return
}
if .lazy.xi != nil {
:= .lazy.b
:= .typ.New()
for len() > 0 {
var uint64
if [0] < 0x80 {
= uint64([0])
= [1:]
} else if len() >= 2 && [1] < 128 {
= uint64([0]&0x7f) + uint64([1])<<7
= [2:]
} else {
var int
, = protowire.ConsumeVarint()
if < 0 {
panic(errors.New("bad tag in lazy extension decoding"))
}
= [:]
}
:= protowire.Number( >> 3)
:= protowire.Type( & 7)
var unmarshalOutput
var error
, , = .lazy.xi.funcs.unmarshal(, , , , lazyUnmarshalOptions)
if != nil {
panic(errors.New("decode failure in lazy extension decoding: %v", ))
}
= [.n:]
}
.lazy.value =
} else {
.lazy.value = .lazy.fn()
}
.lazy.xi = nil
.lazy.fn = nil
.lazy.b = nil
atomic.StoreUint32(&.lazy.atomicOnce, 1)
}
func ( *ExtensionField) ( protoreflect.ExtensionType, protoreflect.Value) {
.typ =
.value =
.lazy = nil
}
func ( *ExtensionField) ( protoreflect.ExtensionType, func() protoreflect.Value) {
.typ =
.lazy = &lazyExtensionValue{fn: }
}
func ( *ExtensionField) () protoreflect.Value {
if .lazy != nil {
if atomic.LoadUint32(&.lazy.atomicOnce) == 0 {
.lazyInit()
}
return .lazy.value
}
return .value
}
func ( ExtensionField) () protoreflect.ExtensionType {
return .typ
}
func ( ExtensionField) () bool {
return .typ != nil
}
func ( protoreflect.Message, protoreflect.FieldDescriptor) bool {
var *MessageInfo
var pointer
switch m := .(type) {
case *messageState:
= .messageInfo()
= .pointer()
case *messageReflectWrapper:
= .messageInfo()
= .pointer()
default:
return false
}
, := .(protoreflect.ExtensionTypeDescriptor)
if ! {
return false
}
:= .Type()
:= .extensionMap()
if == nil {
return false
}
, := (*)[int32(.Number())]
if ! {
return false
}
return .typ == && .lazy != nil && atomic.LoadUint32(&.lazy.atomicOnce) == 0
}