/
githubmirror
/
terraform
Обзор
Документация
Войти
/
githubmirror
/
terraform
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
internal/collections/map.go
146 строк
4 KB
Radek Simko
make copyrightfix
17 фев 2026, 16:56
17 фев 2026, 16:56
0fe906f
Код
Авторство
О чём код?
// Copyright IBM Corp. 2014, 2026 // SPDX-License-Identifier: BUSL-1.1 package collections import "iter" // Set represents an associative array from keys of type K to values of type V. // // A caller-provided "key function" defines how to produce a comparable unique // key for each distinct value of type K. // // Map operations are not concurrency-safe. Use external locking if multiple // goroutines might modify the map concurrently or if one goroutine might // read a map while another is modifying it. type Map[K, V any] struct { elems map[UniqueKey[K]]MapElem[K, V] key func(K) UniqueKey[K] } // MapElem represents a single element of a map. type MapElem[K, V any] struct { K K V V } // NewMap constructs a new map whose key type knows how to calculate its own // unique keys, by implementing [UniqueKeyer] of itself. func NewMap[K UniqueKeyer[K], V any](elems ...MapElem[K, V]) Map[K, V] { m := NewMapFunc[K, V](K.UniqueKey) for _, elems := range elems { m.Put(elems.K, elems.V) } return m } // NewMapFunc constructs a new map with the given "map function". // // A valid key function must produce only values of types that can be compared // for equality using the Go == operator, and must guarantee that each unique // value of K has a corresponding key that uniquely identifies it. The // implementer of the key function can decide what constitutes a // "unique value of K", based on the meaning of type K. // // Type V is unconstrained by the arguments, so callers must explicitly provide // the key and value type arguments when calling this function. func NewMapFunc[K, V any](keyFunc func(K) UniqueKey[K]) Map[K, V] { return Map[K, V]{ elems: make(map[UniqueKey[K]]MapElem[K, V]), key: keyFunc, } } // NewMapCmp constructs a new set for any comparable key type, using the // built-in == operator as the definition of key equivalence. // // This is here for completeness in case it's useful when talking to a // generalized API that operates on maps of any key type, but if your // key type is fixed and known to be comparable then it's pointless to // use [Map]; use Go's built-in map types instead, which will then avoid // redundantly storing the keys twice. func NewMapCmp[K comparable, V any]() Map[K, V] { return NewMapFunc[K, V](cmpUniqueKeyFunc[K]) } // HasKey returns true if the map has an element with the given key, or // false otherwise. func (m Map[K, V]) HasKey(k K) bool { if m.key == nil { return false // an uninitialized map has no keys } uniq := m.key(k) _, exists := m.elems[uniq] return exists } // Get retrieves the value associated with the given key, or the zero value // of V if no matching element exists in the map. func (m Map[K, V]) Get(k K) V { ret, _ := m.GetOk(k) return ret } // GetOk is like [Map.Get] but also returns a second boolean result reporting // whether a matching element was present in the map. func (m Map[K, V]) GetOk(k K) (V, bool) { if m.key == nil { var zero V return zero, false // an uninitialized map has no keys } uniq := m.key(k) ret, ok := m.elems[uniq] return ret.V, ok } // Put writes a new element into the map, with the given key and value. // // If there is already an element with an equivalent key (as determined by the // set's "key function") then the new element replaces that existing element. func (m Map[K, V]) Put(k K, v V) { if m.key == nil { panic("Put into uninitialized collections.Map") } uniq := m.key(k) m.elems[uniq] = MapElem[K, V]{ K: k, V: v, } } // Delete removes from the map the element with the given key, or does nothing // if there is no such element. func (m Map[K, V]) Delete(k K) { if m.key == nil { panic("Delete from uninitialized collections.Map") } uniq := m.key(k) delete(m.elems, uniq) } // All returns an iterator over the elements of the map, in an unspecified // order. // // This is intended for use in a range-over-func statement, like this: // // for k, v := range map.All() { // // do something with k and/or v // } // // Modifying the map during iteration causes unspecified results. Modifying // the map concurrently with advancing the iterator causes undefined behavior // including possible memory unsafety. func (m Map[K, V]) All() iter.Seq2[K, V] { return func(yield func(K, V) bool) { for _, elem := range m.elems { if !yield(elem.K, elem.V) { return } } } } // Len returns the number of elements in the map. func (m Map[K, V]) Len() int { return len(m.elems) }