opentofu/internal/addrs/set.go
Martin Atkins f3a57db293 addrs: UniqueKey and UniqueKeyer
Many times now we've seen situations where we need to use addresses
as map keys, but not all of our address types are comparable and thus
we tend to end up using string representations as keys instead.

That's problematic because conversion to string uses type information
and some of the address types have string representations that are
ambiguous with one another.

UniqueKey therefore represents an opaque key that is unique for each
functionally-distinct address across all types that implement
UniqueKeyer.

For this initial commit I've implemented UniqueKeyer only for the
Referenceable family of types. These are an easy case because they
were all already comparable (intentionally) anyway. Later commits
can implement UniqueKeyer for other types that are not naturally
comparable, such as any which include a ModuleInstance.

This also includes a new type addrs.Set which wraps a map as a set
of addresses, using the unique keys to ensure that there can be only
one element for each distinct address.
2021-07-14 17:37:48 -07:00

44 lines
771 B
Go

package addrs
// Set represents a set of addresses of types that implement UniqueKeyer.
type Set map[UniqueKey]UniqueKeyer
func (s Set) Has(addr UniqueKeyer) bool {
_, exists := s[addr.UniqueKey()]
return exists
}
func (s Set) Add(addr UniqueKeyer) {
s[addr.UniqueKey()] = addr
}
func (s Set) Remove(addr UniqueKeyer) {
delete(s, addr.UniqueKey())
}
func (s Set) Union(other Set) Set {
ret := make(Set)
for k, addr := range s {
ret[k] = addr
}
for k, addr := range other {
ret[k] = addr
}
return ret
}
func (s Set) Intersection(other Set) Set {
ret := make(Set)
for k, addr := range s {
if _, exists := other[k]; exists {
ret[k] = addr
}
}
for k, addr := range other {
if _, exists := s[k]; exists {
ret[k] = addr
}
}
return ret
}