diff options
author | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
---|---|---|
committer | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
commit | 15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch) | |
tree | 255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/zclconf/go-cty/cty/gocty | |
parent | 07971ca38143c5faf951d152fba370ddcbe26ad5 (diff) | |
download | terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.gz terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.zst terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.zip |
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
Updated via: go get github.com/hashicorp/terraform@sdk-v0.11-with-go-modules and go mod tidy
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/gocty')
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/gocty/doc.go | 7 | ||||
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go | 43 | ||||
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/gocty/in.go | 528 | ||||
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/gocty/out.go | 705 | ||||
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go | 108 |
5 files changed, 1391 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go b/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go new file mode 100644 index 0000000..a5177d2 --- /dev/null +++ b/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go | |||
@@ -0,0 +1,7 @@ | |||
1 | // Package gocty deals with converting between cty Values and native go | ||
2 | // values. | ||
3 | // | ||
4 | // It operates under a similar principle to the encoding/json and | ||
5 | // encoding/xml packages in the standard library, using reflection to | ||
6 | // populate native Go data structures from cty values and vice-versa. | ||
7 | package gocty | ||
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go b/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go new file mode 100644 index 0000000..94ffd2f --- /dev/null +++ b/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go | |||
@@ -0,0 +1,43 @@ | |||
1 | package gocty | ||
2 | |||
3 | import ( | ||
4 | "math/big" | ||
5 | "reflect" | ||
6 | |||
7 | "github.com/zclconf/go-cty/cty" | ||
8 | "github.com/zclconf/go-cty/cty/set" | ||
9 | ) | ||
10 | |||
11 | var valueType = reflect.TypeOf(cty.Value{}) | ||
12 | var typeType = reflect.TypeOf(cty.Type{}) | ||
13 | |||
14 | var setType = reflect.TypeOf(set.Set{}) | ||
15 | |||
16 | var bigFloatType = reflect.TypeOf(big.Float{}) | ||
17 | var bigIntType = reflect.TypeOf(big.Int{}) | ||
18 | |||
19 | var emptyInterfaceType = reflect.TypeOf(interface{}(nil)) | ||
20 | |||
21 | var stringType = reflect.TypeOf("") | ||
22 | |||
23 | // structTagIndices interrogates the fields of the given type (which must | ||
24 | // be a struct type, or we'll panic) and returns a map from the cty | ||
25 | // attribute names declared via struct tags to the indices of the | ||
26 | // fields holding those tags. | ||
27 | // | ||
28 | // This function will panic if two fields within the struct are tagged with | ||
29 | // the same cty attribute name. | ||
30 | func structTagIndices(st reflect.Type) map[string]int { | ||
31 | ct := st.NumField() | ||
32 | ret := make(map[string]int, ct) | ||
33 | |||
34 | for i := 0; i < ct; i++ { | ||
35 | field := st.Field(i) | ||
36 | attrName := field.Tag.Get("cty") | ||
37 | if attrName != "" { | ||
38 | ret[attrName] = i | ||
39 | } | ||
40 | } | ||
41 | |||
42 | return ret | ||
43 | } | ||
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/in.go b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go new file mode 100644 index 0000000..642501b --- /dev/null +++ b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go | |||
@@ -0,0 +1,528 @@ | |||
1 | package gocty | ||
2 | |||
3 | import ( | ||
4 | "math/big" | ||
5 | "reflect" | ||
6 | |||
7 | "github.com/zclconf/go-cty/cty" | ||
8 | "github.com/zclconf/go-cty/cty/set" | ||
9 | ) | ||
10 | |||
11 | // ToCtyValue produces a cty.Value from a Go value. The result will conform | ||
12 | // to the given type, or an error will be returned if this is not possible. | ||
13 | // | ||
14 | // The target type serves as a hint to resolve ambiguities in the mapping. | ||
15 | // For example, the Go type set.Set tells us that the value is a set but | ||
16 | // does not describe the set's element type. This also allows for convenient | ||
17 | // conversions, such as populating a set from a slice rather than having to | ||
18 | // first explicitly instantiate a set.Set. | ||
19 | // | ||
20 | // The audience of this function is assumed to be the developers of Go code | ||
21 | // that is integrating with cty, and thus the error messages it returns are | ||
22 | // presented from Go's perspective. These messages are thus not appropriate | ||
23 | // for display to end-users. An error returned from ToCtyValue represents a | ||
24 | // bug in the calling program, not user error. | ||
25 | func ToCtyValue(val interface{}, ty cty.Type) (cty.Value, error) { | ||
26 | // 'path' starts off as empty but will grow for each level of recursive | ||
27 | // call we make, so by the time toCtyValue returns it is likely to have | ||
28 | // unused capacity on the end of it, depending on how deeply-recursive | ||
29 | // the given Type is. | ||
30 | path := make(cty.Path, 0) | ||
31 | return toCtyValue(reflect.ValueOf(val), ty, path) | ||
32 | } | ||
33 | |||
34 | func toCtyValue(val reflect.Value, ty cty.Type, path cty.Path) (cty.Value, error) { | ||
35 | |||
36 | switch ty { | ||
37 | case cty.Bool: | ||
38 | return toCtyBool(val, path) | ||
39 | case cty.Number: | ||
40 | return toCtyNumber(val, path) | ||
41 | case cty.String: | ||
42 | return toCtyString(val, path) | ||
43 | case cty.DynamicPseudoType: | ||
44 | return toCtyDynamic(val, path) | ||
45 | } | ||
46 | |||
47 | switch { | ||
48 | case ty.IsListType(): | ||
49 | return toCtyList(val, ty.ElementType(), path) | ||
50 | case ty.IsMapType(): | ||
51 | return toCtyMap(val, ty.ElementType(), path) | ||
52 | case ty.IsSetType(): | ||
53 | return toCtySet(val, ty.ElementType(), path) | ||
54 | case ty.IsObjectType(): | ||
55 | return toCtyObject(val, ty.AttributeTypes(), path) | ||
56 | case ty.IsTupleType(): | ||
57 | return toCtyTuple(val, ty.TupleElementTypes(), path) | ||
58 | case ty.IsCapsuleType(): | ||
59 | return toCtyCapsule(val, ty, path) | ||
60 | } | ||
61 | |||
62 | // We should never fall out here | ||
63 | return cty.NilVal, path.NewErrorf("unsupported target type %#v", ty) | ||
64 | } | ||
65 | |||
66 | func toCtyBool(val reflect.Value, path cty.Path) (cty.Value, error) { | ||
67 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
68 | return cty.NullVal(cty.Bool), nil | ||
69 | } | ||
70 | |||
71 | switch val.Kind() { | ||
72 | |||
73 | case reflect.Bool: | ||
74 | return cty.BoolVal(val.Bool()), nil | ||
75 | |||
76 | default: | ||
77 | return cty.NilVal, path.NewErrorf("can't convert Go %s to bool", val.Kind()) | ||
78 | |||
79 | } | ||
80 | |||
81 | } | ||
82 | |||
83 | func toCtyNumber(val reflect.Value, path cty.Path) (cty.Value, error) { | ||
84 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
85 | return cty.NullVal(cty.Number), nil | ||
86 | } | ||
87 | |||
88 | switch val.Kind() { | ||
89 | |||
90 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
91 | return cty.NumberIntVal(val.Int()), nil | ||
92 | |||
93 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
94 | return cty.NumberUIntVal(val.Uint()), nil | ||
95 | |||
96 | case reflect.Float32, reflect.Float64: | ||
97 | return cty.NumberFloatVal(val.Float()), nil | ||
98 | |||
99 | case reflect.Struct: | ||
100 | if val.Type().AssignableTo(bigIntType) { | ||
101 | bigInt := val.Interface().(big.Int) | ||
102 | bigFloat := (&big.Float{}).SetInt(&bigInt) | ||
103 | val = reflect.ValueOf(*bigFloat) | ||
104 | } | ||
105 | |||
106 | if val.Type().AssignableTo(bigFloatType) { | ||
107 | bigFloat := val.Interface().(big.Float) | ||
108 | return cty.NumberVal(&bigFloat), nil | ||
109 | } | ||
110 | |||
111 | fallthrough | ||
112 | default: | ||
113 | return cty.NilVal, path.NewErrorf("can't convert Go %s to number", val.Kind()) | ||
114 | |||
115 | } | ||
116 | |||
117 | } | ||
118 | |||
119 | func toCtyString(val reflect.Value, path cty.Path) (cty.Value, error) { | ||
120 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
121 | return cty.NullVal(cty.String), nil | ||
122 | } | ||
123 | |||
124 | switch val.Kind() { | ||
125 | |||
126 | case reflect.String: | ||
127 | return cty.StringVal(val.String()), nil | ||
128 | |||
129 | default: | ||
130 | return cty.NilVal, path.NewErrorf("can't convert Go %s to string", val.Kind()) | ||
131 | |||
132 | } | ||
133 | |||
134 | } | ||
135 | |||
136 | func toCtyList(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) { | ||
137 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
138 | return cty.NullVal(cty.List(ety)), nil | ||
139 | } | ||
140 | |||
141 | switch val.Kind() { | ||
142 | |||
143 | case reflect.Slice: | ||
144 | if val.IsNil() { | ||
145 | return cty.NullVal(cty.List(ety)), nil | ||
146 | } | ||
147 | fallthrough | ||
148 | case reflect.Array: | ||
149 | if val.Len() == 0 { | ||
150 | return cty.ListValEmpty(ety), nil | ||
151 | } | ||
152 | |||
153 | // While we work on our elements we'll temporarily grow | ||
154 | // path to give us a place to put our index step. | ||
155 | path = append(path, cty.PathStep(nil)) | ||
156 | |||
157 | vals := make([]cty.Value, val.Len()) | ||
158 | for i := range vals { | ||
159 | var err error | ||
160 | path[len(path)-1] = cty.IndexStep{ | ||
161 | Key: cty.NumberIntVal(int64(i)), | ||
162 | } | ||
163 | vals[i], err = toCtyValue(val.Index(i), ety, path) | ||
164 | if err != nil { | ||
165 | return cty.NilVal, err | ||
166 | } | ||
167 | } | ||
168 | |||
169 | // Discard our extra path segment, retaining it as extra capacity | ||
170 | // for future appending to the path. | ||
171 | path = path[:len(path)-1] | ||
172 | |||
173 | return cty.ListVal(vals), nil | ||
174 | |||
175 | default: | ||
176 | return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.List(ety)) | ||
177 | |||
178 | } | ||
179 | } | ||
180 | |||
181 | func toCtyMap(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) { | ||
182 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
183 | return cty.NullVal(cty.Map(ety)), nil | ||
184 | } | ||
185 | |||
186 | switch val.Kind() { | ||
187 | |||
188 | case reflect.Map: | ||
189 | if val.IsNil() { | ||
190 | return cty.NullVal(cty.Map(ety)), nil | ||
191 | } | ||
192 | |||
193 | if val.Len() == 0 { | ||
194 | return cty.MapValEmpty(ety), nil | ||
195 | } | ||
196 | |||
197 | keyType := val.Type().Key() | ||
198 | if keyType.Kind() != reflect.String { | ||
199 | return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType) | ||
200 | } | ||
201 | |||
202 | // While we work on our elements we'll temporarily grow | ||
203 | // path to give us a place to put our index step. | ||
204 | path = append(path, cty.PathStep(nil)) | ||
205 | |||
206 | vals := make(map[string]cty.Value, val.Len()) | ||
207 | for _, kv := range val.MapKeys() { | ||
208 | k := kv.String() | ||
209 | var err error | ||
210 | path[len(path)-1] = cty.IndexStep{ | ||
211 | Key: cty.StringVal(k), | ||
212 | } | ||
213 | vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), ety, path) | ||
214 | if err != nil { | ||
215 | return cty.NilVal, err | ||
216 | } | ||
217 | } | ||
218 | |||
219 | // Discard our extra path segment, retaining it as extra capacity | ||
220 | // for future appending to the path. | ||
221 | path = path[:len(path)-1] | ||
222 | |||
223 | return cty.MapVal(vals), nil | ||
224 | |||
225 | default: | ||
226 | return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Map(ety)) | ||
227 | |||
228 | } | ||
229 | } | ||
230 | |||
231 | func toCtySet(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) { | ||
232 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
233 | return cty.NullVal(cty.Set(ety)), nil | ||
234 | } | ||
235 | |||
236 | var vals []cty.Value | ||
237 | |||
238 | switch val.Kind() { | ||
239 | |||
240 | case reflect.Slice: | ||
241 | if val.IsNil() { | ||
242 | return cty.NullVal(cty.Set(ety)), nil | ||
243 | } | ||
244 | fallthrough | ||
245 | case reflect.Array: | ||
246 | if val.Len() == 0 { | ||
247 | return cty.SetValEmpty(ety), nil | ||
248 | } | ||
249 | |||
250 | vals = make([]cty.Value, val.Len()) | ||
251 | for i := range vals { | ||
252 | var err error | ||
253 | vals[i], err = toCtyValue(val.Index(i), ety, path) | ||
254 | if err != nil { | ||
255 | return cty.NilVal, err | ||
256 | } | ||
257 | } | ||
258 | |||
259 | case reflect.Struct: | ||
260 | |||
261 | if !val.Type().AssignableTo(setType) { | ||
262 | return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Type(), cty.Set(ety)) | ||
263 | } | ||
264 | |||
265 | rawSet := val.Interface().(set.Set) | ||
266 | inVals := rawSet.Values() | ||
267 | |||
268 | if len(inVals) == 0 { | ||
269 | return cty.SetValEmpty(ety), nil | ||
270 | } | ||
271 | |||
272 | vals = make([]cty.Value, len(inVals)) | ||
273 | for i := range inVals { | ||
274 | var err error | ||
275 | vals[i], err = toCtyValue(reflect.ValueOf(inVals[i]), ety, path) | ||
276 | if err != nil { | ||
277 | return cty.NilVal, err | ||
278 | } | ||
279 | } | ||
280 | |||
281 | default: | ||
282 | return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Set(ety)) | ||
283 | |||
284 | } | ||
285 | |||
286 | return cty.SetVal(vals), nil | ||
287 | } | ||
288 | |||
289 | func toCtyObject(val reflect.Value, attrTypes map[string]cty.Type, path cty.Path) (cty.Value, error) { | ||
290 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
291 | return cty.NullVal(cty.Object(attrTypes)), nil | ||
292 | } | ||
293 | |||
294 | switch val.Kind() { | ||
295 | |||
296 | case reflect.Map: | ||
297 | if val.IsNil() { | ||
298 | return cty.NullVal(cty.Object(attrTypes)), nil | ||
299 | } | ||
300 | |||
301 | keyType := val.Type().Key() | ||
302 | if keyType.Kind() != reflect.String { | ||
303 | return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType) | ||
304 | } | ||
305 | |||
306 | if len(attrTypes) == 0 { | ||
307 | return cty.EmptyObjectVal, nil | ||
308 | } | ||
309 | |||
310 | // While we work on our elements we'll temporarily grow | ||
311 | // path to give us a place to put our GetAttr step. | ||
312 | path = append(path, cty.PathStep(nil)) | ||
313 | |||
314 | haveKeys := make(map[string]struct{}, val.Len()) | ||
315 | for _, kv := range val.MapKeys() { | ||
316 | haveKeys[kv.String()] = struct{}{} | ||
317 | } | ||
318 | |||
319 | vals := make(map[string]cty.Value, len(attrTypes)) | ||
320 | for k, at := range attrTypes { | ||
321 | var err error | ||
322 | path[len(path)-1] = cty.GetAttrStep{ | ||
323 | Name: k, | ||
324 | } | ||
325 | |||
326 | if _, have := haveKeys[k]; !have { | ||
327 | vals[k] = cty.NullVal(at) | ||
328 | continue | ||
329 | } | ||
330 | |||
331 | vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), at, path) | ||
332 | if err != nil { | ||
333 | return cty.NilVal, err | ||
334 | } | ||
335 | } | ||
336 | |||
337 | // Discard our extra path segment, retaining it as extra capacity | ||
338 | // for future appending to the path. | ||
339 | path = path[:len(path)-1] | ||
340 | |||
341 | return cty.ObjectVal(vals), nil | ||
342 | |||
343 | case reflect.Struct: | ||
344 | if len(attrTypes) == 0 { | ||
345 | return cty.EmptyObjectVal, nil | ||
346 | } | ||
347 | |||
348 | // While we work on our elements we'll temporarily grow | ||
349 | // path to give us a place to put our GetAttr step. | ||
350 | path = append(path, cty.PathStep(nil)) | ||
351 | |||
352 | attrFields := structTagIndices(val.Type()) | ||
353 | |||
354 | vals := make(map[string]cty.Value, len(attrTypes)) | ||
355 | for k, at := range attrTypes { | ||
356 | path[len(path)-1] = cty.GetAttrStep{ | ||
357 | Name: k, | ||
358 | } | ||
359 | |||
360 | if fieldIdx, have := attrFields[k]; have { | ||
361 | var err error | ||
362 | vals[k], err = toCtyValue(val.Field(fieldIdx), at, path) | ||
363 | if err != nil { | ||
364 | return cty.NilVal, err | ||
365 | } | ||
366 | } else { | ||
367 | vals[k] = cty.NullVal(at) | ||
368 | } | ||
369 | } | ||
370 | |||
371 | // Discard our extra path segment, retaining it as extra capacity | ||
372 | // for future appending to the path. | ||
373 | path = path[:len(path)-1] | ||
374 | |||
375 | return cty.ObjectVal(vals), nil | ||
376 | |||
377 | default: | ||
378 | return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Object(attrTypes)) | ||
379 | |||
380 | } | ||
381 | } | ||
382 | |||
383 | func toCtyTuple(val reflect.Value, elemTypes []cty.Type, path cty.Path) (cty.Value, error) { | ||
384 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
385 | return cty.NullVal(cty.Tuple(elemTypes)), nil | ||
386 | } | ||
387 | |||
388 | switch val.Kind() { | ||
389 | |||
390 | case reflect.Slice: | ||
391 | if val.IsNil() { | ||
392 | return cty.NullVal(cty.Tuple(elemTypes)), nil | ||
393 | } | ||
394 | |||
395 | if val.Len() != len(elemTypes) { | ||
396 | return cty.NilVal, path.NewErrorf("wrong number of elements %d; need %d", val.Len(), len(elemTypes)) | ||
397 | } | ||
398 | |||
399 | if len(elemTypes) == 0 { | ||
400 | return cty.EmptyTupleVal, nil | ||
401 | } | ||
402 | |||
403 | // While we work on our elements we'll temporarily grow | ||
404 | // path to give us a place to put our Index step. | ||
405 | path = append(path, cty.PathStep(nil)) | ||
406 | |||
407 | vals := make([]cty.Value, len(elemTypes)) | ||
408 | for i, ety := range elemTypes { | ||
409 | var err error | ||
410 | |||
411 | path[len(path)-1] = cty.IndexStep{ | ||
412 | Key: cty.NumberIntVal(int64(i)), | ||
413 | } | ||
414 | |||
415 | vals[i], err = toCtyValue(val.Index(i), ety, path) | ||
416 | if err != nil { | ||
417 | return cty.NilVal, err | ||
418 | } | ||
419 | } | ||
420 | |||
421 | // Discard our extra path segment, retaining it as extra capacity | ||
422 | // for future appending to the path. | ||
423 | path = path[:len(path)-1] | ||
424 | |||
425 | return cty.TupleVal(vals), nil | ||
426 | |||
427 | case reflect.Struct: | ||
428 | fieldCount := val.Type().NumField() | ||
429 | if fieldCount != len(elemTypes) { | ||
430 | return cty.NilVal, path.NewErrorf("wrong number of struct fields %d; need %d", fieldCount, len(elemTypes)) | ||
431 | } | ||
432 | |||
433 | if len(elemTypes) == 0 { | ||
434 | return cty.EmptyTupleVal, nil | ||
435 | } | ||
436 | |||
437 | // While we work on our elements we'll temporarily grow | ||
438 | // path to give us a place to put our Index step. | ||
439 | path = append(path, cty.PathStep(nil)) | ||
440 | |||
441 | vals := make([]cty.Value, len(elemTypes)) | ||
442 | for i, ety := range elemTypes { | ||
443 | var err error | ||
444 | |||
445 | path[len(path)-1] = cty.IndexStep{ | ||
446 | Key: cty.NumberIntVal(int64(i)), | ||
447 | } | ||
448 | |||
449 | vals[i], err = toCtyValue(val.Field(i), ety, path) | ||
450 | if err != nil { | ||
451 | return cty.NilVal, err | ||
452 | } | ||
453 | } | ||
454 | |||
455 | // Discard our extra path segment, retaining it as extra capacity | ||
456 | // for future appending to the path. | ||
457 | path = path[:len(path)-1] | ||
458 | |||
459 | return cty.TupleVal(vals), nil | ||
460 | |||
461 | default: | ||
462 | return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Tuple(elemTypes)) | ||
463 | |||
464 | } | ||
465 | } | ||
466 | |||
467 | func toCtyCapsule(val reflect.Value, capsuleType cty.Type, path cty.Path) (cty.Value, error) { | ||
468 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
469 | return cty.NullVal(capsuleType), nil | ||
470 | } | ||
471 | |||
472 | if val.Kind() != reflect.Ptr { | ||
473 | if !val.CanAddr() { | ||
474 | return cty.NilVal, path.NewErrorf("source value for capsule %#v must be addressable", capsuleType) | ||
475 | } | ||
476 | |||
477 | val = val.Addr() | ||
478 | } | ||
479 | |||
480 | if !val.Type().Elem().AssignableTo(capsuleType.EncapsulatedType()) { | ||
481 | return cty.NilVal, path.NewErrorf("value of type %T not compatible with capsule %#v", val.Interface(), capsuleType) | ||
482 | } | ||
483 | |||
484 | return cty.CapsuleVal(capsuleType, val.Interface()), nil | ||
485 | } | ||
486 | |||
487 | func toCtyDynamic(val reflect.Value, path cty.Path) (cty.Value, error) { | ||
488 | if val = toCtyUnwrapPointer(val); !val.IsValid() { | ||
489 | return cty.NullVal(cty.DynamicPseudoType), nil | ||
490 | } | ||
491 | |||
492 | switch val.Kind() { | ||
493 | |||
494 | case reflect.Struct: | ||
495 | if !val.Type().AssignableTo(valueType) { | ||
496 | return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Type()) | ||
497 | } | ||
498 | |||
499 | return val.Interface().(cty.Value), nil | ||
500 | |||
501 | default: | ||
502 | return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Kind()) | ||
503 | |||
504 | } | ||
505 | |||
506 | } | ||
507 | |||
508 | // toCtyUnwrapPointer is a helper for dealing with Go pointers. It has three | ||
509 | // possible outcomes: | ||
510 | // | ||
511 | // - Given value isn't a pointer, so it's just returned as-is. | ||
512 | // - Given value is a non-nil pointer, in which case it is dereferenced | ||
513 | // and the result returned. | ||
514 | // - Given value is a nil pointer, in which case an invalid value is returned. | ||
515 | // | ||
516 | // For nested pointer types, like **int, they are all dereferenced in turn | ||
517 | // until a non-pointer value is found, or until a nil pointer is encountered. | ||
518 | func toCtyUnwrapPointer(val reflect.Value) reflect.Value { | ||
519 | for val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface { | ||
520 | if val.IsNil() { | ||
521 | return reflect.Value{} | ||
522 | } | ||
523 | |||
524 | val = val.Elem() | ||
525 | } | ||
526 | |||
527 | return val | ||
528 | } | ||
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/out.go b/vendor/github.com/zclconf/go-cty/cty/gocty/out.go new file mode 100644 index 0000000..99b65a7 --- /dev/null +++ b/vendor/github.com/zclconf/go-cty/cty/gocty/out.go | |||
@@ -0,0 +1,705 @@ | |||
1 | package gocty | ||
2 | |||
3 | import ( | ||
4 | "math/big" | ||
5 | "reflect" | ||
6 | |||
7 | "math" | ||
8 | |||
9 | "github.com/zclconf/go-cty/cty" | ||
10 | ) | ||
11 | |||
12 | // FromCtyValue assigns a cty.Value to a reflect.Value, which must be a pointer, | ||
13 | // using a fixed set of conversion rules. | ||
14 | // | ||
15 | // This function considers its audience to be the creator of the cty Value | ||
16 | // given, and thus the error messages it generates are (unlike with ToCtyValue) | ||
17 | // presented in cty terminology that is generally appropriate to return to | ||
18 | // end-users in applications where cty data structures are built from | ||
19 | // user-provided configuration. In particular this means that if incorrect | ||
20 | // target types are provided by the calling application the resulting error | ||
21 | // messages are likely to be confusing, since we assume that the given target | ||
22 | // type is correct and the cty.Value is where the error lies. | ||
23 | // | ||
24 | // If an error is returned, the target data structure may have been partially | ||
25 | // populated, but the degree to which this is true is an implementation | ||
26 | // detail that the calling application should not rely on. | ||
27 | // | ||
28 | // The function will panic if given a non-pointer as the Go value target, | ||
29 | // since that is considered to be a bug in the calling program. | ||
30 | func FromCtyValue(val cty.Value, target interface{}) error { | ||
31 | tVal := reflect.ValueOf(target) | ||
32 | if tVal.Kind() != reflect.Ptr { | ||
33 | panic("target value is not a pointer") | ||
34 | } | ||
35 | if tVal.IsNil() { | ||
36 | panic("target value is nil pointer") | ||
37 | } | ||
38 | |||
39 | // 'path' starts off as empty but will grow for each level of recursive | ||
40 | // call we make, so by the time fromCtyValue returns it is likely to have | ||
41 | // unused capacity on the end of it, depending on how deeply-recursive | ||
42 | // the given cty.Value is. | ||
43 | path := make(cty.Path, 0) | ||
44 | return fromCtyValue(val, tVal, path) | ||
45 | } | ||
46 | |||
47 | func fromCtyValue(val cty.Value, target reflect.Value, path cty.Path) error { | ||
48 | ty := val.Type() | ||
49 | |||
50 | deepTarget := fromCtyPopulatePtr(target, false) | ||
51 | |||
52 | // If we're decoding into a cty.Value then we just pass through the | ||
53 | // value as-is, to enable partial decoding. This is the only situation | ||
54 | // where unknown values are permitted. | ||
55 | if deepTarget.Kind() == reflect.Struct && deepTarget.Type().AssignableTo(valueType) { | ||
56 | deepTarget.Set(reflect.ValueOf(val)) | ||
57 | return nil | ||
58 | } | ||
59 | |||
60 | // Lists and maps can be nil without indirection, but everything else | ||
61 | // requires a pointer and we set it immediately to nil. | ||
62 | // We also make an exception for capsule types because we want to handle | ||
63 | // pointers specially for these. | ||
64 | // (fromCtyList and fromCtyMap must therefore deal with val.IsNull, while | ||
65 | // other types can assume no nulls after this point.) | ||
66 | if val.IsNull() && !val.Type().IsListType() && !val.Type().IsMapType() && !val.Type().IsCapsuleType() { | ||
67 | target = fromCtyPopulatePtr(target, true) | ||
68 | if target.Kind() != reflect.Ptr { | ||
69 | return path.NewErrorf("null value is not allowed") | ||
70 | } | ||
71 | |||
72 | target.Set(reflect.Zero(target.Type())) | ||
73 | return nil | ||
74 | } | ||
75 | |||
76 | target = deepTarget | ||
77 | |||
78 | if !val.IsKnown() { | ||
79 | return path.NewErrorf("value must be known") | ||
80 | } | ||
81 | |||
82 | switch ty { | ||
83 | case cty.Bool: | ||
84 | return fromCtyBool(val, target, path) | ||
85 | case cty.Number: | ||
86 | return fromCtyNumber(val, target, path) | ||
87 | case cty.String: | ||
88 | return fromCtyString(val, target, path) | ||
89 | } | ||
90 | |||
91 | switch { | ||
92 | case ty.IsListType(): | ||
93 | return fromCtyList(val, target, path) | ||
94 | case ty.IsMapType(): | ||
95 | return fromCtyMap(val, target, path) | ||
96 | case ty.IsSetType(): | ||
97 | return fromCtySet(val, target, path) | ||
98 | case ty.IsObjectType(): | ||
99 | return fromCtyObject(val, target, path) | ||
100 | case ty.IsTupleType(): | ||
101 | return fromCtyTuple(val, target, path) | ||
102 | case ty.IsCapsuleType(): | ||
103 | return fromCtyCapsule(val, target, path) | ||
104 | } | ||
105 | |||
106 | // We should never fall out here; reaching here indicates a bug in this | ||
107 | // function. | ||
108 | return path.NewErrorf("unsupported source type %#v", ty) | ||
109 | } | ||
110 | |||
111 | func fromCtyBool(val cty.Value, target reflect.Value, path cty.Path) error { | ||
112 | switch target.Kind() { | ||
113 | |||
114 | case reflect.Bool: | ||
115 | if val.True() { | ||
116 | target.Set(reflect.ValueOf(true)) | ||
117 | } else { | ||
118 | target.Set(reflect.ValueOf(false)) | ||
119 | } | ||
120 | return nil | ||
121 | |||
122 | default: | ||
123 | return likelyRequiredTypesError(path, target) | ||
124 | |||
125 | } | ||
126 | } | ||
127 | |||
128 | func fromCtyNumber(val cty.Value, target reflect.Value, path cty.Path) error { | ||
129 | bf := val.AsBigFloat() | ||
130 | |||
131 | switch target.Kind() { | ||
132 | |||
133 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
134 | return fromCtyNumberInt(bf, target, path) | ||
135 | |||
136 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
137 | return fromCtyNumberUInt(bf, target, path) | ||
138 | |||
139 | case reflect.Float32, reflect.Float64: | ||
140 | return fromCtyNumberFloat(bf, target, path) | ||
141 | |||
142 | case reflect.Struct: | ||
143 | return fromCtyNumberBig(bf, target, path) | ||
144 | |||
145 | default: | ||
146 | return likelyRequiredTypesError(path, target) | ||
147 | |||
148 | } | ||
149 | } | ||
150 | |||
151 | func fromCtyNumberInt(bf *big.Float, target reflect.Value, path cty.Path) error { | ||
152 | // Doing this with switch rather than << arithmetic because << with | ||
153 | // result >32-bits is not portable to 32-bit systems. | ||
154 | var min int64 | ||
155 | var max int64 | ||
156 | switch target.Type().Bits() { | ||
157 | case 8: | ||
158 | min = math.MinInt8 | ||
159 | max = math.MaxInt8 | ||
160 | case 16: | ||
161 | min = math.MinInt16 | ||
162 | max = math.MaxInt16 | ||
163 | case 32: | ||
164 | min = math.MinInt32 | ||
165 | max = math.MaxInt32 | ||
166 | case 64: | ||
167 | min = math.MinInt64 | ||
168 | max = math.MaxInt64 | ||
169 | default: | ||
170 | panic("weird number of bits in target int") | ||
171 | } | ||
172 | |||
173 | iv, accuracy := bf.Int64() | ||
174 | if accuracy != big.Exact || iv < min || iv > max { | ||
175 | return path.NewErrorf("value must be a whole number, between %d and %d", min, max) | ||
176 | } | ||
177 | |||
178 | target.Set(reflect.ValueOf(iv).Convert(target.Type())) | ||
179 | |||
180 | return nil | ||
181 | } | ||
182 | |||
183 | func fromCtyNumberUInt(bf *big.Float, target reflect.Value, path cty.Path) error { | ||
184 | // Doing this with switch rather than << arithmetic because << with | ||
185 | // result >32-bits is not portable to 32-bit systems. | ||
186 | var max uint64 | ||
187 | switch target.Type().Bits() { | ||
188 | case 8: | ||
189 | max = math.MaxUint8 | ||
190 | case 16: | ||
191 | max = math.MaxUint16 | ||
192 | case 32: | ||
193 | max = math.MaxUint32 | ||
194 | case 64: | ||
195 | max = math.MaxUint64 | ||
196 | default: | ||
197 | panic("weird number of bits in target uint") | ||
198 | } | ||
199 | |||
200 | iv, accuracy := bf.Uint64() | ||
201 | if accuracy != big.Exact || iv > max { | ||
202 | return path.NewErrorf("value must be a whole number, between 0 and %d inclusive", max) | ||
203 | } | ||
204 | |||
205 | target.Set(reflect.ValueOf(iv).Convert(target.Type())) | ||
206 | |||
207 | return nil | ||
208 | } | ||
209 | |||
210 | func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) error { | ||
211 | switch target.Kind() { | ||
212 | case reflect.Float32: | ||
213 | fv, accuracy := bf.Float32() | ||
214 | if accuracy != big.Exact { | ||
215 | // We allow the precision to be truncated as part of our conversion, | ||
216 | // but we don't want to silently introduce infinities. | ||
217 | if math.IsInf(float64(fv), 0) { | ||
218 | return path.NewErrorf("value must be between %f and %f inclusive", -math.MaxFloat32, math.MaxFloat32) | ||
219 | } | ||
220 | } | ||
221 | target.Set(reflect.ValueOf(fv)) | ||
222 | return nil | ||
223 | case reflect.Float64: | ||
224 | fv, accuracy := bf.Float64() | ||
225 | if accuracy != big.Exact { | ||
226 | // We allow the precision to be truncated as part of our conversion, | ||
227 | // but we don't want to silently introduce infinities. | ||
228 | if math.IsInf(fv, 0) { | ||
229 | return path.NewErrorf("value must be between %f and %f inclusive", -math.MaxFloat64, math.MaxFloat64) | ||
230 | } | ||
231 | } | ||
232 | target.Set(reflect.ValueOf(fv)) | ||
233 | return nil | ||
234 | default: | ||
235 | panic("unsupported kind of float") | ||
236 | } | ||
237 | } | ||
238 | |||
239 | func fromCtyNumberBig(bf *big.Float, target reflect.Value, path cty.Path) error { | ||
240 | switch { | ||
241 | |||
242 | case bigFloatType.AssignableTo(target.Type()): | ||
243 | // Easy! | ||
244 | target.Set(reflect.ValueOf(bf).Elem()) | ||
245 | return nil | ||
246 | |||
247 | case bigIntType.AssignableTo(target.Type()): | ||
248 | bi, accuracy := bf.Int(nil) | ||
249 | if accuracy != big.Exact { | ||
250 | return path.NewErrorf("value must be a whole number") | ||
251 | } | ||
252 | target.Set(reflect.ValueOf(bi).Elem()) | ||
253 | return nil | ||
254 | |||
255 | default: | ||
256 | return likelyRequiredTypesError(path, target) | ||
257 | } | ||
258 | } | ||
259 | |||
260 | func fromCtyString(val cty.Value, target reflect.Value, path cty.Path) error { | ||
261 | switch target.Kind() { | ||
262 | |||
263 | case reflect.String: | ||
264 | target.Set(reflect.ValueOf(val.AsString())) | ||
265 | return nil | ||
266 | |||
267 | default: | ||
268 | return likelyRequiredTypesError(path, target) | ||
269 | |||
270 | } | ||
271 | } | ||
272 | |||
273 | func fromCtyList(val cty.Value, target reflect.Value, path cty.Path) error { | ||
274 | switch target.Kind() { | ||
275 | |||
276 | case reflect.Slice: | ||
277 | if val.IsNull() { | ||
278 | target.Set(reflect.Zero(target.Type())) | ||
279 | return nil | ||
280 | } | ||
281 | |||
282 | length := val.LengthInt() | ||
283 | tv := reflect.MakeSlice(target.Type(), length, length) | ||
284 | |||
285 | path = append(path, nil) | ||
286 | |||
287 | i := 0 | ||
288 | var err error | ||
289 | val.ForEachElement(func(key cty.Value, val cty.Value) bool { | ||
290 | path[len(path)-1] = cty.IndexStep{ | ||
291 | Key: cty.NumberIntVal(int64(i)), | ||
292 | } | ||
293 | |||
294 | targetElem := tv.Index(i) | ||
295 | err = fromCtyValue(val, targetElem, path) | ||
296 | if err != nil { | ||
297 | return true | ||
298 | } | ||
299 | |||
300 | i++ | ||
301 | return false | ||
302 | }) | ||
303 | if err != nil { | ||
304 | return err | ||
305 | } | ||
306 | |||
307 | path = path[:len(path)-1] | ||
308 | |||
309 | target.Set(tv) | ||
310 | return nil | ||
311 | |||
312 | case reflect.Array: | ||
313 | if val.IsNull() { | ||
314 | return path.NewErrorf("null value is not allowed") | ||
315 | } | ||
316 | |||
317 | length := val.LengthInt() | ||
318 | if length != target.Len() { | ||
319 | return path.NewErrorf("must be a list of length %d", target.Len()) | ||
320 | } | ||
321 | |||
322 | path = append(path, nil) | ||
323 | |||
324 | i := 0 | ||
325 | var err error | ||
326 | val.ForEachElement(func(key cty.Value, val cty.Value) bool { | ||
327 | path[len(path)-1] = cty.IndexStep{ | ||
328 | Key: cty.NumberIntVal(int64(i)), | ||
329 | } | ||
330 | |||
331 | targetElem := target.Index(i) | ||
332 | err = fromCtyValue(val, targetElem, path) | ||
333 | if err != nil { | ||
334 | return true | ||
335 | } | ||
336 | |||
337 | i++ | ||
338 | return false | ||
339 | }) | ||
340 | if err != nil { | ||
341 | return err | ||
342 | } | ||
343 | |||
344 | path = path[:len(path)-1] | ||
345 | |||
346 | return nil | ||
347 | |||
348 | default: | ||
349 | return likelyRequiredTypesError(path, target) | ||
350 | |||
351 | } | ||
352 | } | ||
353 | |||
354 | func fromCtyMap(val cty.Value, target reflect.Value, path cty.Path) error { | ||
355 | |||
356 | switch target.Kind() { | ||
357 | |||
358 | case reflect.Map: | ||
359 | if val.IsNull() { | ||
360 | target.Set(reflect.Zero(target.Type())) | ||
361 | return nil | ||
362 | } | ||
363 | |||
364 | tv := reflect.MakeMap(target.Type()) | ||
365 | et := target.Type().Elem() | ||
366 | |||
367 | path = append(path, nil) | ||
368 | |||
369 | var err error | ||
370 | val.ForEachElement(func(key cty.Value, val cty.Value) bool { | ||
371 | path[len(path)-1] = cty.IndexStep{ | ||
372 | Key: key, | ||
373 | } | ||
374 | |||
375 | ks := key.AsString() | ||
376 | |||
377 | targetElem := reflect.New(et) | ||
378 | err = fromCtyValue(val, targetElem, path) | ||
379 | |||
380 | tv.SetMapIndex(reflect.ValueOf(ks), targetElem.Elem()) | ||
381 | |||
382 | return err != nil | ||
383 | }) | ||
384 | if err != nil { | ||
385 | return err | ||
386 | } | ||
387 | |||
388 | path = path[:len(path)-1] | ||
389 | |||
390 | target.Set(tv) | ||
391 | return nil | ||
392 | |||
393 | default: | ||
394 | return likelyRequiredTypesError(path, target) | ||
395 | |||
396 | } | ||
397 | } | ||
398 | |||
399 | func fromCtySet(val cty.Value, target reflect.Value, path cty.Path) error { | ||
400 | switch target.Kind() { | ||
401 | |||
402 | case reflect.Slice: | ||
403 | if val.IsNull() { | ||
404 | target.Set(reflect.Zero(target.Type())) | ||
405 | return nil | ||
406 | } | ||
407 | |||
408 | length := val.LengthInt() | ||
409 | tv := reflect.MakeSlice(target.Type(), length, length) | ||
410 | |||
411 | i := 0 | ||
412 | var err error | ||
413 | val.ForEachElement(func(key cty.Value, val cty.Value) bool { | ||
414 | targetElem := tv.Index(i) | ||
415 | err = fromCtyValue(val, targetElem, path) | ||
416 | if err != nil { | ||
417 | return true | ||
418 | } | ||
419 | |||
420 | i++ | ||
421 | return false | ||
422 | }) | ||
423 | if err != nil { | ||
424 | return err | ||
425 | } | ||
426 | |||
427 | target.Set(tv) | ||
428 | return nil | ||
429 | |||
430 | case reflect.Array: | ||
431 | if val.IsNull() { | ||
432 | return path.NewErrorf("null value is not allowed") | ||
433 | } | ||
434 | |||
435 | length := val.LengthInt() | ||
436 | if length != target.Len() { | ||
437 | return path.NewErrorf("must be a set of length %d", target.Len()) | ||
438 | } | ||
439 | |||
440 | i := 0 | ||
441 | var err error | ||
442 | val.ForEachElement(func(key cty.Value, val cty.Value) bool { | ||
443 | targetElem := target.Index(i) | ||
444 | err = fromCtyValue(val, targetElem, path) | ||
445 | if err != nil { | ||
446 | return true | ||
447 | } | ||
448 | |||
449 | i++ | ||
450 | return false | ||
451 | }) | ||
452 | if err != nil { | ||
453 | return err | ||
454 | } | ||
455 | |||
456 | return nil | ||
457 | |||
458 | // TODO: decode into set.Set instance | ||
459 | |||
460 | default: | ||
461 | return likelyRequiredTypesError(path, target) | ||
462 | |||
463 | } | ||
464 | } | ||
465 | |||
466 | func fromCtyObject(val cty.Value, target reflect.Value, path cty.Path) error { | ||
467 | |||
468 | switch target.Kind() { | ||
469 | |||
470 | case reflect.Struct: | ||
471 | |||
472 | attrTypes := val.Type().AttributeTypes() | ||
473 | targetFields := structTagIndices(target.Type()) | ||
474 | |||
475 | path = append(path, nil) | ||
476 | |||
477 | for k, i := range targetFields { | ||
478 | if _, exists := attrTypes[k]; !exists { | ||
479 | // If the field in question isn't able to represent nil, | ||
480 | // that's an error. | ||
481 | fk := target.Field(i).Kind() | ||
482 | switch fk { | ||
483 | case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface: | ||
484 | // okay | ||
485 | default: | ||
486 | return path.NewErrorf("missing required attribute %q", k) | ||
487 | } | ||
488 | } | ||
489 | } | ||
490 | |||
491 | for k := range attrTypes { | ||
492 | path[len(path)-1] = cty.GetAttrStep{ | ||
493 | Name: k, | ||
494 | } | ||
495 | |||
496 | fieldIdx, exists := targetFields[k] | ||
497 | if !exists { | ||
498 | return path.NewErrorf("unsupported attribute %q", k) | ||
499 | } | ||
500 | |||
501 | ev := val.GetAttr(k) | ||
502 | |||
503 | targetField := target.Field(fieldIdx) | ||
504 | err := fromCtyValue(ev, targetField, path) | ||
505 | if err != nil { | ||
506 | return err | ||
507 | } | ||
508 | } | ||
509 | |||
510 | path = path[:len(path)-1] | ||
511 | |||
512 | return nil | ||
513 | |||
514 | default: | ||
515 | return likelyRequiredTypesError(path, target) | ||
516 | |||
517 | } | ||
518 | } | ||
519 | |||
520 | func fromCtyTuple(val cty.Value, target reflect.Value, path cty.Path) error { | ||
521 | |||
522 | switch target.Kind() { | ||
523 | |||
524 | case reflect.Struct: | ||
525 | |||
526 | elemTypes := val.Type().TupleElementTypes() | ||
527 | fieldCount := target.Type().NumField() | ||
528 | |||
529 | if fieldCount != len(elemTypes) { | ||
530 | return path.NewErrorf("a tuple of %d elements is required", fieldCount) | ||
531 | } | ||
532 | |||
533 | path = append(path, nil) | ||
534 | |||
535 | for i := range elemTypes { | ||
536 | path[len(path)-1] = cty.IndexStep{ | ||
537 | Key: cty.NumberIntVal(int64(i)), | ||
538 | } | ||
539 | |||
540 | ev := val.Index(cty.NumberIntVal(int64(i))) | ||
541 | |||
542 | targetField := target.Field(i) | ||
543 | err := fromCtyValue(ev, targetField, path) | ||
544 | if err != nil { | ||
545 | return err | ||
546 | } | ||
547 | } | ||
548 | |||
549 | path = path[:len(path)-1] | ||
550 | |||
551 | return nil | ||
552 | |||
553 | default: | ||
554 | return likelyRequiredTypesError(path, target) | ||
555 | |||
556 | } | ||
557 | } | ||
558 | |||
559 | func fromCtyCapsule(val cty.Value, target reflect.Value, path cty.Path) error { | ||
560 | |||
561 | if target.Kind() == reflect.Ptr { | ||
562 | // Walk through indirection until we get to the last pointer, | ||
563 | // which we might set to null below. | ||
564 | target = fromCtyPopulatePtr(target, true) | ||
565 | |||
566 | if val.IsNull() { | ||
567 | target.Set(reflect.Zero(target.Type())) | ||
568 | return nil | ||
569 | } | ||
570 | |||
571 | // Since a capsule contains a pointer to an object, we'll preserve | ||
572 | // that pointer on the way out and thus allow the caller to recover | ||
573 | // the original object, rather than a copy of it. | ||
574 | |||
575 | eType := val.Type().EncapsulatedType() | ||
576 | |||
577 | if !eType.AssignableTo(target.Elem().Type()) { | ||
578 | // Our interface contract promises that we won't expose Go | ||
579 | // implementation details in error messages, so we need to keep | ||
580 | // this vague. This can only arise if a calling application has | ||
581 | // more than one capsule type in play and a user mixes them up. | ||
582 | return path.NewErrorf("incorrect type %s", val.Type().FriendlyName()) | ||
583 | } | ||
584 | |||
585 | target.Set(reflect.ValueOf(val.EncapsulatedValue())) | ||
586 | |||
587 | return nil | ||
588 | } else { | ||
589 | if val.IsNull() { | ||
590 | return path.NewErrorf("null value is not allowed") | ||
591 | } | ||
592 | |||
593 | // If our target isn't a pointer then we will attempt to copy | ||
594 | // the encapsulated value into it. | ||
595 | |||
596 | eType := val.Type().EncapsulatedType() | ||
597 | |||
598 | if !eType.AssignableTo(target.Type()) { | ||
599 | // Our interface contract promises that we won't expose Go | ||
600 | // implementation details in error messages, so we need to keep | ||
601 | // this vague. This can only arise if a calling application has | ||
602 | // more than one capsule type in play and a user mixes them up. | ||
603 | return path.NewErrorf("incorrect type %s", val.Type().FriendlyName()) | ||
604 | } | ||
605 | |||
606 | // We know that EncapsulatedValue is always a pointer, so we | ||
607 | // can safely call .Elem on its reflect.Value. | ||
608 | target.Set(reflect.ValueOf(val.EncapsulatedValue()).Elem()) | ||
609 | |||
610 | return nil | ||
611 | } | ||
612 | |||
613 | } | ||
614 | |||
615 | // fromCtyPopulatePtr recognizes when target is a pointer type and allocates | ||
616 | // a value to assign to that pointer, which it returns. | ||
617 | // | ||
618 | // If the given value has multiple levels of indirection, like **int, these | ||
619 | // will be processed in turn so that the return value is guaranteed to be | ||
620 | // a non-pointer. | ||
621 | // | ||
622 | // As an exception, if decodingNull is true then the returned value will be | ||
623 | // the final level of pointer, if any, so that the caller can assign it | ||
624 | // as nil to represent a null value. If the given target value is not a pointer | ||
625 | // at all then the returned value will be just the given target, so the caller | ||
626 | // must test if the returned value is a pointer before trying to assign nil | ||
627 | // to it. | ||
628 | func fromCtyPopulatePtr(target reflect.Value, decodingNull bool) reflect.Value { | ||
629 | for { | ||
630 | if target.Kind() == reflect.Interface && !target.IsNil() { | ||
631 | e := target.Elem() | ||
632 | if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { | ||
633 | target = e | ||
634 | } | ||
635 | } | ||
636 | |||
637 | if target.Kind() != reflect.Ptr { | ||
638 | break | ||
639 | } | ||
640 | |||
641 | // Stop early if we're decodingNull and we've found our last indirection | ||
642 | if target.Elem().Kind() != reflect.Ptr && decodingNull && target.CanSet() { | ||
643 | break | ||
644 | } | ||
645 | |||
646 | if target.IsNil() { | ||
647 | target.Set(reflect.New(target.Type().Elem())) | ||
648 | } | ||
649 | |||
650 | target = target.Elem() | ||
651 | } | ||
652 | return target | ||
653 | } | ||
654 | |||
655 | // likelyRequiredTypesError returns an error that states which types are | ||
656 | // acceptable by making some assumptions about what types we support for | ||
657 | // each target Go kind. It's not a precise science but it allows us to return | ||
658 | // an error message that is cty-user-oriented rather than Go-oriented. | ||
659 | // | ||
660 | // Generally these error messages should be a matter of last resort, since | ||
661 | // the calling application should be validating user-provided value types | ||
662 | // before decoding anyway. | ||
663 | func likelyRequiredTypesError(path cty.Path, target reflect.Value) error { | ||
664 | switch target.Kind() { | ||
665 | |||
666 | case reflect.Bool: | ||
667 | return path.NewErrorf("bool value is required") | ||
668 | |||
669 | case reflect.String: | ||
670 | return path.NewErrorf("string value is required") | ||
671 | |||
672 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
673 | fallthrough | ||
674 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
675 | fallthrough | ||
676 | case reflect.Float32, reflect.Float64: | ||
677 | return path.NewErrorf("number value is required") | ||
678 | |||
679 | case reflect.Slice, reflect.Array: | ||
680 | return path.NewErrorf("list or set value is required") | ||
681 | |||
682 | case reflect.Map: | ||
683 | return path.NewErrorf("map or object value is required") | ||
684 | |||
685 | case reflect.Struct: | ||
686 | switch { | ||
687 | |||
688 | case target.Type().AssignableTo(bigFloatType) || target.Type().AssignableTo(bigIntType): | ||
689 | return path.NewErrorf("number value is required") | ||
690 | |||
691 | case target.Type().AssignableTo(setType): | ||
692 | return path.NewErrorf("set or list value is required") | ||
693 | |||
694 | default: | ||
695 | return path.NewErrorf("object or tuple value is required") | ||
696 | |||
697 | } | ||
698 | |||
699 | default: | ||
700 | // We should avoid getting into this path, since this error | ||
701 | // message is rather useless. | ||
702 | return path.NewErrorf("incorrect type") | ||
703 | |||
704 | } | ||
705 | } | ||
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go b/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go new file mode 100644 index 0000000..ce4c8f1 --- /dev/null +++ b/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go | |||
@@ -0,0 +1,108 @@ | |||
1 | package gocty | ||
2 | |||
3 | import ( | ||
4 | "reflect" | ||
5 | |||
6 | "github.com/zclconf/go-cty/cty" | ||
7 | ) | ||
8 | |||
9 | // ImpliedType takes an arbitrary Go value (as an interface{}) and attempts | ||
10 | // to find a suitable cty.Type instance that could be used for a conversion | ||
11 | // with ToCtyValue. | ||
12 | // | ||
13 | // This allows -- for simple situations at least -- types to be defined just | ||
14 | // once in Go and the cty types derived from the Go types, but in the process | ||
15 | // it makes some assumptions that may be undesirable so applications are | ||
16 | // encouraged to build their cty types directly if exacting control is | ||
17 | // required. | ||
18 | // | ||
19 | // Not all Go types can be represented as cty types, so an error may be | ||
20 | // returned which is usually considered to be a bug in the calling program. | ||
21 | // In particular, ImpliedType will never use capsule types in its returned | ||
22 | // type, because it cannot know the capsule types supported by the calling | ||
23 | // program. | ||
24 | func ImpliedType(gv interface{}) (cty.Type, error) { | ||
25 | rt := reflect.TypeOf(gv) | ||
26 | var path cty.Path | ||
27 | return impliedType(rt, path) | ||
28 | } | ||
29 | |||
30 | func impliedType(rt reflect.Type, path cty.Path) (cty.Type, error) { | ||
31 | switch rt.Kind() { | ||
32 | |||
33 | case reflect.Ptr: | ||
34 | return impliedType(rt.Elem(), path) | ||
35 | |||
36 | // Primitive types | ||
37 | case reflect.Bool: | ||
38 | return cty.Bool, nil | ||
39 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
40 | return cty.Number, nil | ||
41 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
42 | return cty.Number, nil | ||
43 | case reflect.Float32, reflect.Float64: | ||
44 | return cty.Number, nil | ||
45 | case reflect.String: | ||
46 | return cty.String, nil | ||
47 | |||
48 | // Collection types | ||
49 | case reflect.Slice: | ||
50 | path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.Number)}) | ||
51 | ety, err := impliedType(rt.Elem(), path) | ||
52 | if err != nil { | ||
53 | return cty.NilType, err | ||
54 | } | ||
55 | return cty.List(ety), nil | ||
56 | case reflect.Map: | ||
57 | if !stringType.AssignableTo(rt.Key()) { | ||
58 | return cty.NilType, path.NewErrorf("no cty.Type for %s (must have string keys)", rt) | ||
59 | } | ||
60 | path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.String)}) | ||
61 | ety, err := impliedType(rt.Elem(), path) | ||
62 | if err != nil { | ||
63 | return cty.NilType, err | ||
64 | } | ||
65 | return cty.Map(ety), nil | ||
66 | |||
67 | // Structural types | ||
68 | case reflect.Struct: | ||
69 | return impliedStructType(rt, path) | ||
70 | |||
71 | default: | ||
72 | return cty.NilType, path.NewErrorf("no cty.Type for %s", rt) | ||
73 | } | ||
74 | } | ||
75 | |||
76 | func impliedStructType(rt reflect.Type, path cty.Path) (cty.Type, error) { | ||
77 | if valueType.AssignableTo(rt) { | ||
78 | // Special case: cty.Value represents cty.DynamicPseudoType, for | ||
79 | // type conformance checking. | ||
80 | return cty.DynamicPseudoType, nil | ||
81 | } | ||
82 | |||
83 | fieldIdxs := structTagIndices(rt) | ||
84 | if len(fieldIdxs) == 0 { | ||
85 | return cty.NilType, path.NewErrorf("no cty.Type for %s (no cty field tags)", rt) | ||
86 | } | ||
87 | |||
88 | atys := make(map[string]cty.Type, len(fieldIdxs)) | ||
89 | |||
90 | { | ||
91 | // Temporary extension of path for attributes | ||
92 | path := append(path, nil) | ||
93 | |||
94 | for k, fi := range fieldIdxs { | ||
95 | path[len(path)-1] = cty.GetAttrStep{Name: k} | ||
96 | |||
97 | ft := rt.Field(fi).Type | ||
98 | aty, err := impliedType(ft, path) | ||
99 | if err != nil { | ||
100 | return cty.NilType, err | ||
101 | } | ||
102 | |||
103 | atys[k] = aty | ||
104 | } | ||
105 | } | ||
106 | |||
107 | return cty.Object(atys), nil | ||
108 | } | ||