aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/gocty
diff options
context:
space:
mode:
authorAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
committerAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
commit15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch)
tree255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/zclconf/go-cty/cty/gocty
parent07971ca38143c5faf951d152fba370ddcbe26ad5 (diff)
downloadterraform-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.go7
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go43
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/in.go528
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/out.go705
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go108
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.
7package 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 @@
1package gocty
2
3import (
4 "math/big"
5 "reflect"
6
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/set"
9)
10
11var valueType = reflect.TypeOf(cty.Value{})
12var typeType = reflect.TypeOf(cty.Type{})
13
14var setType = reflect.TypeOf(set.Set{})
15
16var bigFloatType = reflect.TypeOf(big.Float{})
17var bigIntType = reflect.TypeOf(big.Int{})
18
19var emptyInterfaceType = reflect.TypeOf(interface{}(nil))
20
21var 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.
30func 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 @@
1package gocty
2
3import (
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.
25func 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
34func 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
66func 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
83func 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
119func 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
136func 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
181func 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
231func 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
289func 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
383func 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
467func 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
487func 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.
518func 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 @@
1package gocty
2
3import (
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.
30func 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
47func 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
111func 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
128func 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
151func 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
183func 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
210func 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
239func 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
260func 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
273func 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
354func 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
399func 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
466func 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
520func 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
559func 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.
628func 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.
663func 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 @@
1package gocty
2
3import (
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.
24func ImpliedType(gv interface{}) (cty.Type, error) {
25 rt := reflect.TypeOf(gv)
26 var path cty.Path
27 return impliedType(rt, path)
28}
29
30func 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
76func 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}