// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package attribute // import "go.opentelemetry.io/otel/attribute"

import (
	
	
	
	
	
)

type (
	// Set is the representation for a distinct attribute set. It manages an
	// immutable set of attributes, with an internal cache for storing
	// attribute encodings.
	//
	// This type will remain comparable for backwards compatibility. The
	// equivalence of Sets across versions is not guaranteed to be stable.
	// Prior versions may find two Sets to be equal or not when compared
	// directly (i.e. ==), but subsequent versions may not. Users should use
	// the Equals method to ensure stable equivalence checking.
	//
	// Users should also use the Distinct returned from Equivalent as a map key
	// instead of a Set directly. In addition to that type providing guarantees
	// on stable equivalence, it may also provide performance improvements.
	Set struct {
		equivalent Distinct
	}

	// Distinct is a unique identifier of a Set.
	//
	// Distinct is designed to ensure equivalence stability: comparisons will
	// return the same value across versions. For this reason, Distinct should
	// always be used as a map key instead of a Set.
	Distinct struct {
		iface any
	}

	// Sortable implements sort.Interface, used for sorting KeyValue.
	//
	// Deprecated: This type is no longer used. It was added as a performance
	// optimization for Go < 1.21 that is no longer needed (Go < 1.21 is no
	// longer supported by the module).
	Sortable []KeyValue
)

var (
	// keyValueType is used in computeDistinctReflect.
	keyValueType = reflect.TypeOf(KeyValue{})

	// emptySet is returned for empty attribute sets.
	emptySet = &Set{
		equivalent: Distinct{
			iface: [0]KeyValue{},
		},
	}
)

// EmptySet returns a reference to a Set with no elements.
//
// This is a convenience provided for optimized calling utility.
func () *Set {
	return emptySet
}

// reflectValue abbreviates reflect.ValueOf(d).
func ( Distinct) () reflect.Value {
	return reflect.ValueOf(.iface)
}

// Valid reports whether this value refers to a valid Set.
func ( Distinct) () bool {
	return .iface != nil
}

// Len returns the number of attributes in this set.
func ( *Set) () int {
	if  == nil || !.equivalent.Valid() {
		return 0
	}
	return .equivalent.reflectValue().Len()
}

// Get returns the KeyValue at ordered position idx in this set.
func ( *Set) ( int) (KeyValue, bool) {
	if  == nil || !.equivalent.Valid() {
		return KeyValue{}, false
	}
	 := .equivalent.reflectValue()

	if  >= 0 &&  < .Len() {
		// Note: The Go compiler successfully avoids an allocation for
		// the interface{} conversion here:
		return .Index().Interface().(KeyValue), true
	}

	return KeyValue{}, false
}

// Value returns the value of a specified key in this set.
func ( *Set) ( Key) (Value, bool) {
	if  == nil || !.equivalent.Valid() {
		return Value{}, false
	}
	 := .equivalent.reflectValue()
	 := .Len()

	 := sort.Search(, func( int) bool {
		return .Index().Interface().(KeyValue).Key >= 
	})
	if  >=  {
		return Value{}, false
	}
	 := .Index().Interface().(KeyValue)
	if  == .Key {
		return .Value, true
	}
	return Value{}, false
}

// HasValue reports whether a key is defined in this set.
func ( *Set) ( Key) bool {
	if  == nil {
		return false
	}
	,  := .Value()
	return 
}

// Iter returns an iterator for visiting the attributes in this set.
func ( *Set) () Iterator {
	return Iterator{
		storage: ,
		idx:     -1,
	}
}

// ToSlice returns the set of attributes belonging to this set, sorted, where
// keys appear no more than once.
func ( *Set) () []KeyValue {
	 := .Iter()
	return .ToSlice()
}

// Equivalent returns a value that may be used as a map key. The Distinct type
// guarantees that the result will equal the equivalent. Distinct value of any
// attribute set with the same elements as this, where sets are made unique by
// choosing the last value in the input for any given key.
func ( *Set) () Distinct {
	if  == nil || !.equivalent.Valid() {
		return emptySet.equivalent
	}
	return .equivalent
}

// Equals reports whether the argument set is equivalent to this set.
func ( *Set) ( *Set) bool {
	return .Equivalent() == .Equivalent()
}

// Encoded returns the encoded form of this set, according to encoder.
func ( *Set) ( Encoder) string {
	if  == nil ||  == nil {
		return ""
	}

	return .Encode(.Iter())
}

func empty() Set {
	return Set{
		equivalent: emptySet.equivalent,
	}
}

// NewSet returns a new Set. See the documentation for
// NewSetWithSortableFiltered for more details.
//
// Except for empty sets, this method adds an additional allocation compared
// with calls that include a Sortable.
func ( ...KeyValue) Set {
	,  := NewSetWithFiltered(, nil)
	return 
}

// NewSetWithSortable returns a new Set. See the documentation for
// NewSetWithSortableFiltered for more details.
//
// This call includes a Sortable option as a memory optimization.
//
// Deprecated: Use [NewSet] instead.
func ( []KeyValue,  *Sortable) Set {
	,  := NewSetWithFiltered(, nil)
	return 
}

// NewSetWithFiltered returns a new Set. See the documentation for
// NewSetWithSortableFiltered for more details.
//
// This call includes a Filter to include/exclude attribute keys from the
// return value. Excluded keys are returned as a slice of attribute values.
func ( []KeyValue,  Filter) (Set, []KeyValue) {
	// Check for empty set.
	if len() == 0 {
		return empty(), nil
	}

	// Stable sort so the following de-duplication can implement
	// last-value-wins semantics.
	slices.SortStableFunc(, func(,  KeyValue) int {
		return cmp.Compare(.Key, .Key)
	})

	 := len() - 1
	 :=  - 1

	// The requirements stated above require that the stable
	// result be placed in the end of the input slice, while
	// overwritten values are swapped to the beginning.
	//
	// De-duplicate with last-value-wins semantics.  Preserve
	// duplicate values at the beginning of the input slice.
	for ;  >= 0; -- {
		if [].Key == [].Key {
			continue
		}
		--
		[], [] = [], []
	}
	 = [:]

	if  != nil {
		if  := filteredToFront(, );  != 0 {
			return Set{equivalent: computeDistinct([:])}, [:]
		}
	}
	return Set{equivalent: computeDistinct()}, nil
}

// NewSetWithSortableFiltered returns a new Set.
//
// Duplicate keys are eliminated by taking the last value.  This
// re-orders the input slice so that unique last-values are contiguous
// at the end of the slice.
//
// This ensures the following:
//
// - Last-value-wins semantics
// - Caller sees the reordering, but doesn't lose values
// - Repeated call preserve last-value wins.
//
// Note that methods are defined on Set, although this returns Set. Callers
// can avoid memory allocations by:
//
// - allocating a Sortable for use as a temporary in this method
// - allocating a Set for storing the return value of this constructor.
//
// The result maintains a cache of encoded attributes, by attribute.EncoderID.
// This value should not be copied after its first use.
//
// The second []KeyValue return value is a list of attributes that were
// excluded by the Filter (if non-nil).
//
// Deprecated: Use [NewSetWithFiltered] instead.
func ( []KeyValue,  *Sortable,  Filter) (Set, []KeyValue) {
	return NewSetWithFiltered(, )
}

// filteredToFront filters slice in-place using keep function. All KeyValues that need to
// be removed are moved to the front. All KeyValues that need to be kept are
// moved (in-order) to the back. The index for the first KeyValue to be kept is
// returned.
func filteredToFront( []KeyValue,  Filter) int {
	 := len()
	 := 
	for  :=  - 1;  >= 0; -- {
		if ([]) {
			--
			[], [] = [], []
		}
	}
	return 
}

// Filter returns a filtered copy of this Set. See the documentation for
// NewSetWithSortableFiltered for more details.
func ( *Set) ( Filter) (Set, []KeyValue) {
	if  == nil {
		return *, nil
	}

	// Iterate in reverse to the first attribute that will be filtered out.
	 := .Len()
	 :=  - 1
	for ;  >= 0; -- {
		,  := .Get()
		if !() {
			break
		}
	}

	// No attributes will be dropped, return the immutable Set l and nil.
	if  < 0 {
		return *, nil
	}

	// Copy now that we know we need to return a modified set.
	//
	// Do not do this in-place on the underlying storage of *Set l. Sets are
	// immutable and filtering should not change this.
	 := .ToSlice()

	// Don't re-iterate the slice if only slice[0] is filtered.
	if  == 0 {
		// It is safe to assume len(slice) >= 1 given we found at least one
		// attribute above that needs to be filtered out.
		return Set{equivalent: computeDistinct([1:])}, [:1]
	}

	// Move the filtered slice[first] to the front (preserving order).
	 := []
	copy([1:+1], [:])
	[0] = 

	// Do not re-evaluate re(slice[first+1:]).
	 := filteredToFront([1:+1], ) + 1
	return Set{equivalent: computeDistinct([:])}, [:]
}

// computeDistinct returns a Distinct using either the fixed- or
// reflect-oriented code path, depending on the size of the input. The input
// slice is assumed to already be sorted and de-duplicated.
func computeDistinct( []KeyValue) Distinct {
	 := computeDistinctFixed()
	if  == nil {
		 = computeDistinctReflect()
	}
	return Distinct{
		iface: ,
	}
}

// computeDistinctFixed computes a Distinct for small slices. It returns nil
// if the input is too large for this code path.
func computeDistinctFixed( []KeyValue) any {
	switch len() {
	case 1:
		return [1]KeyValue()
	case 2:
		return [2]KeyValue()
	case 3:
		return [3]KeyValue()
	case 4:
		return [4]KeyValue()
	case 5:
		return [5]KeyValue()
	case 6:
		return [6]KeyValue()
	case 7:
		return [7]KeyValue()
	case 8:
		return [8]KeyValue()
	case 9:
		return [9]KeyValue()
	case 10:
		return [10]KeyValue()
	default:
		return nil
	}
}

// computeDistinctReflect computes a Distinct using reflection, works for any
// size input.
func computeDistinctReflect( []KeyValue) any {
	 := reflect.New(reflect.ArrayOf(len(), keyValueType)).Elem()
	for ,  := range  {
		*(.Index().Addr().Interface().(*KeyValue)) = 
	}
	return .Interface()
}

// MarshalJSON returns the JSON encoding of the Set.
func ( *Set) () ([]byte, error) {
	return json.Marshal(.equivalent.iface)
}

// MarshalLog is the marshaling function used by the logging system to represent this Set.
func ( Set) () any {
	 := make(map[string]string)
	for ,  := range .ToSlice() {
		[string(.Key)] = .Value.Emit()
	}
	return 
}

// Len implements sort.Interface.
func ( *Sortable) () int {
	return len(*)
}

// Swap implements sort.Interface.
func ( *Sortable) (,  int) {
	(*)[], (*)[] = (*)[], (*)[]
}

// Less implements sort.Interface.
func ( *Sortable) (,  int) bool {
	return (*)[].Key < (*)[].Key
}