aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/value_ops.go
diff options
context:
space:
mode:
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.go117
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
3import ( 3import (
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.
12func (val Value) GoString() string { 13func (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.
77func (val Value) Equals(other Value) Value { 103func (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 }