diff options
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/helper.go')
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/helper.go | 99 |
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 @@ | |||
1 | package cty | ||
2 | |||
3 | import ( | ||
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. | ||
9 | func 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. | ||
24 | func 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. | ||
61 | func 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. | ||
84 | func 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 | } | ||