11 "github.com/hashicorp/terraform/helper/hashcode"
14 // HashString hashes strings. If you want a Set of strings, this is the
15 // SchemaSetFunc you want.
16 func HashString(v interface{}) int {
17 return hashcode.String(v.(string))
20 // HashInt hashes integers. If you want a Set of integers, this is the
21 // SchemaSetFunc you want.
22 func HashInt(v interface{}) int {
23 return hashcode.String(strconv.Itoa(v.(int)))
26 // HashResource hashes complex structures that are described using
27 // a *Resource. This is the default set implementation used when a set's
28 // element type is a full resource.
29 func HashResource(resource *Resource) SchemaSetFunc {
30 return func(v interface{}) int {
32 SerializeResourceForHash(&buf, v, resource)
33 return hashcode.String(buf.String())
37 // HashSchema hashes values that are described using a *Schema. This is the
38 // default set implementation used when a set's element type is a single
40 func HashSchema(schema *Schema) SchemaSetFunc {
41 return func(v interface{}) int {
43 SerializeValueForHash(&buf, v, schema)
44 return hashcode.String(buf.String())
48 // Set is a set data structure that is returned for elements of type
53 m map[string]interface{}
57 // NewSet is a convenience method for creating a new set with the given
59 func NewSet(f SchemaSetFunc, items []interface{}) *Set {
61 for _, i := range items {
68 // CopySet returns a copy of another set.
69 func CopySet(otherSet *Set) *Set {
70 return NewSet(otherSet.F, otherSet.List())
73 // Add adds an item to the set if it isn't already in the set.
74 func (s *Set) Add(item interface{}) {
78 // Remove removes an item if it's already in the set. Idempotent.
79 func (s *Set) Remove(item interface{}) {
83 // Contains checks if the set has the given item.
84 func (s *Set) Contains(item interface{}) bool {
85 _, ok := s.m[s.hash(item)]
89 // Len returns the amount of items in the set.
90 func (s *Set) Len() int {
94 // List returns the elements of this set in slice format.
96 // The order of the returned elements is deterministic. Given the same
97 // set, the order of this will always be the same.
98 func (s *Set) List() []interface{} {
99 result := make([]interface{}, len(s.m))
100 for i, k := range s.listCode() {
107 // Difference performs a set difference of the two sets, returning
108 // a new third set that has only the elements unique to this set.
109 func (s *Set) Difference(other *Set) *Set {
110 result := &Set{F: s.F}
111 result.once.Do(result.init)
113 for k, v := range s.m {
114 if _, ok := other.m[k]; !ok {
122 // Intersection performs the set intersection of the two sets
123 // and returns a new third set.
124 func (s *Set) Intersection(other *Set) *Set {
125 result := &Set{F: s.F}
126 result.once.Do(result.init)
128 for k, v := range s.m {
129 if _, ok := other.m[k]; ok {
137 // Union performs the set union of the two sets and returns a new third
139 func (s *Set) Union(other *Set) *Set {
140 result := &Set{F: s.F}
141 result.once.Do(result.init)
143 for k, v := range s.m {
146 for k, v := range other.m {
153 func (s *Set) Equal(raw interface{}) bool {
154 other, ok := raw.(*Set)
159 return reflect.DeepEqual(s.m, other.m)
162 // HashEqual simply checks to the keys the top-level map to the keys in the
163 // other set's top-level map to see if they are equal. This obviously assumes
164 // you have a properly working hash function - use HashResource if in doubt.
165 func (s *Set) HashEqual(raw interface{}) bool {
166 other, ok := raw.(*Set)
171 ks1 := make([]string, 0)
172 ks2 := make([]string, 0)
177 for k := range other.m {
184 return reflect.DeepEqual(ks1, ks2)
187 func (s *Set) GoString() string {
188 return fmt.Sprintf("*Set(%#v)", s.m)
191 func (s *Set) init() {
192 s.m = make(map[string]interface{})
195 func (s *Set) add(item interface{}, computed bool) string {
205 for _, exists := s.m[tmpCode]; exists; _, exists = s.m[tmpCode] {
207 tmpCode = fmt.Sprintf("%s%d", code, count)
213 if _, ok := s.m[code]; !ok {
220 func (s *Set) hash(item interface{}) string {
222 // Always return a nonnegative hashcode.
226 return strconv.Itoa(code)
229 func (s *Set) remove(item interface{}) string {
238 func (s *Set) index(item interface{}) int {
239 return sort.SearchStrings(s.listCode(), s.hash(item))
242 func (s *Set) listCode() []string {
243 // Sort the hash codes so the order of the list is deterministic
244 keys := make([]string, 0, len(s.m))
246 keys = append(keys, k)
248 sort.Sort(sort.StringSlice(keys))