aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/helper.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/helper.go')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/helper.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/helper.go b/vendor/github.com/zclconf/go-cty/cty/helper.go
new file mode 100644
index 0000000..1b88e9f
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/helper.go
@@ -0,0 +1,99 @@
1package cty
2
3import (
4 "fmt"
5)
6
7// anyUnknown is a helper to easily check if a set of values contains any
8// unknowns, for operations that short-circuit to return unknown in that case.
9func anyUnknown(values ...Value) bool {
10 for _, val := range values {
11 if val.v == unknown {
12 return true
13 }
14 }
15 return false
16}
17
18// typeCheck tests whether all of the given values belong to the given type.
19// If the given types are a mixture of the given type and the dynamic
20// pseudo-type then a short-circuit dynamic value is returned. If the given
21// values are all of the correct type but at least one is unknown then
22// a short-circuit unknown value is returned. If any other types appear then
23// an error is returned. Otherwise (finally!) the result is nil, nil.
24func typeCheck(required Type, ret Type, values ...Value) (shortCircuit *Value, err error) {
25 hasDynamic := false
26 hasUnknown := false
27
28 for i, val := range values {
29 if val.ty == DynamicPseudoType {
30 hasDynamic = true
31 continue
32 }
33
34 if !val.Type().Equals(required) {
35 return nil, fmt.Errorf(
36 "type mismatch: want %s but value %d is %s",
37 required.FriendlyName(),
38 i, val.ty.FriendlyName(),
39 )
40 }
41
42 if val.v == unknown {
43 hasUnknown = true
44 }
45 }
46
47 if hasDynamic {
48 return &DynamicVal, nil
49 }
50
51 if hasUnknown {
52 ret := UnknownVal(ret)
53 return &ret, nil
54 }
55
56 return nil, nil
57}
58
59// mustTypeCheck is a wrapper around typeCheck that immediately panics if
60// any error is returned.
61func mustTypeCheck(required Type, ret Type, values ...Value) *Value {
62 shortCircuit, err := typeCheck(required, ret, values...)
63 if err != nil {
64 panic(err)
65 }
66 return shortCircuit
67}
68
69// shortCircuitForceType takes the return value from mustTypeCheck and
70// replaces it with an unknown of the given type if the original value was
71// DynamicVal.
72//
73// This is useful for operations that are specified to always return a
74// particular type, since then a dynamic result can safely be "upgrade" to
75// a strongly-typed unknown, which then allows subsequent operations to
76// be actually type-checked.
77//
78// It is safe to use this only if the operation in question is defined as
79// returning either a value of the given type or panicking, since we know
80// then that subsequent operations won't run if the operation panics.
81//
82// If the given short-circuit value is *not* DynamicVal then it must be
83// of the given type, or this function will panic.
84func forceShortCircuitType(shortCircuit *Value, ty Type) *Value {
85 if shortCircuit == nil {
86 return nil
87 }
88
89 if shortCircuit.ty == DynamicPseudoType {
90 ret := UnknownVal(ty)
91 return &ret
92 }
93
94 if !shortCircuit.ty.Equals(ty) {
95 panic("forceShortCircuitType got value of wrong type")
96 }
97
98 return shortCircuit
99}