github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/addrs/map.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package addrs
     5  
     6  // Map represents a mapping whose keys are address types that implement
     7  // UniqueKeyer.
     8  //
     9  // Since not all address types are comparable in the Go language sense, this
    10  // type cannot work with the typical Go map access syntax, and so instead has
    11  // a method-based syntax. Use this type only for situations where the key
    12  // type isn't guaranteed to always be a valid key for a standard Go map.
    13  type Map[K UniqueKeyer, V any] struct {
    14  	// Elems is the internal data structure of the map.
    15  	//
    16  	// This is exported to allow for comparisons during tests and other similar
    17  	// careful read operations, but callers MUST NOT modify this map directly.
    18  	// Use only the methods of Map to modify the contents of this structure,
    19  	// to ensure that it remains correct and consistent.
    20  	Elems map[UniqueKey]MapElem[K, V]
    21  }
    22  
    23  type MapElem[K UniqueKeyer, V any] struct {
    24  	Key   K
    25  	Value V
    26  }
    27  
    28  func MakeMap[K UniqueKeyer, V any](initialElems ...MapElem[K, V]) Map[K, V] {
    29  	inner := make(map[UniqueKey]MapElem[K, V], len(initialElems))
    30  	ret := Map[K, V]{inner}
    31  	for _, elem := range initialElems {
    32  		ret.Put(elem.Key, elem.Value)
    33  	}
    34  	return ret
    35  }
    36  
    37  func MakeMapElem[K UniqueKeyer, V any](key K, value V) MapElem[K, V] {
    38  	return MapElem[K, V]{key, value}
    39  }
    40  
    41  // Put inserts a new element into the map, or replaces an existing element
    42  // which has an equivalent key.
    43  func (m Map[K, V]) Put(key K, value V) {
    44  	realKey := key.UniqueKey()
    45  	m.Elems[realKey] = MapElem[K, V]{key, value}
    46  }
    47  
    48  // PutElement is like Put but takes the key and value from the given MapElement
    49  // structure instead of as individual arguments.
    50  func (m Map[K, V]) PutElement(elem MapElem[K, V]) {
    51  	m.Put(elem.Key, elem.Value)
    52  }
    53  
    54  // Remove deletes the element with the given key from the map, or does nothing
    55  // if there is no such element.
    56  func (m Map[K, V]) Remove(key K) {
    57  	realKey := key.UniqueKey()
    58  	delete(m.Elems, realKey)
    59  }
    60  
    61  // Get returns the value of the element with the given key, or the zero value
    62  // of V if there is no such element.
    63  func (m Map[K, V]) Get(key K) V {
    64  	realKey := key.UniqueKey()
    65  	return m.Elems[realKey].Value
    66  }
    67  
    68  // GetOk is like Get but additionally returns a flag for whether there was an
    69  // element with the given key present in the map.
    70  func (m Map[K, V]) GetOk(key K) (V, bool) {
    71  	realKey := key.UniqueKey()
    72  	elem, ok := m.Elems[realKey]
    73  	return elem.Value, ok
    74  }
    75  
    76  // Has returns true if and only if there is an element in the map which has the
    77  // given key.
    78  func (m Map[K, V]) Has(key K) bool {
    79  	realKey := key.UniqueKey()
    80  	_, ok := m.Elems[realKey]
    81  	return ok
    82  }
    83  
    84  // Len returns the number of elements in the map.
    85  func (m Map[K, V]) Len() int {
    86  	return len(m.Elems)
    87  }
    88  
    89  // Elements returns a slice containing a snapshot of the current elements of
    90  // the map, in an unpredictable order.
    91  func (m Map[K, V]) Elements() []MapElem[K, V] {
    92  	if len(m.Elems) == 0 {
    93  		return nil
    94  	}
    95  	ret := make([]MapElem[K, V], 0, len(m.Elems))
    96  	for _, elem := range m.Elems {
    97  		ret = append(ret, elem)
    98  	}
    99  	return ret
   100  }
   101  
   102  // Keys returns a Set[K] containing a snapshot of the current keys of elements
   103  // of the map.
   104  func (m Map[K, V]) Keys() Set[K] {
   105  	if len(m.Elems) == 0 {
   106  		return nil
   107  	}
   108  	ret := make(Set[K], len(m.Elems))
   109  
   110  	// We mess with the internals of Set here, rather than going through its
   111  	// public interface, because that means we can avoid re-calling UniqueKey
   112  	// on all of the elements when we know that our own Put method would have
   113  	// already done the same thing.
   114  	for realKey, elem := range m.Elems {
   115  		ret[realKey] = elem.Key
   116  	}
   117  	return ret
   118  }
   119  
   120  // Values returns a slice containing a snapshot of the current values of
   121  // elements of the map, in an unpredictable order.
   122  func (m Map[K, V]) Values() []V {
   123  	if len(m.Elems) == 0 {
   124  		return nil
   125  	}
   126  	ret := make([]V, 0, len(m.Elems))
   127  	for _, elem := range m.Elems {
   128  		ret = append(ret, elem.Value)
   129  	}
   130  	return ret
   131  }