github.com/lamielle/terraform@v0.3.2-0.20141121070651-81f008ba53d5/helper/schema/set.go (about) 1 package schema 2 3 import ( 4 "sort" 5 "sync" 6 ) 7 8 // Set is a set data structure that is returned for elements of type 9 // TypeSet. 10 type Set struct { 11 F SchemaSetFunc 12 13 m map[int]interface{} 14 once sync.Once 15 } 16 17 // NewSet is a convenience method for creating a new set with the given 18 // items. 19 func NewSet(f SchemaSetFunc, items []interface{}) *Set { 20 s := &Set{F: f} 21 for _, i := range items { 22 s.Add(i) 23 } 24 25 return s 26 } 27 28 // Add adds an item to the set if it isn't already in the set. 29 func (s *Set) Add(item interface{}) { 30 s.add(item) 31 } 32 33 // Contains checks if the set has the given item. 34 func (s *Set) Contains(item interface{}) bool { 35 _, ok := s.m[s.F(item)] 36 return ok 37 } 38 39 // Len returns the amount of items in the set. 40 func (s *Set) Len() int { 41 return len(s.m) 42 } 43 44 // List returns the elements of this set in slice format. 45 // 46 // The order of the returned elements is deterministic. Given the same 47 // set, the order of this will always be the same. 48 func (s *Set) List() []interface{} { 49 result := make([]interface{}, len(s.m)) 50 for i, k := range s.listCode() { 51 result[i] = s.m[k] 52 } 53 54 return result 55 } 56 57 // Differences performs a set difference of the two sets, returning 58 // a new third set that has only the elements unique to this set. 59 func (s *Set) Difference(other *Set) *Set { 60 result := &Set{F: s.F} 61 result.init() 62 63 for k, v := range s.m { 64 if _, ok := other.m[k]; !ok { 65 result.m[k] = v 66 } 67 } 68 69 return result 70 } 71 72 // Intersection performs the set intersection of the two sets 73 // and returns a new third set. 74 func (s *Set) Intersection(other *Set) *Set { 75 result := &Set{F: s.F} 76 result.init() 77 78 for k, v := range s.m { 79 if _, ok := other.m[k]; ok { 80 result.m[k] = v 81 } 82 } 83 84 return result 85 } 86 87 // Union performs the set union of the two sets and returns a new third 88 // set. 89 func (s *Set) Union(other *Set) *Set { 90 result := &Set{F: s.F} 91 result.init() 92 93 for k, v := range s.m { 94 result.m[k] = v 95 } 96 for k, v := range other.m { 97 result.m[k] = v 98 } 99 100 return result 101 } 102 103 func (s *Set) init() { 104 s.m = make(map[int]interface{}) 105 } 106 107 func (s *Set) add(item interface{}) int { 108 s.once.Do(s.init) 109 110 code := s.F(item) 111 if _, ok := s.m[code]; !ok { 112 s.m[code] = item 113 } 114 115 return code 116 } 117 118 func (s *Set) index(item interface{}) int { 119 return sort.SearchInts(s.listCode(), s.F(item)) 120 } 121 122 func (s *Set) listCode() []int { 123 // Sort the hash codes so the order of the list is deterministic 124 keys := make([]int, 0, len(s.m)) 125 for k, _ := range s.m { 126 keys = append(keys, k) 127 } 128 sort.Sort(sort.IntSlice(keys)) 129 return keys 130 }