diff options
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/value_ops.go')
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/value_ops.go | 117 |
1 files changed, 92 insertions, 25 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/value_ops.go b/vendor/github.com/zclconf/go-cty/cty/value_ops.go index 967aa76..afd621c 100644 --- a/vendor/github.com/zclconf/go-cty/cty/value_ops.go +++ b/vendor/github.com/zclconf/go-cty/cty/value_ops.go | |||
@@ -3,27 +3,27 @@ package cty | |||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "math/big" | 5 | "math/big" |
6 | |||
7 | "reflect" | 6 | "reflect" |
8 | 7 | ||
9 | "github.com/zclconf/go-cty/cty/set" | 8 | "github.com/zclconf/go-cty/cty/set" |
10 | ) | 9 | ) |
11 | 10 | ||
11 | // GoString is an implementation of fmt.GoStringer that produces concise | ||
12 | // source-like representations of values suitable for use in debug messages. | ||
12 | func (val Value) GoString() string { | 13 | func (val Value) GoString() string { |
13 | if val == NilVal { | 14 | if val == NilVal { |
14 | return "cty.NilVal" | 15 | return "cty.NilVal" |
15 | } | 16 | } |
16 | 17 | ||
17 | if val.ty == DynamicPseudoType { | 18 | if val.IsNull() { |
19 | return fmt.Sprintf("cty.NullVal(%#v)", val.ty) | ||
20 | } | ||
21 | if val == DynamicVal { // is unknown, so must be before the IsKnown check below | ||
18 | return "cty.DynamicVal" | 22 | return "cty.DynamicVal" |
19 | } | 23 | } |
20 | |||
21 | if !val.IsKnown() { | 24 | if !val.IsKnown() { |
22 | return fmt.Sprintf("cty.UnknownVal(%#v)", val.ty) | 25 | return fmt.Sprintf("cty.UnknownVal(%#v)", val.ty) |
23 | } | 26 | } |
24 | if val.IsNull() { | ||
25 | return fmt.Sprintf("cty.NullVal(%#v)", val.ty) | ||
26 | } | ||
27 | 27 | ||
28 | // By the time we reach here we've dealt with all of the exceptions around | 28 | // By the time we reach here we've dealt with all of the exceptions around |
29 | // unknowns and nulls, so we're guaranteed that the values are the | 29 | // unknowns and nulls, so we're guaranteed that the values are the |
@@ -33,9 +33,8 @@ func (val Value) GoString() string { | |||
33 | case Bool: | 33 | case Bool: |
34 | if val.v.(bool) { | 34 | if val.v.(bool) { |
35 | return "cty.True" | 35 | return "cty.True" |
36 | } else { | ||
37 | return "cty.False" | ||
38 | } | 36 | } |
37 | return "cty.False" | ||
39 | case Number: | 38 | case Number: |
40 | fv := val.v.(*big.Float) | 39 | fv := val.v.(*big.Float) |
41 | // We'll try to use NumberIntVal or NumberFloatVal if we can, since | 40 | // We'll try to use NumberIntVal or NumberFloatVal if we can, since |
@@ -46,19 +45,42 @@ func (val Value) GoString() string { | |||
46 | if rfv, accuracy := fv.Float64(); accuracy == big.Exact { | 45 | if rfv, accuracy := fv.Float64(); accuracy == big.Exact { |
47 | return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv) | 46 | return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv) |
48 | } | 47 | } |
49 | return fmt.Sprintf("cty.NumberVal(new(big.Float).Parse(\"%#v\", 10))", fv) | 48 | return fmt.Sprintf("cty.MustParseNumberVal(%q)", fv.Text('f', -1)) |
50 | case String: | 49 | case String: |
51 | return fmt.Sprintf("cty.StringVal(%#v)", val.v) | 50 | return fmt.Sprintf("cty.StringVal(%#v)", val.v) |
52 | } | 51 | } |
53 | 52 | ||
54 | switch { | 53 | switch { |
55 | case val.ty.IsSetType(): | 54 | case val.ty.IsSetType(): |
56 | vals := val.v.(set.Set).Values() | 55 | vals := val.AsValueSlice() |
57 | if vals == nil || len(vals) == 0 { | 56 | if len(vals) == 0 { |
58 | return fmt.Sprintf("cty.SetValEmpty()") | 57 | return fmt.Sprintf("cty.SetValEmpty(%#v)", val.ty.ElementType()) |
59 | } else { | ||
60 | return fmt.Sprintf("cty.SetVal(%#v)", vals) | ||
61 | } | 58 | } |
59 | return fmt.Sprintf("cty.SetVal(%#v)", vals) | ||
60 | case val.ty.IsListType(): | ||
61 | vals := val.AsValueSlice() | ||
62 | if len(vals) == 0 { | ||
63 | return fmt.Sprintf("cty.ListValEmpty(%#v)", val.ty.ElementType()) | ||
64 | } | ||
65 | return fmt.Sprintf("cty.ListVal(%#v)", vals) | ||
66 | case val.ty.IsMapType(): | ||
67 | vals := val.AsValueMap() | ||
68 | if len(vals) == 0 { | ||
69 | return fmt.Sprintf("cty.MapValEmpty(%#v)", val.ty.ElementType()) | ||
70 | } | ||
71 | return fmt.Sprintf("cty.MapVal(%#v)", vals) | ||
72 | case val.ty.IsTupleType(): | ||
73 | if val.ty.Equals(EmptyTuple) { | ||
74 | return "cty.EmptyTupleVal" | ||
75 | } | ||
76 | vals := val.AsValueSlice() | ||
77 | return fmt.Sprintf("cty.TupleVal(%#v)", vals) | ||
78 | case val.ty.IsObjectType(): | ||
79 | if val.ty.Equals(EmptyObject) { | ||
80 | return "cty.EmptyObjectVal" | ||
81 | } | ||
82 | vals := val.AsValueMap() | ||
83 | return fmt.Sprintf("cty.ObjectVal(%#v)", vals) | ||
62 | case val.ty.IsCapsuleType(): | 84 | case val.ty.IsCapsuleType(): |
63 | return fmt.Sprintf("cty.CapsuleVal(%#v, %#v)", val.ty, val.v) | 85 | return fmt.Sprintf("cty.CapsuleVal(%#v, %#v)", val.ty, val.v) |
64 | } | 86 | } |
@@ -71,26 +93,67 @@ func (val Value) GoString() string { | |||
71 | // Equals returns True if the receiver and the given other value have the | 93 | // Equals returns True if the receiver and the given other value have the |
72 | // same type and are exactly equal in value. | 94 | // same type and are exactly equal in value. |
73 | // | 95 | // |
74 | // The usual short-circuit rules apply, so the result can be unknown or typed | 96 | // As a special case, two null values are always equal regardless of type. |
75 | // as dynamic if either of the given values are. Use RawEquals to compare | 97 | // |
76 | // if two values are equal *ignoring* the short-circuit rules. | 98 | // The usual short-circuit rules apply, so the result will be unknown if |
99 | // either of the given values are. | ||
100 | // | ||
101 | // Use RawEquals to compare if two values are equal *ignoring* the | ||
102 | // short-circuit rules and the exception for null values. | ||
77 | func (val Value) Equals(other Value) Value { | 103 | func (val Value) Equals(other Value) Value { |
78 | if val.ty.HasDynamicTypes() || other.ty.HasDynamicTypes() { | 104 | // Start by handling Unknown values before considering types. |
105 | // This needs to be done since Null values are always equal regardless of | ||
106 | // type. | ||
107 | switch { | ||
108 | case !val.IsKnown() && !other.IsKnown(): | ||
109 | // both unknown | ||
79 | return UnknownVal(Bool) | 110 | return UnknownVal(Bool) |
111 | case val.IsKnown() && !other.IsKnown(): | ||
112 | switch { | ||
113 | case val.IsNull(), other.ty.HasDynamicTypes(): | ||
114 | // If known is Null, we need to wait for the unkown value since | ||
115 | // nulls of any type are equal. | ||
116 | // An unkown with a dynamic type compares as unknown, which we need | ||
117 | // to check before the type comparison below. | ||
118 | return UnknownVal(Bool) | ||
119 | case !val.ty.Equals(other.ty): | ||
120 | // There is no null comparison or dynamic types, so unequal types | ||
121 | // will never be equal. | ||
122 | return False | ||
123 | default: | ||
124 | return UnknownVal(Bool) | ||
125 | } | ||
126 | case other.IsKnown() && !val.IsKnown(): | ||
127 | switch { | ||
128 | case other.IsNull(), val.ty.HasDynamicTypes(): | ||
129 | // If known is Null, we need to wait for the unkown value since | ||
130 | // nulls of any type are equal. | ||
131 | // An unkown with a dynamic type compares as unknown, which we need | ||
132 | // to check before the type comparison below. | ||
133 | return UnknownVal(Bool) | ||
134 | case !other.ty.Equals(val.ty): | ||
135 | // There's no null comparison or dynamic types, so unequal types | ||
136 | // will never be equal. | ||
137 | return False | ||
138 | default: | ||
139 | return UnknownVal(Bool) | ||
140 | } | ||
80 | } | 141 | } |
81 | 142 | ||
82 | if !val.ty.Equals(other.ty) { | 143 | switch { |
144 | case val.IsNull() && other.IsNull(): | ||
145 | // Nulls are always equal, regardless of type | ||
146 | return BoolVal(true) | ||
147 | case val.IsNull() || other.IsNull(): | ||
148 | // If only one is null then the result must be false | ||
83 | return BoolVal(false) | 149 | return BoolVal(false) |
84 | } | 150 | } |
85 | 151 | ||
86 | if !(val.IsKnown() && other.IsKnown()) { | 152 | if val.ty.HasDynamicTypes() || other.ty.HasDynamicTypes() { |
87 | return UnknownVal(Bool) | 153 | return UnknownVal(Bool) |
88 | } | 154 | } |
89 | 155 | ||
90 | if val.IsNull() || other.IsNull() { | 156 | if !val.ty.Equals(other.ty) { |
91 | if val.IsNull() && other.IsNull() { | ||
92 | return BoolVal(true) | ||
93 | } | ||
94 | return BoolVal(false) | 157 | return BoolVal(false) |
95 | } | 158 | } |
96 | 159 | ||
@@ -758,7 +821,7 @@ func (val Value) HasElement(elem Value) Value { | |||
758 | if val.IsNull() { | 821 | if val.IsNull() { |
759 | panic("can't call HasElement on a nil value") | 822 | panic("can't call HasElement on a nil value") |
760 | } | 823 | } |
761 | if ty.ElementType() != elem.Type() { | 824 | if !ty.ElementType().Equals(elem.Type()) { |
762 | return False | 825 | return False |
763 | } | 826 | } |
764 | 827 | ||
@@ -800,6 +863,10 @@ func (val Value) LengthInt() int { | |||
800 | // For tuples, we can return the length even if the value is not known. | 863 | // For tuples, we can return the length even if the value is not known. |
801 | return val.Type().Length() | 864 | return val.Type().Length() |
802 | } | 865 | } |
866 | if val.Type().IsObjectType() { | ||
867 | // For objects, the length is the number of attributes associated with the type. | ||
868 | return len(val.Type().AttributeTypes()) | ||
869 | } | ||
803 | if !val.IsKnown() { | 870 | if !val.IsKnown() { |
804 | panic("value is not known") | 871 | panic("value is not known") |
805 | } | 872 | } |