// 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 (
	
	

	
	
	
)

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

func ( protoreflect.ExtensionType) *extensionFieldInfo {
	if ,  := .(*ExtensionInfo);  {
		.lazyInit()
		return .info
	}
	// Ideally we'd cache the resulting *extensionFieldInfo so we don't have to
	// recompute this metadata repeatedly. But without support for something like
	// weak references, such a cache would pin temporary values (like dynamic
	// extension types, constructed for the duration of a user request) to the
	// heap forever, causing memory usage of the cache to grow unbounded.
	// See discussion in https://github.com/golang/protobuf/issues/1521.
	return makeExtensionFieldInfo(.TypeDescriptor())
}

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(),
	}
	// 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 protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.EnumKind:
		.unmarshalNeedsValue = true
	default:
		if .Cardinality() == protoreflect.Repeated {
			.unmarshalNeedsValue = true
		}
	}
	return 
}

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

type ExtensionField struct {
	typ protoreflect.ExtensionType

	// value is either the value of GetValue,
	// or a *lazyExtensionValue that then returns the value of GetValue.
	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
}

// isUnexpandedLazy returns true if the ExensionField is lazy and not
// yet expanded, which means it's present and already checked for
// initialized required fields.
func ( *ExtensionField) () bool {
	return .lazy != nil && atomic.LoadUint32(&.lazy.atomicOnce) == 0
}

// lazyBuffer retrieves the buffer for a lazy extension if it's not yet expanded.
//
// The returned buffer has to be kept over whatever operation we're planning,
// as re-retrieving it will fail after the message is lazily decoded.
func ( *ExtensionField) () []byte {
	// This function might be in the critical path, so check the atomic without
	// taking a look first, then only take the lock if needed.
	if !.isUnexpandedLazy() {
		return nil
	}
	.lazy.mu.Lock()
	defer .lazy.mu.Unlock()
	return .lazy.b
}

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 {
		panic("No support for lazy fns for ExtensionField")
	}
	.lazy.xi = 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) ( protoreflect.ExtensionType,  protoreflect.Value) {
	.typ = 
	.value = 
	.lazy = nil
}

// Value returns the value of the extension field.
// This may be called concurrently.
func ( *ExtensionField) () protoreflect.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) () protoreflect.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 ( 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
}