aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/set
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/set')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/gob.go76
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/iterator.go36
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/ops.go199
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/rules.go25
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/set.go62
5 files changed, 398 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/gob.go b/vendor/github.com/zclconf/go-cty/cty/set/gob.go
new file mode 100644
index 0000000..da2978f
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/gob.go
@@ -0,0 +1,76 @@
1package set
2
3import (
4 "bytes"
5 "encoding/gob"
6 "fmt"
7)
8
9// GobEncode is an implementation of the interface gob.GobEncoder, allowing
10// sets to be included in structures encoded via gob.
11//
12// The set rules are included in the serialized value, so the caller must
13// register its concrete rules type with gob.Register before using a
14// set in a gob, and possibly also implement GobEncode/GobDecode to customize
15// how any parameters are persisted.
16//
17// The set elements are also included, so if they are of non-primitive types
18// they too must be registered with gob.
19//
20// If the produced gob values will persist for a long time, the caller must
21// ensure compatibility of the rules implementation. In particular, if the
22// definition of element equivalence changes between encoding and decoding
23// then two distinct stored elements may be considered equivalent on decoding,
24// causing the recovered set to have fewer elements than when it was stored.
25func (s Set) GobEncode() ([]byte, error) {
26 gs := gobSet{
27 Version: 0,
28 Rules: s.rules,
29 Values: s.Values(),
30 }
31
32 buf := &bytes.Buffer{}
33 enc := gob.NewEncoder(buf)
34 err := enc.Encode(gs)
35 if err != nil {
36 return nil, fmt.Errorf("error encoding set.Set: %s", err)
37 }
38
39 return buf.Bytes(), nil
40}
41
42// GobDecode is the opposite of GobEncode. See GobEncode for information
43// on the requirements for and caveats of including set values in gobs.
44func (s *Set) GobDecode(buf []byte) error {
45 r := bytes.NewReader(buf)
46 dec := gob.NewDecoder(r)
47
48 var gs gobSet
49 err := dec.Decode(&gs)
50 if err != nil {
51 return fmt.Errorf("error decoding set.Set: %s", err)
52 }
53 if gs.Version != 0 {
54 return fmt.Errorf("unsupported set.Set encoding version %d; need 0", gs.Version)
55 }
56
57 victim := NewSetFromSlice(gs.Rules, gs.Values)
58 s.vals = victim.vals
59 s.rules = victim.rules
60 return nil
61}
62
63type gobSet struct {
64 Version int
65 Rules Rules
66
67 // The bucket-based representation is for efficient in-memory access, but
68 // for serialization it's enough to just retain the values themselves,
69 // which we can re-bucket using the rules (which may have changed!) when
70 // we re-inflate.
71 Values []interface{}
72}
73
74func init() {
75 gob.Register([]interface{}(nil))
76}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/iterator.go b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
new file mode 100644
index 0000000..f15498e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
@@ -0,0 +1,36 @@
1package set
2
3type Iterator struct {
4 bucketIds []int
5 vals map[int][]interface{}
6 bucketIdx int
7 valIdx int
8}
9
10func (it *Iterator) Value() interface{} {
11 return it.currentBucket()[it.valIdx]
12}
13
14func (it *Iterator) Next() bool {
15 if it.bucketIdx == -1 {
16 // init
17 if len(it.bucketIds) == 0 {
18 return false
19 }
20
21 it.valIdx = 0
22 it.bucketIdx = 0
23 return true
24 }
25
26 it.valIdx++
27 if it.valIdx >= len(it.currentBucket()) {
28 it.valIdx = 0
29 it.bucketIdx++
30 }
31 return it.bucketIdx < len(it.bucketIds)
32}
33
34func (it *Iterator) currentBucket() []interface{} {
35 return it.vals[it.bucketIds[it.bucketIdx]]
36}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/ops.go b/vendor/github.com/zclconf/go-cty/cty/set/ops.go
new file mode 100644
index 0000000..726e707
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/ops.go
@@ -0,0 +1,199 @@
1package set
2
3import (
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.
10func (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.
29func (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.
53func (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.
70func (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, in an undefined order
79// that callers should not depend on.
80//
81// The pattern for using the returned iterator is:
82//
83// it := set.Iterator()
84// for it.Next() {
85// val := it.Value()
86// // ...
87// }
88//
89// Once an iterator has been created for a set, the set *must not* be mutated
90// until the iterator is no longer in use.
91func (s Set) Iterator() *Iterator {
92 // Sort the bucketIds to ensure that we always traverse in a
93 // consistent order.
94 bucketIds := make([]int, 0, len(s.vals))
95 for id := range s.vals {
96 bucketIds = append(bucketIds, id)
97 }
98 sort.Ints(bucketIds)
99
100 return &Iterator{
101 bucketIds: bucketIds,
102 vals: s.vals,
103 bucketIdx: -1,
104 }
105}
106
107// EachValue calls the given callback once for each value in the set, in an
108// undefined order that callers should not depend on.
109func (s Set) EachValue(cb func(interface{})) {
110 it := s.Iterator()
111 for it.Next() {
112 cb(it.Value())
113 }
114}
115
116// Values returns a slice of all of the values in the set in no particular
117// order. This is just a wrapper around EachValue that accumulates the results
118// in a slice for caller convenience.
119//
120// The returned slice will be nil if there are no values in the set.
121func (s Set) Values() []interface{} {
122 var ret []interface{}
123 s.EachValue(func(v interface{}) {
124 ret = append(ret, v)
125 })
126 return ret
127}
128
129// Length returns the number of values in the set.
130func (s Set) Length() int {
131 var count int
132 for _, bucket := range s.vals {
133 count = count + len(bucket)
134 }
135 return count
136}
137
138// Union returns a new set that contains all of the members of both the
139// receiving set and the given set. Both sets must have the same rules, or
140// else this function will panic.
141func (s1 Set) Union(s2 Set) Set {
142 mustHaveSameRules(s1, s2)
143 rs := NewSet(s1.rules)
144 s1.EachValue(func(v interface{}) {
145 rs.Add(v)
146 })
147 s2.EachValue(func(v interface{}) {
148 rs.Add(v)
149 })
150 return rs
151}
152
153// Intersection returns a new set that contains the values that both the
154// receiver and given sets have in common. Both sets must have the same rules,
155// or else this function will panic.
156func (s1 Set) Intersection(s2 Set) Set {
157 mustHaveSameRules(s1, s2)
158 rs := NewSet(s1.rules)
159 s1.EachValue(func(v interface{}) {
160 if s2.Has(v) {
161 rs.Add(v)
162 }
163 })
164 return rs
165}
166
167// Subtract returns a new set that contains all of the values from the receiver
168// that are not also in the given set. Both sets must have the same rules,
169// or else this function will panic.
170func (s1 Set) Subtract(s2 Set) Set {
171 mustHaveSameRules(s1, s2)
172 rs := NewSet(s1.rules)
173 s1.EachValue(func(v interface{}) {
174 if !s2.Has(v) {
175 rs.Add(v)
176 }
177 })
178 return rs
179}
180
181// SymmetricDifference returns a new set that contains all of the values from
182// both the receiver and given sets, except those that both sets have in
183// common. Both sets must have the same rules, or else this function will
184// panic.
185func (s1 Set) SymmetricDifference(s2 Set) Set {
186 mustHaveSameRules(s1, s2)
187 rs := NewSet(s1.rules)
188 s1.EachValue(func(v interface{}) {
189 if !s2.Has(v) {
190 rs.Add(v)
191 }
192 })
193 s2.EachValue(func(v interface{}) {
194 if !s1.Has(v) {
195 rs.Add(v)
196 }
197 })
198 return rs
199}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/rules.go b/vendor/github.com/zclconf/go-cty/cty/set/rules.go
new file mode 100644
index 0000000..7200184
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/rules.go
@@ -0,0 +1,25 @@
1package set
2
3// Rules represents the operations that define membership for a Set.
4//
5// Each Set has a Rules instance, whose methods must satisfy the interface
6// contracts given below for any value that will be added to the set.
7type Rules interface {
8 // Hash returns an int that somewhat-uniquely identifies the given value.
9 //
10 // A good hash function will minimize collisions for values that will be
11 // added to the set, though collisions *are* permitted. Collisions will
12 // simply reduce the efficiency of operations on the set.
13 Hash(interface{}) int
14
15 // Equivalent returns true if and only if the two values are considered
16 // equivalent for the sake of set membership. Two values that are
17 // equivalent cannot exist in the set at the same time, and if two
18 // equivalent values are added it is undefined which one will be
19 // returned when enumerating all of the set members.
20 //
21 // Two values that are equivalent *must* result in the same hash value,
22 // though it is *not* required that two values with the same hash value
23 // be equivalent.
24 Equivalent(interface{}, interface{}) bool
25}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/set.go b/vendor/github.com/zclconf/go-cty/cty/set/set.go
new file mode 100644
index 0000000..b4fb316
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/set.go
@@ -0,0 +1,62 @@
1package set
2
3import (
4 "fmt"
5)
6
7// Set is an implementation of the concept of a set: a collection where all
8// values are conceptually either in or out of the set, but the members are
9// not ordered.
10//
11// This type primarily exists to be the internal type of sets in cty, but
12// it is considered to be at the same level of abstraction as Go's built in
13// slice and map collection types, and so should make no cty-specific
14// assumptions.
15//
16// Set operations are not thread safe. It is the caller's responsibility to
17// provide mutex guarantees where necessary.
18//
19// Set operations are not optimized to minimize memory pressure. Mutating
20// a set will generally create garbage and so should perhaps be avoided in
21// tight loops where memory pressure is a concern.
22type Set struct {
23 vals map[int][]interface{}
24 rules Rules
25}
26
27// NewSet returns an empty set with the membership rules given.
28func NewSet(rules Rules) Set {
29 return Set{
30 vals: map[int][]interface{}{},
31 rules: rules,
32 }
33}
34
35func NewSetFromSlice(rules Rules, vals []interface{}) Set {
36 s := NewSet(rules)
37 for _, v := range vals {
38 s.Add(v)
39 }
40 return s
41}
42
43func sameRules(s1 Set, s2 Set) bool {
44 return s1.rules == s2.rules
45}
46
47func mustHaveSameRules(s1 Set, s2 Set) {
48 if !sameRules(s1, s2) {
49 panic(fmt.Errorf("incompatible set rules: %#v, %#v", s1.rules, s2.rules))
50 }
51}
52
53// HasRules returns true if and only if the receiving set has the given rules
54// instance as its rules.
55func (s Set) HasRules(rules Rules) bool {
56 return s.rules == rules
57}
58
59// Rules returns the receiving set's rules instance.
60func (s Set) Rules() Rules {
61 return s.rules
62}