// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors.  All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package proto

/*
 * Types and routines for supporting protocol buffer extensions.
 */

import (
	
	
	
	
	
	
)

// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
var ErrMissingExtension = errors.New("proto: missing extension")

// ExtensionRange represents a range of message extensions for a protocol buffer.
// Used in code generated by the protocol compiler.
type ExtensionRange struct {
	Start, End int32 // both inclusive
}

// extendableProto is an interface implemented by any protocol buffer generated by the current
// proto compiler that may be extended.
type extendableProto interface {
	Message
	ExtensionRangeArray() []ExtensionRange
	extensionsWrite() map[int32]Extension
	extensionsRead() (map[int32]Extension, sync.Locker)
}

// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
// version of the proto compiler that may be extended.
type extendableProtoV1 interface {
	Message
	ExtensionRangeArray() []ExtensionRange
	ExtensionMap() map[int32]Extension
}

// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
type extensionAdapter struct {
	extendableProtoV1
}

func ( extensionAdapter) () map[int32]Extension {
	return .ExtensionMap()
}

func ( extensionAdapter) () (map[int32]Extension, sync.Locker) {
	return .ExtensionMap(), notLocker{}
}

// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
type notLocker struct{}

func ( notLocker) ()   {}
func ( notLocker) () {}

// extendable returns the extendableProto interface for the given generated proto message.
// If the proto message has the old extension format, it returns a wrapper that implements
// the extendableProto interface.
func extendable( interface{}) (extendableProto, error) {
	switch p := .(type) {
	case extendableProto:
		if isNilPtr() {
			return nil, fmt.Errorf("proto: nil %T is not extendable", )
		}
		return , nil
	case extendableProtoV1:
		if isNilPtr() {
			return nil, fmt.Errorf("proto: nil %T is not extendable", )
		}
		return extensionAdapter{}, nil
	case extensionsBytes:
		return slowExtensionAdapter{}, nil
	}
	// Don't allocate a specific error containing %T:
	// this is the hot path for Clone and MarshalText.
	return nil, errNotExtendable
}

var errNotExtendable = errors.New("proto: not an extendable proto.Message")

func isNilPtr( interface{}) bool {
	 := reflect.ValueOf()
	return .Kind() == reflect.Ptr && .IsNil()
}

// XXX_InternalExtensions is an internal representation of proto extensions.
//
// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
//
// The methods of XXX_InternalExtensions are not concurrency safe in general,
// but calls to logically read-only methods such as has and get may be executed concurrently.
type XXX_InternalExtensions struct {
	// The struct must be indirect so that if a user inadvertently copies a
	// generated message and its embedded XXX_InternalExtensions, they
	// avoid the mayhem of a copied mutex.
	//
	// The mutex serializes all logically read-only operations to p.extensionMap.
	// It is up to the client to ensure that write operations to p.extensionMap are
	// mutually exclusive with other accesses.
	p *struct {
		mu           sync.Mutex
		extensionMap map[int32]Extension
	}
}

// extensionsWrite returns the extension map, creating it on first use.
func ( *XXX_InternalExtensions) () map[int32]Extension {
	if .p == nil {
		.p = new(struct {
			           sync.Mutex
			 map[int32]Extension
		})
		.p.extensionMap = make(map[int32]Extension)
	}
	return .p.extensionMap
}

// extensionsRead returns the extensions map for read-only use.  It may be nil.
// The caller must hold the returned mutex's lock when accessing Elements within the map.
func ( *XXX_InternalExtensions) () (map[int32]Extension, sync.Locker) {
	if .p == nil {
		return nil, nil
	}
	return .p.extensionMap, &.p.mu
}

// ExtensionDesc represents an extension specification.
// Used in generated code from the protocol compiler.
type ExtensionDesc struct {
	ExtendedType  Message     // nil pointer to the type that is being extended
	ExtensionType interface{} // nil pointer to the extension type
	Field         int32       // field number
	Name          string      // fully-qualified name of extension, for text formatting
	Tag           string      // protobuf tag style
	Filename      string      // name of the file in which the extension is defined
}

func ( *ExtensionDesc) () bool {
	 := reflect.TypeOf(.ExtensionType)
	return .Kind() == reflect.Slice && .Elem().Kind() != reflect.Uint8
}

// Extension represents an extension in a message.
type Extension struct {
	// When an extension is stored in a message using SetExtension
	// only desc and value are set. When the message is marshaled
	// enc will be set to the encoded form of the message.
	//
	// When a message is unmarshaled and contains extensions, each
	// extension will have only enc set. When such an extension is
	// accessed using GetExtension (or GetExtensions) desc and value
	// will be set.
	desc  *ExtensionDesc
	value interface{}
	enc   []byte
}

// SetRawExtension is for testing only.
func ( Message,  int32,  []byte) {
	if ,  := .(extensionsBytes);  {
		clearExtension(, )
		 := .GetExtensions()
		* = append(*, ...)
		return
	}
	,  := extendable()
	if  != nil {
		return
	}
	 := .extensionsWrite()
	[] = Extension{enc: }
}

// isExtensionField returns true iff the given field number is in an extension range.
func isExtensionField( extendableProto,  int32) bool {
	for ,  := range .ExtensionRangeArray() {
		if .Start <=  &&  <= .End {
			return true
		}
	}
	return false
}

// checkExtensionTypes checks that the given extension is valid for pb.
func checkExtensionTypes( extendableProto,  *ExtensionDesc) error {
	var  interface{} = 
	// Check the extended type.
	if ,  := .(extensionAdapter);  {
		 = .extendableProtoV1
	}
	if ,  := .(slowExtensionAdapter);  {
		 = .extensionsBytes
	}
	if ,  := reflect.TypeOf(), reflect.TypeOf(.ExtendedType);  !=  {
		return fmt.Errorf("proto: bad extended type; %v does not extend %v", , )
	}
	// Check the range.
	if !isExtensionField(, .Field) {
		return errors.New("proto: bad extension number; not in declared ranges")
	}
	return nil
}

// extPropKey is sufficient to uniquely identify an extension.
type extPropKey struct {
	base  reflect.Type
	field int32
}

var extProp = struct {
	sync.RWMutex
	m map[extPropKey]*Properties
}{
	m: make(map[extPropKey]*Properties),
}

func extensionProperties( *ExtensionDesc) *Properties {
	 := extPropKey{base: reflect.TypeOf(.ExtendedType), field: .Field}

	extProp.RLock()
	if ,  := extProp.m[];  {
		extProp.RUnlock()
		return 
	}
	extProp.RUnlock()

	extProp.Lock()
	defer extProp.Unlock()
	// Check again.
	if ,  := extProp.m[];  {
		return 
	}

	 := new(Properties)
	.Init(reflect.TypeOf(.ExtensionType), "unknown_name", .Tag, nil)
	extProp.m[] = 
	return 
}

// HasExtension returns whether the given extension is present in pb.
func ( Message,  *ExtensionDesc) bool {
	if ,  := .(extensionsBytes);  {
		 := .GetExtensions()
		 := *
		 := 0
		for  < len() {
			,  := DecodeVarint([:])
			 := int32( >> 3)
			if int32() == .Field {
				return true
			}
			 := int( & 0x7)
			 += 
			,  := size([:], )
			if  != nil {
				return false
			}
			 += 
		}
		return false
	}
	// TODO: Check types, field numbers, etc.?
	,  := extendable()
	if  != nil {
		return false
	}
	,  := .extensionsRead()
	if  == nil {
		return false
	}
	.Lock()
	,  := [.Field]
	.Unlock()
	return 
}

// ClearExtension removes the given extension from pb.
func ( Message,  *ExtensionDesc) {
	clearExtension(, .Field)
}

func clearExtension( Message,  int32) {
	if ,  := .(extensionsBytes);  {
		 := 0
		for  != -1 {
			 = deleteExtension(, , )
		}
		return
	}
	,  := extendable()
	if  != nil {
		return
	}
	// TODO: Check types, field numbers, etc.?
	 := .extensionsWrite()
	delete(, )
}

// GetExtension retrieves a proto2 extended field from pb.
//
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
// then GetExtension parses the encoded field and returns a Go value of the specified type.
// If the field is not present, then the default value is returned (if one is specified),
// otherwise ErrMissingExtension is reported.
//
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
// then GetExtension returns the raw encoded bytes of the field extension.
func ( Message,  *ExtensionDesc) (interface{}, error) {
	if ,  := .(extensionsBytes);  {
		 := .GetExtensions()
		return decodeExtensionFromBytes(, *)
	}

	,  := extendable()
	if  != nil {
		return nil, 
	}

	if .ExtendedType != nil {
		// can only check type if this is a complete descriptor
		if  := checkExtensionTypes(, );  != nil {
			return nil, 
		}
	}

	,  := .extensionsRead()
	if  == nil {
		return defaultExtensionValue()
	}
	.Lock()
	defer .Unlock()
	,  := [.Field]
	if ! {
		// defaultExtensionValue returns the default value or
		// ErrMissingExtension if there is no default.
		return defaultExtensionValue()
	}

	if .value != nil {
		// Already decoded. Check the descriptor, though.
		if .desc !=  {
			// This shouldn't happen. If it does, it means that
			// GetExtension was called twice with two different
			// descriptors with the same field number.
			return nil, errors.New("proto: descriptor conflict")
		}
		return .value, nil
	}

	if .ExtensionType == nil {
		// incomplete descriptor
		return .enc, nil
	}

	,  := decodeExtension(.enc, )
	if  != nil {
		return nil, 
	}

	// Remember the decoded version and drop the encoded version.
	// That way it is safe to mutate what we return.
	.value = 
	.desc = 
	.enc = nil
	[.Field] = 
	return .value, nil
}

// defaultExtensionValue returns the default value for extension.
// If no default for an extension is defined ErrMissingExtension is returned.
func defaultExtensionValue( *ExtensionDesc) (interface{}, error) {
	if .ExtensionType == nil {
		// incomplete descriptor, so no default
		return nil, ErrMissingExtension
	}

	 := reflect.TypeOf(.ExtensionType)
	 := extensionProperties()

	, ,  := fieldDefault(, )
	if  != nil {
		return nil, 
	}

	if  == nil || .value == nil {
		// There is no default value.
		return nil, ErrMissingExtension
	}

	if .Kind() != reflect.Ptr {
		// We do not need to return a Ptr, we can directly return sf.value.
		return .value, nil
	}

	// We need to return an interface{} that is a pointer to sf.value.
	 := reflect.New().Elem()
	.Set(reflect.New(.Type().Elem()))
	if .kind == reflect.Int32 {
		// We may have an int32 or an enum, but the underlying data is int32.
		// Since we can't set an int32 into a non int32 reflect.value directly
		// set it as a int32.
		.Elem().SetInt(int64(.value.(int32)))
	} else {
		.Elem().Set(reflect.ValueOf(.value))
	}
	return .Interface(), nil
}

// decodeExtension decodes an extension encoded in b.
func decodeExtension( []byte,  *ExtensionDesc) (interface{}, error) {
	 := reflect.TypeOf(.ExtensionType)
	 := typeUnmarshaler(, .Tag)

	// t is a pointer to a struct, pointer to basic type or a slice.
	// Allocate space to store the pointer/slice.
	 := reflect.New().Elem()

	var  error
	for {
		,  := decodeVarint()
		if  == 0 {
			return nil, io.ErrUnexpectedEOF
		}
		 = [:]
		 := int() & 7

		,  = (, valToPointer(.Addr()), )
		if  != nil {
			return nil, 
		}

		if len() == 0 {
			break
		}
	}
	return .Interface(), nil
}

// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
// The returned slice has the same length as es; missing extensions will appear as nil elements.
func ( Message,  []*ExtensionDesc) ( []interface{},  error) {
	,  := extendable()
	if  != nil {
		return nil, 
	}
	 = make([]interface{}, len())
	for ,  := range  {
		[],  = GetExtension(, )
		if  == ErrMissingExtension {
			 = nil
		}
		if  != nil {
			return
		}
	}
	return
}

// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
// just the Field field, which defines the extension's field number.
func ( Message) ([]*ExtensionDesc, error) {
	,  := extendable()
	if  != nil {
		return nil, 
	}
	 := RegisteredExtensions()

	,  := .extensionsRead()
	if  == nil {
		return nil, nil
	}
	.Lock()
	defer .Unlock()
	 := make([]*ExtensionDesc, 0, len())
	for ,  := range  {
		 := .desc
		if  == nil {
			 = []
			if  == nil {
				 = &ExtensionDesc{Field: }
			}
		}

		 = append(, )
	}
	return , nil
}

// SetExtension sets the specified extension of pb to the specified value.
func ( Message,  *ExtensionDesc,  interface{}) error {
	if ,  := .(extensionsBytes);  {
		ClearExtension(, )
		,  := encodeExtension(, )
		if  != nil {
			return 
		}
		 := .GetExtensions()
		* = append(*, ...)
		return nil
	}
	,  := extendable()
	if  != nil {
		return 
	}
	if  := checkExtensionTypes(, );  != nil {
		return 
	}
	 := reflect.TypeOf(.ExtensionType)
	if  != reflect.TypeOf() {
		return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", , .ExtensionType)
	}
	// nil extension values need to be caught early, because the
	// encoder can't distinguish an ErrNil due to a nil extension
	// from an ErrNil due to a missing field. Extensions are
	// always optional, so the encoder would just swallow the error
	// and drop all the extensions from the encoded message.
	if reflect.ValueOf().IsNil() {
		return fmt.Errorf("proto: SetExtension called with nil value of type %T", )
	}

	 := .extensionsWrite()
	[.Field] = Extension{desc: , value: }
	return nil
}

// ClearAllExtensions clears all extensions from pb.
func ( Message) {
	if ,  := .(extensionsBytes);  {
		 := .GetExtensions()
		* = []byte{}
		return
	}
	,  := extendable()
	if  != nil {
		return
	}
	 := .extensionsWrite()
	for  := range  {
		delete(, )
	}
}

// A global registry of extensions.
// The generated code will register the generated descriptors by calling RegisterExtension.

var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)

// RegisterExtension is called from the generated code.
func ( *ExtensionDesc) {
	 := reflect.TypeOf(.ExtendedType).Elem()
	 := extensionMaps[]
	if  == nil {
		 = make(map[int32]*ExtensionDesc)
		extensionMaps[] = 
	}
	if ,  := [.Field];  {
		panic("proto: duplicate extension registered: " + .String() + " " + strconv.Itoa(int(.Field)))
	}
	[.Field] = 
}

// RegisteredExtensions returns a map of the registered extensions of a
// protocol buffer struct, indexed by the extension number.
// The argument pb should be a nil pointer to the struct type.
func ( Message) map[int32]*ExtensionDesc {
	return extensionMaps[reflect.TypeOf().Elem()]
}