packer/internal/dag/set.go
Lucas Bajolet 673c13ebe7 internal: add dag package
The dag package is a port over from Terraform to Packer, changing what
little there was to fit our current dependency ecosystem.
Most of the changes are on the type of diagnostics returned, as
Terraform has its own type for them, while we rely on hcl's Diagnostics.

Other than that, the functionality is essentially equivalent, and the
code was barely touched.
2024-10-29 16:10:29 -04:00

116 lines
2.2 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package dag
// Set is a set data structure.
type Set map[interface{}]interface{}
// Hashable is the interface used by set to get the hash code of a value.
// If this isn't given, then the value of the item being added to the set
// itself is used as the comparison value.
type Hashable interface {
Hashcode() interface{}
}
// hashcode returns the hashcode used for set elements.
func hashcode(v interface{}) interface{} {
if h, ok := v.(Hashable); ok {
return h.Hashcode()
}
return v
}
// Add adds an item to the set
func (s Set) Add(v interface{}) {
s[hashcode(v)] = v
}
// Delete removes an item from the set.
func (s Set) Delete(v interface{}) {
delete(s, hashcode(v))
}
// Include returns true/false of whether a value is in the set.
func (s Set) Include(v interface{}) bool {
_, ok := s[hashcode(v)]
return ok
}
// Intersection computes the set intersection with other.
func (s Set) Intersection(other Set) Set {
result := make(Set)
if s == nil || other == nil {
return result
}
// Iteration over a smaller set has better performance.
if other.Len() < s.Len() {
s, other = other, s
}
for _, v := range s {
if other.Include(v) {
result.Add(v)
}
}
return result
}
// Difference returns a set with the elements that s has but
// other doesn't.
func (s Set) Difference(other Set) Set {
if other == nil || other.Len() == 0 {
return s.Copy()
}
result := make(Set)
for k, v := range s {
if _, ok := other[k]; !ok {
result.Add(v)
}
}
return result
}
// Filter returns a set that contains the elements from the receiver
// where the given callback returns true.
func (s Set) Filter(cb func(interface{}) bool) Set {
result := make(Set)
for _, v := range s {
if cb(v) {
result.Add(v)
}
}
return result
}
// Len is the number of items in the set.
func (s Set) Len() int {
return len(s)
}
// List returns the list of set elements.
func (s Set) List() []interface{} {
if s == nil {
return nil
}
r := make([]interface{}, 0, len(s))
for _, v := range s {
r = append(r, v)
}
return r
}
// Copy returns a shallow copy of the set.
func (s Set) Copy() Set {
c := make(Set, len(s))
for k, v := range s {
c[k] = v
}
return c
}