diff options
author | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
---|---|---|
committer | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
commit | 107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch) | |
tree | ca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/zclconf/go-cty/cty/path_set.go | |
parent | 844b5a68d8af4791755b8f0ad293cc99f5959183 (diff) | |
download | terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip |
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/path_set.go')
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/path_set.go | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/path_set.go b/vendor/github.com/zclconf/go-cty/cty/path_set.go new file mode 100644 index 0000000..f1c892b --- /dev/null +++ b/vendor/github.com/zclconf/go-cty/cty/path_set.go | |||
@@ -0,0 +1,198 @@ | |||
1 | package cty | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "hash/crc64" | ||
6 | |||
7 | "github.com/zclconf/go-cty/cty/set" | ||
8 | ) | ||
9 | |||
10 | // PathSet represents a set of Path objects. This can be used, for example, | ||
11 | // to talk about a subset of paths within a value that meet some criteria, | ||
12 | // without directly modifying the values at those paths. | ||
13 | type PathSet struct { | ||
14 | set set.Set | ||
15 | } | ||
16 | |||
17 | // NewPathSet creates and returns a PathSet, with initial contents optionally | ||
18 | // set by the given arguments. | ||
19 | func NewPathSet(paths ...Path) PathSet { | ||
20 | ret := PathSet{ | ||
21 | set: set.NewSet(pathSetRules{}), | ||
22 | } | ||
23 | |||
24 | for _, path := range paths { | ||
25 | ret.Add(path) | ||
26 | } | ||
27 | |||
28 | return ret | ||
29 | } | ||
30 | |||
31 | // Add inserts a single given path into the set. | ||
32 | // | ||
33 | // Paths are immutable after construction by convention. It is particularly | ||
34 | // important not to mutate a path after it has been placed into a PathSet. | ||
35 | // If a Path is mutated while in a set, behavior is undefined. | ||
36 | func (s PathSet) Add(path Path) { | ||
37 | s.set.Add(path) | ||
38 | } | ||
39 | |||
40 | // AddAllSteps is like Add but it also adds all of the steps leading to | ||
41 | // the given path. | ||
42 | // | ||
43 | // For example, if given a path representing "foo.bar", it will add both | ||
44 | // "foo" and "bar". | ||
45 | func (s PathSet) AddAllSteps(path Path) { | ||
46 | for i := 1; i <= len(path); i++ { | ||
47 | s.Add(path[:i]) | ||
48 | } | ||
49 | } | ||
50 | |||
51 | // Has returns true if the given path is in the receiving set. | ||
52 | func (s PathSet) Has(path Path) bool { | ||
53 | return s.set.Has(path) | ||
54 | } | ||
55 | |||
56 | // List makes and returns a slice of all of the paths in the receiving set, | ||
57 | // in an undefined but consistent order. | ||
58 | func (s PathSet) List() []Path { | ||
59 | if s.Empty() { | ||
60 | return nil | ||
61 | } | ||
62 | ret := make([]Path, 0, s.set.Length()) | ||
63 | for it := s.set.Iterator(); it.Next(); { | ||
64 | ret = append(ret, it.Value().(Path)) | ||
65 | } | ||
66 | return ret | ||
67 | } | ||
68 | |||
69 | // Remove modifies the receving set to no longer include the given path. | ||
70 | // If the given path was already absent, this is a no-op. | ||
71 | func (s PathSet) Remove(path Path) { | ||
72 | s.set.Remove(path) | ||
73 | } | ||
74 | |||
75 | // Empty returns true if the length of the receiving set is zero. | ||
76 | func (s PathSet) Empty() bool { | ||
77 | return s.set.Length() == 0 | ||
78 | } | ||
79 | |||
80 | // Union returns a new set whose contents are the union of the receiver and | ||
81 | // the given other set. | ||
82 | func (s PathSet) Union(other PathSet) PathSet { | ||
83 | return PathSet{ | ||
84 | set: s.set.Union(other.set), | ||
85 | } | ||
86 | } | ||
87 | |||
88 | // Intersection returns a new set whose contents are the intersection of the | ||
89 | // receiver and the given other set. | ||
90 | func (s PathSet) Intersection(other PathSet) PathSet { | ||
91 | return PathSet{ | ||
92 | set: s.set.Intersection(other.set), | ||
93 | } | ||
94 | } | ||
95 | |||
96 | // Subtract returns a new set whose contents are those from the receiver with | ||
97 | // any elements of the other given set subtracted. | ||
98 | func (s PathSet) Subtract(other PathSet) PathSet { | ||
99 | return PathSet{ | ||
100 | set: s.set.Subtract(other.set), | ||
101 | } | ||
102 | } | ||
103 | |||
104 | // SymmetricDifference returns a new set whose contents are the symmetric | ||
105 | // difference of the receiver and the given other set. | ||
106 | func (s PathSet) SymmetricDifference(other PathSet) PathSet { | ||
107 | return PathSet{ | ||
108 | set: s.set.SymmetricDifference(other.set), | ||
109 | } | ||
110 | } | ||
111 | |||
112 | // Equal returns true if and only if both the receiver and the given other | ||
113 | // set contain exactly the same paths. | ||
114 | func (s PathSet) Equal(other PathSet) bool { | ||
115 | if s.set.Length() != other.set.Length() { | ||
116 | return false | ||
117 | } | ||
118 | // Now we know the lengths are the same we only need to test in one | ||
119 | // direction whether everything in one is in the other. | ||
120 | for it := s.set.Iterator(); it.Next(); { | ||
121 | if !other.set.Has(it.Value()) { | ||
122 | return false | ||
123 | } | ||
124 | } | ||
125 | return true | ||
126 | } | ||
127 | |||
128 | var crc64Table = crc64.MakeTable(crc64.ISO) | ||
129 | |||
130 | var indexStepPlaceholder = []byte("#") | ||
131 | |||
132 | // pathSetRules is an implementation of set.Rules from the set package, | ||
133 | // used internally within PathSet. | ||
134 | type pathSetRules struct { | ||
135 | } | ||
136 | |||
137 | func (r pathSetRules) Hash(v interface{}) int { | ||
138 | path := v.(Path) | ||
139 | hash := crc64.New(crc64Table) | ||
140 | |||
141 | for _, rawStep := range path { | ||
142 | switch step := rawStep.(type) { | ||
143 | case GetAttrStep: | ||
144 | // (this creates some garbage converting the string name to a | ||
145 | // []byte, but that's okay since cty is not designed to be | ||
146 | // used in tight loops under memory pressure.) | ||
147 | hash.Write([]byte(step.Name)) | ||
148 | default: | ||
149 | // For any other step type we just append a predefined value, | ||
150 | // which means that e.g. all indexes into a given collection will | ||
151 | // hash to the same value but we assume that collections are | ||
152 | // small and thus this won't hurt too much. | ||
153 | hash.Write(indexStepPlaceholder) | ||
154 | } | ||
155 | } | ||
156 | |||
157 | // We discard half of the hash on 32-bit platforms; collisions just make | ||
158 | // our lookups take marginally longer, so not a big deal. | ||
159 | return int(hash.Sum64()) | ||
160 | } | ||
161 | |||
162 | func (r pathSetRules) Equivalent(a, b interface{}) bool { | ||
163 | aPath := a.(Path) | ||
164 | bPath := b.(Path) | ||
165 | |||
166 | if len(aPath) != len(bPath) { | ||
167 | return false | ||
168 | } | ||
169 | |||
170 | for i := range aPath { | ||
171 | switch aStep := aPath[i].(type) { | ||
172 | case GetAttrStep: | ||
173 | bStep, ok := bPath[i].(GetAttrStep) | ||
174 | if !ok { | ||
175 | return false | ||
176 | } | ||
177 | |||
178 | if aStep.Name != bStep.Name { | ||
179 | return false | ||
180 | } | ||
181 | case IndexStep: | ||
182 | bStep, ok := bPath[i].(IndexStep) | ||
183 | if !ok { | ||
184 | return false | ||
185 | } | ||
186 | |||
187 | eq := aStep.Key.Equals(bStep.Key) | ||
188 | if !eq.IsKnown() || eq.False() { | ||
189 | return false | ||
190 | } | ||
191 | default: | ||
192 | // Should never happen, since we document PathStep as a closed type. | ||
193 | panic(fmt.Errorf("unsupported step type %T", aStep)) | ||
194 | } | ||
195 | } | ||
196 | |||
197 | return true | ||
198 | } | ||