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 (
	
	

	
	
	pref 
)

type extensionFieldInfo struct {
	wiretag             uint64
	tagsize             int
	unmarshalNeedsValue bool
	funcs               valueCoderFuncs
	validation          validationInfo
}

var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo

func ( pref.ExtensionType) *extensionFieldInfo {
	if ,  := .(*ExtensionInfo);  {
		.lazyInit()
		return .info
	}
	return legacyLoadExtensionFieldInfo()
}
legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt.
Does the unmarshal function need a value passed to it? This is true for composite types, where we pass in a message, list, or map to fill in, and for enums, where we pass in a prototype value to specify the concrete enum type.
	switch .Kind() {
	case pref.MessageKind, pref.GroupKind, pref.EnumKind:
		.unmarshalNeedsValue = true
	default:
		if .Cardinality() == pref.Repeated {
			.unmarshalNeedsValue = true
		}
	}
	return 
}

type lazyExtensionValue struct {
	atomicOnce uint32 // atomically set if value is valid
	mu         sync.Mutex
	xi         *extensionFieldInfo
	value      pref.Value
	b          []byte
	fn         func() pref.Value
}

type ExtensionField struct {
	typ pref.ExtensionType
value is either the value of GetValue, or a *lazyExtensionValue that then returns the value of GetValue.
	value pref.Value
	lazy  *lazyExtensionValue
}

func ( *ExtensionField) ( pref.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) ( pref.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)
}
Set sets the type and value of the extension field. This must not be called concurrently.
func ( *ExtensionField) ( pref.ExtensionType,  pref.Value) {
	.typ = 
	.value = 
	.lazy = nil
}
SetLazy sets the type and a value that is to be lazily evaluated upon first use. This must not be called concurrently.
func ( *ExtensionField) ( pref.ExtensionType,  func() pref.Value) {
	.typ = 
	.lazy = &lazyExtensionValue{fn: }
}
Value returns the value of the extension field. This may be called concurrently.
func ( *ExtensionField) () pref.Value {
	if .lazy != nil {
		if atomic.LoadUint32(&.lazy.atomicOnce) == 0 {
			.lazyInit()
		}
		return .lazy.value
	}
	return .value
}
Type returns the type of the extension field. This may be called concurrently.
func ( ExtensionField) () pref.ExtensionType {
	return .typ
}
IsSet returns whether the extension field is set. This may be called concurrently.
func ( ExtensionField) () bool {
	return .typ != nil
}
IsLazy reports whether a field is lazily encoded. It is exported for testing.
func ( pref.Message,  pref.FieldDescriptor) bool {
	var  *MessageInfo
	var  pointer
	switch m := .(type) {
	case *messageState:
		 = .messageInfo()
		 = .pointer()
	case *messageReflectWrapper:
		 = .messageInfo()
		 = .pointer()
	default:
		return false
	}
	,  := .(pref.ExtensionTypeDescriptor)
	if ! {
		return false
	}
	 := .Type()
	 := .extensionMap()
	if  == nil {
		return false
	}
	,  := (*)[int32(.Number())]
	if ! {
		return false
	}
	return .typ ==  && .lazy != nil && atomic.LoadUint32(&.lazy.atomicOnce) == 0