]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/zclconf/go-cty/cty/set/ops.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / zclconf / go-cty / cty / set / ops.go
1 package set
2
3 import (
4 "sort"
5 )
6
7 // Add inserts the given value into the receiving Set.
8 //
9 // This mutates the set in-place. This operation is not thread-safe.
10 func (s Set) Add(val interface{}) {
11 hv := s.rules.Hash(val)
12 if _, ok := s.vals[hv]; !ok {
13 s.vals[hv] = make([]interface{}, 0, 1)
14 }
15 bucket := s.vals[hv]
16
17 // See if an equivalent value is already present
18 for _, ev := range bucket {
19 if s.rules.Equivalent(val, ev) {
20 return
21 }
22 }
23
24 s.vals[hv] = append(bucket, val)
25 }
26
27 // Remove deletes the given value from the receiving set, if indeed it was
28 // there in the first place. If the value is not present, this is a no-op.
29 func (s Set) Remove(val interface{}) {
30 hv := s.rules.Hash(val)
31 bucket, ok := s.vals[hv]
32 if !ok {
33 return
34 }
35
36 for i, ev := range bucket {
37 if s.rules.Equivalent(val, ev) {
38 newBucket := make([]interface{}, 0, len(bucket)-1)
39 newBucket = append(newBucket, bucket[:i]...)
40 newBucket = append(newBucket, bucket[i+1:]...)
41 if len(newBucket) > 0 {
42 s.vals[hv] = newBucket
43 } else {
44 delete(s.vals, hv)
45 }
46 return
47 }
48 }
49 }
50
51 // Has returns true if the given value is in the receiving set, or false if
52 // it is not.
53 func (s Set) Has(val interface{}) bool {
54 hv := s.rules.Hash(val)
55 bucket, ok := s.vals[hv]
56 if !ok {
57 return false
58 }
59
60 for _, ev := range bucket {
61 if s.rules.Equivalent(val, ev) {
62 return true
63 }
64 }
65 return false
66 }
67
68 // Copy performs a shallow copy of the receiving set, returning a new set
69 // with the same rules and elements.
70 func (s Set) Copy() Set {
71 ret := NewSet(s.rules)
72 for k, v := range s.vals {
73 ret.vals[k] = v
74 }
75 return ret
76 }
77
78 // Iterator returns an iterator over values in the set. If the set's rules
79 // implement OrderedRules then the result is ordered per those rules. If
80 // no order is provided, or if it is not a total order, then the iteration
81 // order is undefined but consistent for a particular version of cty. Do not
82 // rely on specific ordering between cty releases unless the rules order is a
83 // total order.
84 //
85 // The pattern for using the returned iterator is:
86 //
87 // it := set.Iterator()
88 // for it.Next() {
89 // val := it.Value()
90 // // ...
91 // }
92 //
93 // Once an iterator has been created for a set, the set *must not* be mutated
94 // until the iterator is no longer in use.
95 func (s Set) Iterator() *Iterator {
96 vals := s.Values()
97
98 return &Iterator{
99 vals: vals,
100 idx: -1,
101 }
102 }
103
104 // EachValue calls the given callback once for each value in the set, in an
105 // undefined order that callers should not depend on.
106 func (s Set) EachValue(cb func(interface{})) {
107 it := s.Iterator()
108 for it.Next() {
109 cb(it.Value())
110 }
111 }
112
113 // Values returns a slice of all the values in the set. If the set rules have
114 // an order then the result is in that order. If no order is provided or if
115 // it is not a total order then the result order is undefined, but consistent
116 // for a particular set value within a specific release of cty.
117 func (s Set) Values() []interface{} {
118 var ret []interface{}
119 // Sort the bucketIds to ensure that we always traverse in a
120 // consistent order.
121 bucketIDs := make([]int, 0, len(s.vals))
122 for id := range s.vals {
123 bucketIDs = append(bucketIDs, id)
124 }
125 sort.Ints(bucketIDs)
126
127 for _, bucketID := range bucketIDs {
128 ret = append(ret, s.vals[bucketID]...)
129 }
130
131 if orderRules, ok := s.rules.(OrderedRules); ok {
132 sort.SliceStable(ret, func(i, j int) bool {
133 return orderRules.Less(ret[i], ret[j])
134 })
135 }
136
137 return ret
138 }
139
140 // Length returns the number of values in the set.
141 func (s Set) Length() int {
142 var count int
143 for _, bucket := range s.vals {
144 count = count + len(bucket)
145 }
146 return count
147 }
148
149 // Union returns a new set that contains all of the members of both the
150 // receiving set and the given set. Both sets must have the same rules, or
151 // else this function will panic.
152 func (s1 Set) Union(s2 Set) Set {
153 mustHaveSameRules(s1, s2)
154 rs := NewSet(s1.rules)
155 s1.EachValue(func(v interface{}) {
156 rs.Add(v)
157 })
158 s2.EachValue(func(v interface{}) {
159 rs.Add(v)
160 })
161 return rs
162 }
163
164 // Intersection returns a new set that contains the values that both the
165 // receiver and given sets have in common. Both sets must have the same rules,
166 // or else this function will panic.
167 func (s1 Set) Intersection(s2 Set) Set {
168 mustHaveSameRules(s1, s2)
169 rs := NewSet(s1.rules)
170 s1.EachValue(func(v interface{}) {
171 if s2.Has(v) {
172 rs.Add(v)
173 }
174 })
175 return rs
176 }
177
178 // Subtract returns a new set that contains all of the values from the receiver
179 // that are not also in the given set. Both sets must have the same rules,
180 // or else this function will panic.
181 func (s1 Set) Subtract(s2 Set) Set {
182 mustHaveSameRules(s1, s2)
183 rs := NewSet(s1.rules)
184 s1.EachValue(func(v interface{}) {
185 if !s2.Has(v) {
186 rs.Add(v)
187 }
188 })
189 return rs
190 }
191
192 // SymmetricDifference returns a new set that contains all of the values from
193 // both the receiver and given sets, except those that both sets have in
194 // common. Both sets must have the same rules, or else this function will
195 // panic.
196 func (s1 Set) SymmetricDifference(s2 Set) Set {
197 mustHaveSameRules(s1, s2)
198 rs := NewSet(s1.rules)
199 s1.EachValue(func(v interface{}) {
200 if !s2.Has(v) {
201 rs.Add(v)
202 }
203 })
204 s2.EachValue(func(v interface{}) {
205 if !s1.Has(v) {
206 rs.Add(v)
207 }
208 })
209 return rs
210 }