aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty
diff options
context:
space:
mode:
authorNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
committerNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
commit107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch)
treeca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/zclconf/go-cty/cty
parent844b5a68d8af4791755b8f0ad293cc99f5959183 (diff)
downloadterraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/capsule.go2
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion.go23
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go114
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go76
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go6
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_tuple.go71
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/mismatch_msg.go220
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/public.go4
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/unify.go254
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/function.go4
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go385
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go5
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go74
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl18
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go233
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go88
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gob.go4
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/in.go20
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/out.go41
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/type_implied.go7
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go2
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/list_type.go10
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/map_type.go10
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/msgpack/doc.go14
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/msgpack/dynamic.go31
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/msgpack/infinity.go8
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/msgpack/marshal.go207
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/msgpack/type_implied.go167
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/msgpack/unknown.go16
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/msgpack/unmarshal.go334
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/object_type.go2
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/path.go24
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/path_set.go198
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/primitive_type.go2
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/iterator.go31
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/ops.go51
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/rules.go18
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set_internals.go76
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set_type.go10
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/tuple_type.go2
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/type.go29
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/type_conform.go29
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/unknown.go9
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/unknown_as_null.go64
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/value_init.go38
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/value_ops.go117
46 files changed, 2965 insertions, 183 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/capsule.go b/vendor/github.com/zclconf/go-cty/cty/capsule.go
index 4fce92a..d273d14 100644
--- a/vendor/github.com/zclconf/go-cty/cty/capsule.go
+++ b/vendor/github.com/zclconf/go-cty/cty/capsule.go
@@ -19,7 +19,7 @@ func (t *capsuleType) Equals(other Type) bool {
19 return false 19 return false
20} 20}
21 21
22func (t *capsuleType) FriendlyName() string { 22func (t *capsuleType) FriendlyName(mode friendlyTypeNameMode) string {
23 return t.Name 23 return t.Name
24} 24}
25 25
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
index 7bfcc08..f9aacb4 100644
--- a/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
@@ -17,6 +17,10 @@ func getConversion(in cty.Type, out cty.Type, unsafe bool) conversion {
17 // Wrap the conversion in some standard checks that we don't want to 17 // Wrap the conversion in some standard checks that we don't want to
18 // have to repeat in every conversion function. 18 // have to repeat in every conversion function.
19 return func(in cty.Value, path cty.Path) (cty.Value, error) { 19 return func(in cty.Value, path cty.Path) (cty.Value, error) {
20 if out == cty.DynamicPseudoType {
21 // Conversion to DynamicPseudoType always just passes through verbatim.
22 return in, nil
23 }
20 if !in.IsKnown() { 24 if !in.IsKnown() {
21 return cty.UnknownVal(out), nil 25 return cty.UnknownVal(out), nil
22 } 26 }
@@ -57,6 +61,12 @@ func getConversionKnown(in cty.Type, out cty.Type, unsafe bool) conversion {
57 } 61 }
58 return nil 62 return nil
59 63
64 case out.IsObjectType() && in.IsObjectType():
65 return conversionObjectToObject(in, out, unsafe)
66
67 case out.IsTupleType() && in.IsTupleType():
68 return conversionTupleToTuple(in, out, unsafe)
69
60 case out.IsListType() && (in.IsListType() || in.IsSetType()): 70 case out.IsListType() && (in.IsListType() || in.IsSetType()):
61 inEty := in.ElementType() 71 inEty := in.ElementType()
62 outEty := out.ElementType() 72 outEty := out.ElementType()
@@ -93,10 +103,23 @@ func getConversionKnown(in cty.Type, out cty.Type, unsafe bool) conversion {
93 } 103 }
94 return conversionCollectionToSet(outEty, convEty) 104 return conversionCollectionToSet(outEty, convEty)
95 105
106 case out.IsMapType() && in.IsMapType():
107 inEty := in.ElementType()
108 outEty := out.ElementType()
109 convEty := getConversion(inEty, outEty, unsafe)
110 if convEty == nil {
111 return nil
112 }
113 return conversionCollectionToMap(outEty, convEty)
114
96 case out.IsListType() && in.IsTupleType(): 115 case out.IsListType() && in.IsTupleType():
97 outEty := out.ElementType() 116 outEty := out.ElementType()
98 return conversionTupleToList(in, outEty, unsafe) 117 return conversionTupleToList(in, outEty, unsafe)
99 118
119 case out.IsSetType() && in.IsTupleType():
120 outEty := out.ElementType()
121 return conversionTupleToSet(in, outEty, unsafe)
122
100 case out.IsMapType() && in.IsObjectType(): 123 case out.IsMapType() && in.IsObjectType():
101 outEty := out.ElementType() 124 outEty := out.ElementType()
102 return conversionObjectToMap(in, outEty, unsafe) 125 return conversionObjectToMap(in, outEty, unsafe)
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
index eace85d..3039ba2 100644
--- a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
@@ -84,6 +84,120 @@ func conversionCollectionToSet(ety cty.Type, conv conversion) conversion {
84 } 84 }
85} 85}
86 86
87// conversionCollectionToMap returns a conversion that will apply the given
88// conversion to all of the elements of a collection (something that supports
89// ForEachElement and LengthInt) and then returns the result as a map.
90//
91// "conv" can be nil if the elements are expected to already be of the
92// correct type and just need to be re-wrapped into a map.
93func conversionCollectionToMap(ety cty.Type, conv conversion) conversion {
94 return func(val cty.Value, path cty.Path) (cty.Value, error) {
95 elems := make(map[string]cty.Value, 0)
96 path = append(path, nil)
97 it := val.ElementIterator()
98 for it.Next() {
99 key, val := it.Element()
100 var err error
101
102 path[len(path)-1] = cty.IndexStep{
103 Key: key,
104 }
105
106 keyStr, err := Convert(key, cty.String)
107 if err != nil {
108 // Should never happen, because keys can only be numbers or
109 // strings and both can convert to string.
110 return cty.DynamicVal, path.NewErrorf("cannot convert key type %s to string for map", key.Type().FriendlyName())
111 }
112
113 if conv != nil {
114 val, err = conv(val, path)
115 if err != nil {
116 return cty.NilVal, err
117 }
118 }
119
120 elems[keyStr.AsString()] = val
121 }
122
123 if len(elems) == 0 {
124 return cty.MapValEmpty(ety), nil
125 }
126
127 return cty.MapVal(elems), nil
128 }
129}
130
131// conversionTupleToSet returns a conversion that will take a value of the
132// given tuple type and return a set of the given element type.
133//
134// Will panic if the given tupleType isn't actually a tuple type.
135func conversionTupleToSet(tupleType cty.Type, listEty cty.Type, unsafe bool) conversion {
136 tupleEtys := tupleType.TupleElementTypes()
137
138 if len(tupleEtys) == 0 {
139 // Empty tuple short-circuit
140 return func(val cty.Value, path cty.Path) (cty.Value, error) {
141 return cty.SetValEmpty(listEty), nil
142 }
143 }
144
145 if listEty == cty.DynamicPseudoType {
146 // This is a special case where the caller wants us to find
147 // a suitable single type that all elements can convert to, if
148 // possible.
149 listEty, _ = unify(tupleEtys, unsafe)
150 if listEty == cty.NilType {
151 return nil
152 }
153 }
154
155 elemConvs := make([]conversion, len(tupleEtys))
156 for i, tupleEty := range tupleEtys {
157 if tupleEty.Equals(listEty) {
158 // no conversion required
159 continue
160 }
161
162 elemConvs[i] = getConversion(tupleEty, listEty, unsafe)
163 if elemConvs[i] == nil {
164 // If any of our element conversions are impossible, then the our
165 // whole conversion is impossible.
166 return nil
167 }
168 }
169
170 // If we fall out here then a conversion is possible, using the
171 // element conversions in elemConvs
172 return func(val cty.Value, path cty.Path) (cty.Value, error) {
173 elems := make([]cty.Value, 0, len(elemConvs))
174 path = append(path, nil)
175 i := int64(0)
176 it := val.ElementIterator()
177 for it.Next() {
178 _, val := it.Element()
179 var err error
180
181 path[len(path)-1] = cty.IndexStep{
182 Key: cty.NumberIntVal(i),
183 }
184
185 conv := elemConvs[i]
186 if conv != nil {
187 val, err = conv(val, path)
188 if err != nil {
189 return cty.NilVal, err
190 }
191 }
192 elems = append(elems, val)
193
194 i++
195 }
196
197 return cty.SetVal(elems), nil
198 }
199}
200
87// conversionTupleToList returns a conversion that will take a value of the 201// conversionTupleToList returns a conversion that will take a value of the
88// given tuple type and return a list of the given element type. 202// given tuple type and return a list of the given element type.
89// 203//
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go
new file mode 100644
index 0000000..62dabb8
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go
@@ -0,0 +1,76 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// conversionObjectToObject returns a conversion that will make the input
8// object type conform to the output object type, if possible.
9//
10// Conversion is possible only if the output type is a subset of the input
11// type, meaning that each attribute of the output type has a corresponding
12// attribute in the input type where a recursive conversion is available.
13//
14// Shallow object conversions work the same for both safe and unsafe modes,
15// but the safety flag is passed on to recursive conversions and may thus
16// limit the above definition of "subset".
17func conversionObjectToObject(in, out cty.Type, unsafe bool) conversion {
18 inAtys := in.AttributeTypes()
19 outAtys := out.AttributeTypes()
20 attrConvs := make(map[string]conversion)
21
22 for name, outAty := range outAtys {
23 inAty, exists := inAtys[name]
24 if !exists {
25 // No conversion is available, then.
26 return nil
27 }
28
29 if inAty.Equals(outAty) {
30 // No conversion needed, but we'll still record the attribute
31 // in our map for later reference.
32 attrConvs[name] = nil
33 continue
34 }
35
36 attrConvs[name] = getConversion(inAty, outAty, unsafe)
37 if attrConvs[name] == nil {
38 // If a recursive conversion isn't available, then our top-level
39 // configuration is impossible too.
40 return nil
41 }
42 }
43
44 // If we get here then a conversion is possible, using the attribute
45 // conversions given in attrConvs.
46 return func(val cty.Value, path cty.Path) (cty.Value, error) {
47 attrVals := make(map[string]cty.Value, len(attrConvs))
48 path = append(path, nil)
49 pathStep := &path[len(path)-1]
50
51 for it := val.ElementIterator(); it.Next(); {
52 nameVal, val := it.Element()
53 var err error
54
55 name := nameVal.AsString()
56 *pathStep = cty.GetAttrStep{
57 Name: name,
58 }
59
60 conv, exists := attrConvs[name]
61 if !exists {
62 continue
63 }
64 if conv != nil {
65 val, err = conv(val, path)
66 if err != nil {
67 return cty.NilVal, err
68 }
69 }
70
71 attrVals[name] = val
72 }
73
74 return cty.ObjectVal(attrVals), nil
75 }
76}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go
index e563ee3..e0dbf49 100644
--- a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go
@@ -1,8 +1,6 @@
1package convert 1package convert
2 2
3import ( 3import (
4 "math/big"
5
6 "github.com/zclconf/go-cty/cty" 4 "github.com/zclconf/go-cty/cty"
7) 5)
8 6
@@ -30,11 +28,11 @@ var primitiveConversionsSafe = map[cty.Type]map[cty.Type]conversion{
30var primitiveConversionsUnsafe = map[cty.Type]map[cty.Type]conversion{ 28var primitiveConversionsUnsafe = map[cty.Type]map[cty.Type]conversion{
31 cty.String: { 29 cty.String: {
32 cty.Number: func(val cty.Value, path cty.Path) (cty.Value, error) { 30 cty.Number: func(val cty.Value, path cty.Path) (cty.Value, error) {
33 f, _, err := big.ParseFloat(val.AsString(), 10, 512, big.ToNearestEven) 31 v, err := cty.ParseNumberVal(val.AsString())
34 if err != nil { 32 if err != nil {
35 return cty.NilVal, path.NewErrorf("a number is required") 33 return cty.NilVal, path.NewErrorf("a number is required")
36 } 34 }
37 return cty.NumberVal(f), nil 35 return v, nil
38 }, 36 },
39 cty.Bool: func(val cty.Value, path cty.Path) (cty.Value, error) { 37 cty.Bool: func(val cty.Value, path cty.Path) (cty.Value, error) {
40 switch val.AsString() { 38 switch val.AsString() {
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_tuple.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_tuple.go
new file mode 100644
index 0000000..592980a
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_tuple.go
@@ -0,0 +1,71 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// conversionTupleToTuple returns a conversion that will make the input
8// tuple type conform to the output tuple type, if possible.
9//
10// Conversion is possible only if the two tuple types have the same number
11// of elements and the corresponding elements by index can be converted.
12//
13// Shallow tuple conversions work the same for both safe and unsafe modes,
14// but the safety flag is passed on to recursive conversions and may thus
15// limit which element type conversions are possible.
16func conversionTupleToTuple(in, out cty.Type, unsafe bool) conversion {
17 inEtys := in.TupleElementTypes()
18 outEtys := out.TupleElementTypes()
19
20 if len(inEtys) != len(outEtys) {
21 return nil // no conversion is possible
22 }
23
24 elemConvs := make([]conversion, len(inEtys))
25
26 for i, outEty := range outEtys {
27 inEty := inEtys[i]
28
29 if inEty.Equals(outEty) {
30 // No conversion needed, so we can leave this one nil.
31 continue
32 }
33
34 elemConvs[i] = getConversion(inEty, outEty, unsafe)
35 if elemConvs[i] == nil {
36 // If a recursive conversion isn't available, then our top-level
37 // configuration is impossible too.
38 return nil
39 }
40 }
41
42 // If we get here then a conversion is possible, using the element
43 // conversions given in elemConvs.
44 return func(val cty.Value, path cty.Path) (cty.Value, error) {
45 elemVals := make([]cty.Value, len(elemConvs))
46 path = append(path, nil)
47 pathStep := &path[len(path)-1]
48
49 i := 0
50 for it := val.ElementIterator(); it.Next(); i++ {
51 _, val := it.Element()
52 var err error
53
54 *pathStep = cty.IndexStep{
55 Key: cty.NumberIntVal(int64(i)),
56 }
57
58 conv := elemConvs[i]
59 if conv != nil {
60 val, err = conv(val, path)
61 if err != nil {
62 return cty.NilVal, err
63 }
64 }
65
66 elemVals[i] = val
67 }
68
69 return cty.TupleVal(elemVals), nil
70 }
71}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/mismatch_msg.go b/vendor/github.com/zclconf/go-cty/cty/convert/mismatch_msg.go
new file mode 100644
index 0000000..581304e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/mismatch_msg.go
@@ -0,0 +1,220 @@
1package convert
2
3import (
4 "bytes"
5 "fmt"
6 "sort"
7
8 "github.com/zclconf/go-cty/cty"
9)
10
11// MismatchMessage is a helper to return an English-language description of
12// the differences between got and want, phrased as a reason why got does
13// not conform to want.
14//
15// This function does not itself attempt conversion, and so it should generally
16// be used only after a conversion has failed, to report the conversion failure
17// to an English-speaking user. The result will be confusing got is actually
18// conforming to or convertable to want.
19//
20// The shorthand helper function Convert uses this function internally to
21// produce its error messages, so callers of that function do not need to
22// also use MismatchMessage.
23//
24// This function is similar to Type.TestConformance, but it is tailored to
25// describing conversion failures and so the messages it generates relate
26// specifically to the conversion rules implemented in this package.
27func MismatchMessage(got, want cty.Type) string {
28 switch {
29
30 case got.IsObjectType() && want.IsObjectType():
31 // If both types are object types then we may be able to say something
32 // about their respective attributes.
33 return mismatchMessageObjects(got, want)
34
35 case got.IsTupleType() && want.IsListType() && want.ElementType() == cty.DynamicPseudoType:
36 // If conversion from tuple to list failed then it's because we couldn't
37 // find a common type to convert all of the tuple elements to.
38 return "all list elements must have the same type"
39
40 case got.IsTupleType() && want.IsSetType() && want.ElementType() == cty.DynamicPseudoType:
41 // If conversion from tuple to set failed then it's because we couldn't
42 // find a common type to convert all of the tuple elements to.
43 return "all set elements must have the same type"
44
45 case got.IsObjectType() && want.IsMapType() && want.ElementType() == cty.DynamicPseudoType:
46 // If conversion from object to map failed then it's because we couldn't
47 // find a common type to convert all of the object attributes to.
48 return "all map elements must have the same type"
49
50 case (got.IsTupleType() || got.IsObjectType()) && want.IsCollectionType():
51 return mismatchMessageCollectionsFromStructural(got, want)
52
53 case got.IsCollectionType() && want.IsCollectionType():
54 return mismatchMessageCollectionsFromCollections(got, want)
55
56 default:
57 // If we have nothing better to say, we'll just state what was required.
58 return want.FriendlyNameForConstraint() + " required"
59 }
60}
61
62func mismatchMessageObjects(got, want cty.Type) string {
63 // Per our conversion rules, "got" is allowed to be a superset of "want",
64 // and so we'll produce error messages here under that assumption.
65 gotAtys := got.AttributeTypes()
66 wantAtys := want.AttributeTypes()
67
68 // If we find missing attributes then we'll report those in preference,
69 // but if not then we will report a maximum of one non-conforming
70 // attribute, just to keep our messages relatively terse.
71 // We'll also prefer to report a recursive type error from an _unsafe_
72 // conversion over a safe one, because these are subjectively more
73 // "serious".
74 var missingAttrs []string
75 var unsafeMismatchAttr string
76 var safeMismatchAttr string
77
78 for name, wantAty := range wantAtys {
79 gotAty, exists := gotAtys[name]
80 if !exists {
81 missingAttrs = append(missingAttrs, name)
82 continue
83 }
84
85 // We'll now try to convert these attributes in isolation and
86 // see if we have a nested conversion error to report.
87 // We'll try an unsafe conversion first, and then fall back on
88 // safe if unsafe is possible.
89
90 // If we already have an unsafe mismatch attr error then we won't bother
91 // hunting for another one.
92 if unsafeMismatchAttr != "" {
93 continue
94 }
95 if conv := GetConversionUnsafe(gotAty, wantAty); conv == nil {
96 unsafeMismatchAttr = fmt.Sprintf("attribute %q: %s", name, MismatchMessage(gotAty, wantAty))
97 }
98
99 // If we already have a safe mismatch attr error then we won't bother
100 // hunting for another one.
101 if safeMismatchAttr != "" {
102 continue
103 }
104 if conv := GetConversion(gotAty, wantAty); conv == nil {
105 safeMismatchAttr = fmt.Sprintf("attribute %q: %s", name, MismatchMessage(gotAty, wantAty))
106 }
107 }
108
109 // We should now have collected at least one problem. If we have more than
110 // one then we'll use our preference order to decide what is most important
111 // to report.
112 switch {
113
114 case len(missingAttrs) != 0:
115 sort.Strings(missingAttrs)
116 switch len(missingAttrs) {
117 case 1:
118 return fmt.Sprintf("attribute %q is required", missingAttrs[0])
119 case 2:
120 return fmt.Sprintf("attributes %q and %q are required", missingAttrs[0], missingAttrs[1])
121 default:
122 sort.Strings(missingAttrs)
123 var buf bytes.Buffer
124 for _, name := range missingAttrs[:len(missingAttrs)-1] {
125 fmt.Fprintf(&buf, "%q, ", name)
126 }
127 fmt.Fprintf(&buf, "and %q", missingAttrs[len(missingAttrs)-1])
128 return fmt.Sprintf("attributes %s are required", buf.Bytes())
129 }
130
131 case unsafeMismatchAttr != "":
132 return unsafeMismatchAttr
133
134 case safeMismatchAttr != "":
135 return safeMismatchAttr
136
137 default:
138 // We should never get here, but if we do then we'll return
139 // just a generic message.
140 return "incorrect object attributes"
141 }
142}
143
144func mismatchMessageCollectionsFromStructural(got, want cty.Type) string {
145 // First some straightforward cases where the kind is just altogether wrong.
146 switch {
147 case want.IsListType() && !got.IsTupleType():
148 return want.FriendlyNameForConstraint() + " required"
149 case want.IsSetType() && !got.IsTupleType():
150 return want.FriendlyNameForConstraint() + " required"
151 case want.IsMapType() && !got.IsObjectType():
152 return want.FriendlyNameForConstraint() + " required"
153 }
154
155 // If the kinds are matched well enough then we'll move on to checking
156 // individual elements.
157 wantEty := want.ElementType()
158 switch {
159 case got.IsTupleType():
160 for i, gotEty := range got.TupleElementTypes() {
161 if gotEty.Equals(wantEty) {
162 continue // exact match, so no problem
163 }
164 if conv := getConversion(gotEty, wantEty, true); conv != nil {
165 continue // conversion is available, so no problem
166 }
167 return fmt.Sprintf("element %d: %s", i, MismatchMessage(gotEty, wantEty))
168 }
169
170 // If we get down here then something weird is going on but we'll
171 // return a reasonable fallback message anyway.
172 return fmt.Sprintf("all elements must be %s", wantEty.FriendlyNameForConstraint())
173
174 case got.IsObjectType():
175 for name, gotAty := range got.AttributeTypes() {
176 if gotAty.Equals(wantEty) {
177 continue // exact match, so no problem
178 }
179 if conv := getConversion(gotAty, wantEty, true); conv != nil {
180 continue // conversion is available, so no problem
181 }
182 return fmt.Sprintf("element %q: %s", name, MismatchMessage(gotAty, wantEty))
183 }
184
185 // If we get down here then something weird is going on but we'll
186 // return a reasonable fallback message anyway.
187 return fmt.Sprintf("all elements must be %s", wantEty.FriendlyNameForConstraint())
188
189 default:
190 // Should not be possible to get here since we only call this function
191 // with got as structural types, but...
192 return want.FriendlyNameForConstraint() + " required"
193 }
194}
195
196func mismatchMessageCollectionsFromCollections(got, want cty.Type) string {
197 // First some straightforward cases where the kind is just altogether wrong.
198 switch {
199 case want.IsListType() && !(got.IsListType() || got.IsSetType()):
200 return want.FriendlyNameForConstraint() + " required"
201 case want.IsSetType() && !(got.IsListType() || got.IsSetType()):
202 return want.FriendlyNameForConstraint() + " required"
203 case want.IsMapType() && !got.IsMapType():
204 return want.FriendlyNameForConstraint() + " required"
205 }
206
207 // If the kinds are matched well enough then we'll check the element types.
208 gotEty := got.ElementType()
209 wantEty := want.ElementType()
210 noun := "element type"
211 switch {
212 case want.IsListType():
213 noun = "list element type"
214 case want.IsSetType():
215 noun = "set element type"
216 case want.IsMapType():
217 noun = "map element type"
218 }
219 return fmt.Sprintf("incorrect %s: %s", noun, MismatchMessage(gotEty, wantEty))
220}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/public.go b/vendor/github.com/zclconf/go-cty/cty/convert/public.go
index 55f44ae..af19bdc 100644
--- a/vendor/github.com/zclconf/go-cty/cty/convert/public.go
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/public.go
@@ -1,7 +1,7 @@
1package convert 1package convert
2 2
3import ( 3import (
4 "fmt" 4 "errors"
5 5
6 "github.com/zclconf/go-cty/cty" 6 "github.com/zclconf/go-cty/cty"
7) 7)
@@ -46,7 +46,7 @@ func Convert(in cty.Value, want cty.Type) (cty.Value, error) {
46 46
47 conv := GetConversionUnsafe(in.Type(), want) 47 conv := GetConversionUnsafe(in.Type(), want)
48 if conv == nil { 48 if conv == nil {
49 return cty.NilVal, fmt.Errorf("incorrect type; %s required", want.FriendlyName()) 49 return cty.NilVal, errors.New(MismatchMessage(in.Type(), want))
50 } 50 }
51 return conv(in) 51 return conv(in)
52} 52}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/unify.go b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
index bd6736b..53ebbfe 100644
--- a/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
@@ -21,6 +21,39 @@ func unify(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
21 return cty.NilType, nil 21 return cty.NilType, nil
22 } 22 }
23 23
24 // If all of the given types are of the same structural kind, we may be
25 // able to construct a new type that they can all be unified to, even if
26 // that is not one of the given types. We must try this before the general
27 // behavior below because in unsafe mode we can convert an object type to
28 // a subset of that type, which would be a much less useful conversion for
29 // unification purposes.
30 {
31 objectCt := 0
32 tupleCt := 0
33 dynamicCt := 0
34 for _, ty := range types {
35 switch {
36 case ty.IsObjectType():
37 objectCt++
38 case ty.IsTupleType():
39 tupleCt++
40 case ty == cty.DynamicPseudoType:
41 dynamicCt++
42 default:
43 break
44 }
45 }
46 switch {
47 case objectCt > 0 && (objectCt+dynamicCt) == len(types):
48 return unifyObjectTypes(types, unsafe, dynamicCt > 0)
49 case tupleCt > 0 && (tupleCt+dynamicCt) == len(types):
50 return unifyTupleTypes(types, unsafe, dynamicCt > 0)
51 case objectCt > 0 && tupleCt > 0:
52 // Can never unify object and tuple types since they have incompatible kinds
53 return cty.NilType, nil
54 }
55 }
56
24 prefOrder := sortTypes(types) 57 prefOrder := sortTypes(types)
25 58
26 // sortTypes gives us an order where earlier items are preferable as 59 // sortTypes gives us an order where earlier items are preferable as
@@ -58,9 +91,224 @@ Preferences:
58 return wantType, conversions 91 return wantType, conversions
59 } 92 }
60 93
61 // TODO: For structural types, try to invent a new type that they
62 // can all be unified to, by unifying their respective attributes.
63
64 // If we fall out here, no unification is possible 94 // If we fall out here, no unification is possible
65 return cty.NilType, nil 95 return cty.NilType, nil
66} 96}
97
98func unifyObjectTypes(types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []Conversion) {
99 // If we had any dynamic types in the input here then we can't predict
100 // what path we'll take through here once these become known types, so
101 // we'll conservatively produce DynamicVal for these.
102 if hasDynamic {
103 return unifyAllAsDynamic(types)
104 }
105
106 // There are two different ways we can succeed here:
107 // - If all of the given object types have the same set of attribute names
108 // and the corresponding types are all unifyable, then we construct that
109 // type.
110 // - If the given object types have different attribute names or their
111 // corresponding types are not unifyable, we'll instead try to unify
112 // all of the attribute types together to produce a map type.
113 //
114 // Our unification behavior is intentionally stricter than our conversion
115 // behavior for subset object types because user intent is different with
116 // unification use-cases: it makes sense to allow {"foo":true} to convert
117 // to emptyobjectval, but unifying an object with an attribute with the
118 // empty object type should be an error because unifying to the empty
119 // object type would be suprising and useless.
120
121 firstAttrs := types[0].AttributeTypes()
122 for _, ty := range types[1:] {
123 thisAttrs := ty.AttributeTypes()
124 if len(thisAttrs) != len(firstAttrs) {
125 // If number of attributes is different then there can be no
126 // object type in common.
127 return unifyObjectTypesToMap(types, unsafe)
128 }
129 for name := range thisAttrs {
130 if _, ok := firstAttrs[name]; !ok {
131 // If attribute names don't exactly match then there can be
132 // no object type in common.
133 return unifyObjectTypesToMap(types, unsafe)
134 }
135 }
136 }
137
138 // If we get here then we've proven that all of the given object types
139 // have exactly the same set of attribute names, though the types may
140 // differ.
141 retAtys := make(map[string]cty.Type)
142 atysAcross := make([]cty.Type, len(types))
143 for name := range firstAttrs {
144 for i, ty := range types {
145 atysAcross[i] = ty.AttributeType(name)
146 }
147 retAtys[name], _ = unify(atysAcross, unsafe)
148 if retAtys[name] == cty.NilType {
149 // Cannot unify this attribute alone, which means that unification
150 // of everything down to a map type can't be possible either.
151 return cty.NilType, nil
152 }
153 }
154 retTy := cty.Object(retAtys)
155
156 conversions := make([]Conversion, len(types))
157 for i, ty := range types {
158 if ty.Equals(retTy) {
159 continue
160 }
161 if unsafe {
162 conversions[i] = GetConversionUnsafe(ty, retTy)
163 } else {
164 conversions[i] = GetConversion(ty, retTy)
165 }
166 if conversions[i] == nil {
167 // Shouldn't be reachable, since we were able to unify
168 return unifyObjectTypesToMap(types, unsafe)
169 }
170 }
171
172 return retTy, conversions
173}
174
175func unifyObjectTypesToMap(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
176 // This is our fallback case for unifyObjectTypes, where we see if we can
177 // construct a map type that can accept all of the attribute types.
178
179 var atys []cty.Type
180 for _, ty := range types {
181 for _, aty := range ty.AttributeTypes() {
182 atys = append(atys, aty)
183 }
184 }
185
186 ety, _ := unify(atys, unsafe)
187 if ety == cty.NilType {
188 return cty.NilType, nil
189 }
190
191 retTy := cty.Map(ety)
192 conversions := make([]Conversion, len(types))
193 for i, ty := range types {
194 if ty.Equals(retTy) {
195 continue
196 }
197 if unsafe {
198 conversions[i] = GetConversionUnsafe(ty, retTy)
199 } else {
200 conversions[i] = GetConversion(ty, retTy)
201 }
202 if conversions[i] == nil {
203 return cty.NilType, nil
204 }
205 }
206 return retTy, conversions
207}
208
209func unifyTupleTypes(types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []Conversion) {
210 // If we had any dynamic types in the input here then we can't predict
211 // what path we'll take through here once these become known types, so
212 // we'll conservatively produce DynamicVal for these.
213 if hasDynamic {
214 return unifyAllAsDynamic(types)
215 }
216
217 // There are two different ways we can succeed here:
218 // - If all of the given tuple types have the same sequence of element types
219 // and the corresponding types are all unifyable, then we construct that
220 // type.
221 // - If the given tuple types have different element types or their
222 // corresponding types are not unifyable, we'll instead try to unify
223 // all of the elements types together to produce a list type.
224
225 firstEtys := types[0].TupleElementTypes()
226 for _, ty := range types[1:] {
227 thisEtys := ty.TupleElementTypes()
228 if len(thisEtys) != len(firstEtys) {
229 // If number of elements is different then there can be no
230 // tuple type in common.
231 return unifyTupleTypesToList(types, unsafe)
232 }
233 }
234
235 // If we get here then we've proven that all of the given tuple types
236 // have the same number of elements, though the types may differ.
237 retEtys := make([]cty.Type, len(firstEtys))
238 atysAcross := make([]cty.Type, len(types))
239 for idx := range firstEtys {
240 for tyI, ty := range types {
241 atysAcross[tyI] = ty.TupleElementTypes()[idx]
242 }
243 retEtys[idx], _ = unify(atysAcross, unsafe)
244 if retEtys[idx] == cty.NilType {
245 // Cannot unify this element alone, which means that unification
246 // of everything down to a map type can't be possible either.
247 return cty.NilType, nil
248 }
249 }
250 retTy := cty.Tuple(retEtys)
251
252 conversions := make([]Conversion, len(types))
253 for i, ty := range types {
254 if ty.Equals(retTy) {
255 continue
256 }
257 if unsafe {
258 conversions[i] = GetConversionUnsafe(ty, retTy)
259 } else {
260 conversions[i] = GetConversion(ty, retTy)
261 }
262 if conversions[i] == nil {
263 // Shouldn't be reachable, since we were able to unify
264 return unifyTupleTypesToList(types, unsafe)
265 }
266 }
267
268 return retTy, conversions
269}
270
271func unifyTupleTypesToList(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
272 // This is our fallback case for unifyTupleTypes, where we see if we can
273 // construct a list type that can accept all of the element types.
274
275 var etys []cty.Type
276 for _, ty := range types {
277 for _, ety := range ty.TupleElementTypes() {
278 etys = append(etys, ety)
279 }
280 }
281
282 ety, _ := unify(etys, unsafe)
283 if ety == cty.NilType {
284 return cty.NilType, nil
285 }
286
287 retTy := cty.List(ety)
288 conversions := make([]Conversion, len(types))
289 for i, ty := range types {
290 if ty.Equals(retTy) {
291 continue
292 }
293 if unsafe {
294 conversions[i] = GetConversionUnsafe(ty, retTy)
295 } else {
296 conversions[i] = GetConversion(ty, retTy)
297 }
298 if conversions[i] == nil {
299 // Shouldn't be reachable, since we were able to unify
300 return unifyObjectTypesToMap(types, unsafe)
301 }
302 }
303 return retTy, conversions
304}
305
306func unifyAllAsDynamic(types []cty.Type) (cty.Type, []Conversion) {
307 conversions := make([]Conversion, len(types))
308 for i := range conversions {
309 conversions[i] = func(cty.Value) (cty.Value, error) {
310 return cty.DynamicVal, nil
311 }
312 }
313 return cty.DynamicPseudoType, conversions
314}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/function.go b/vendor/github.com/zclconf/go-cty/cty/function/function.go
index 162f7bf..9e8bf33 100644
--- a/vendor/github.com/zclconf/go-cty/cty/function/function.go
+++ b/vendor/github.com/zclconf/go-cty/cty/function/function.go
@@ -143,7 +143,7 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error)
143 val := posArgs[i] 143 val := posArgs[i]
144 144
145 if val.IsNull() && !spec.AllowNull { 145 if val.IsNull() && !spec.AllowNull {
146 return cty.Type{}, NewArgErrorf(i, "must not be null") 146 return cty.Type{}, NewArgErrorf(i, "argument must not be null")
147 } 147 }
148 148
149 // AllowUnknown is ignored for type-checking, since we expect to be 149 // AllowUnknown is ignored for type-checking, since we expect to be
@@ -169,7 +169,7 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error)
169 realI := i + len(posArgs) 169 realI := i + len(posArgs)
170 170
171 if val.IsNull() && !spec.AllowNull { 171 if val.IsNull() && !spec.AllowNull {
172 return cty.Type{}, NewArgErrorf(realI, "must not be null") 172 return cty.Type{}, NewArgErrorf(realI, "argument must not be null")
173 } 173 }
174 174
175 if val.Type() == cty.DynamicPseudoType { 175 if val.Type() == cty.DynamicPseudoType {
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go
new file mode 100644
index 0000000..aa15b7b
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go
@@ -0,0 +1,385 @@
1package stdlib
2
3import (
4 "bufio"
5 "bytes"
6 "fmt"
7 "strings"
8 "time"
9
10 "github.com/zclconf/go-cty/cty"
11 "github.com/zclconf/go-cty/cty/function"
12)
13
14var FormatDateFunc = function.New(&function.Spec{
15 Params: []function.Parameter{
16 {
17 Name: "format",
18 Type: cty.String,
19 },
20 {
21 Name: "time",
22 Type: cty.String,
23 },
24 },
25 Type: function.StaticReturnType(cty.String),
26 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
27 formatStr := args[0].AsString()
28 timeStr := args[1].AsString()
29 t, err := parseTimestamp(timeStr)
30 if err != nil {
31 return cty.DynamicVal, function.NewArgError(1, err)
32 }
33
34 var buf bytes.Buffer
35 sc := bufio.NewScanner(strings.NewReader(formatStr))
36 sc.Split(splitDateFormat)
37 const esc = '\''
38 for sc.Scan() {
39 tok := sc.Bytes()
40
41 // The leading byte signals the token type
42 switch {
43 case tok[0] == esc:
44 if tok[len(tok)-1] != esc || len(tok) == 1 {
45 return cty.DynamicVal, function.NewArgErrorf(0, "unterminated literal '")
46 }
47 if len(tok) == 2 {
48 // Must be a single escaped quote, ''
49 buf.WriteByte(esc)
50 } else {
51 // The content (until a closing esc) is printed out verbatim
52 // except that we must un-double any double-esc escapes in
53 // the middle of the string.
54 raw := tok[1 : len(tok)-1]
55 for i := 0; i < len(raw); i++ {
56 buf.WriteByte(raw[i])
57 if raw[i] == esc {
58 i++ // skip the escaped quote
59 }
60 }
61 }
62
63 case startsDateFormatVerb(tok[0]):
64 switch tok[0] {
65 case 'Y':
66 y := t.Year()
67 switch len(tok) {
68 case 2:
69 fmt.Fprintf(&buf, "%02d", y%100)
70 case 4:
71 fmt.Fprintf(&buf, "%04d", y)
72 default:
73 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: year must either be \"YY\" or \"YYYY\"", tok)
74 }
75 case 'M':
76 m := t.Month()
77 switch len(tok) {
78 case 1:
79 fmt.Fprintf(&buf, "%d", m)
80 case 2:
81 fmt.Fprintf(&buf, "%02d", m)
82 case 3:
83 buf.WriteString(m.String()[:3])
84 case 4:
85 buf.WriteString(m.String())
86 default:
87 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: month must be \"M\", \"MM\", \"MMM\", or \"MMMM\"", tok)
88 }
89 case 'D':
90 d := t.Day()
91 switch len(tok) {
92 case 1:
93 fmt.Fprintf(&buf, "%d", d)
94 case 2:
95 fmt.Fprintf(&buf, "%02d", d)
96 default:
97 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: day of month must either be \"D\" or \"DD\"", tok)
98 }
99 case 'E':
100 d := t.Weekday()
101 switch len(tok) {
102 case 3:
103 buf.WriteString(d.String()[:3])
104 case 4:
105 buf.WriteString(d.String())
106 default:
107 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: day of week must either be \"EEE\" or \"EEEE\"", tok)
108 }
109 case 'h':
110 h := t.Hour()
111 switch len(tok) {
112 case 1:
113 fmt.Fprintf(&buf, "%d", h)
114 case 2:
115 fmt.Fprintf(&buf, "%02d", h)
116 default:
117 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: 24-hour must either be \"h\" or \"hh\"", tok)
118 }
119 case 'H':
120 h := t.Hour() % 12
121 if h == 0 {
122 h = 12
123 }
124 switch len(tok) {
125 case 1:
126 fmt.Fprintf(&buf, "%d", h)
127 case 2:
128 fmt.Fprintf(&buf, "%02d", h)
129 default:
130 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: 12-hour must either be \"H\" or \"HH\"", tok)
131 }
132 case 'A', 'a':
133 if len(tok) != 2 {
134 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: must be \"%s%s\"", tok, tok[0:1], tok[0:1])
135 }
136 upper := tok[0] == 'A'
137 switch t.Hour() / 12 {
138 case 0:
139 if upper {
140 buf.WriteString("AM")
141 } else {
142 buf.WriteString("am")
143 }
144 case 1:
145 if upper {
146 buf.WriteString("PM")
147 } else {
148 buf.WriteString("pm")
149 }
150 }
151 case 'm':
152 m := t.Minute()
153 switch len(tok) {
154 case 1:
155 fmt.Fprintf(&buf, "%d", m)
156 case 2:
157 fmt.Fprintf(&buf, "%02d", m)
158 default:
159 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: minute must either be \"m\" or \"mm\"", tok)
160 }
161 case 's':
162 s := t.Second()
163 switch len(tok) {
164 case 1:
165 fmt.Fprintf(&buf, "%d", s)
166 case 2:
167 fmt.Fprintf(&buf, "%02d", s)
168 default:
169 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: second must either be \"s\" or \"ss\"", tok)
170 }
171 case 'Z':
172 // We'll just lean on Go's own formatter for this one, since
173 // the necessary information is unexported.
174 switch len(tok) {
175 case 1:
176 buf.WriteString(t.Format("Z07:00"))
177 case 3:
178 str := t.Format("-0700")
179 switch str {
180 case "+0000":
181 buf.WriteString("UTC")
182 default:
183 buf.WriteString(str)
184 }
185 case 4:
186 buf.WriteString(t.Format("-0700"))
187 case 5:
188 buf.WriteString(t.Format("-07:00"))
189 default:
190 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: timezone must be Z, ZZZZ, or ZZZZZ", tok)
191 }
192 default:
193 return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q", tok)
194 }
195
196 default:
197 // Any other starting character indicates a literal sequence
198 buf.Write(tok)
199 }
200 }
201
202 return cty.StringVal(buf.String()), nil
203 },
204})
205
206// FormatDate reformats a timestamp given in RFC3339 syntax into another time
207// syntax defined by a given format string.
208//
209// The format string uses letter mnemonics to represent portions of the
210// timestamp, with repetition signifying length variants of each portion.
211// Single quote characters ' can be used to quote sequences of literal letters
212// that should not be interpreted as formatting mnemonics.
213//
214// The full set of supported mnemonic sequences is listed below:
215//
216// YY Year modulo 100 zero-padded to two digits, like "06".
217// YYYY Four (or more) digit year, like "2006".
218// M Month number, like "1" for January.
219// MM Month number zero-padded to two digits, like "01".
220// MMM English month name abbreviated to three letters, like "Jan".
221// MMMM English month name unabbreviated, like "January".
222// D Day of month number, like "2".
223// DD Day of month number zero-padded to two digits, like "02".
224// EEE English day of week name abbreviated to three letters, like "Mon".
225// EEEE English day of week name unabbreviated, like "Monday".
226// h 24-hour number, like "2".
227// hh 24-hour number zero-padded to two digits, like "02".
228// H 12-hour number, like "2".
229// HH 12-hour number zero-padded to two digits, like "02".
230// AA Hour AM/PM marker in uppercase, like "AM".
231// aa Hour AM/PM marker in lowercase, like "am".
232// m Minute within hour, like "5".
233// mm Minute within hour zero-padded to two digits, like "05".
234// s Second within minute, like "9".
235// ss Second within minute zero-padded to two digits, like "09".
236// ZZZZ Timezone offset with just sign and digit, like "-0800".
237// ZZZZZ Timezone offset with colon separating hours and minutes, like "-08:00".
238// Z Like ZZZZZ but with a special case "Z" for UTC.
239// ZZZ Like ZZZZ but with a special case "UTC" for UTC.
240//
241// The format syntax is optimized mainly for generating machine-oriented
242// timestamps rather than human-oriented timestamps; the English language
243// portions of the output reflect the use of English names in a number of
244// machine-readable date formatting standards. For presentation to humans,
245// a locale-aware time formatter (not included in this package) is a better
246// choice.
247//
248// The format syntax is not compatible with that of any other language, but
249// is optimized so that patterns for common standard date formats can be
250// recognized quickly even by a reader unfamiliar with the format syntax.
251func FormatDate(format cty.Value, timestamp cty.Value) (cty.Value, error) {
252 return FormatDateFunc.Call([]cty.Value{format, timestamp})
253}
254
255func parseTimestamp(ts string) (time.Time, error) {
256 t, err := time.Parse(time.RFC3339, ts)
257 if err != nil {
258 switch err := err.(type) {
259 case *time.ParseError:
260 // If err is s time.ParseError then its string representation is not
261 // appropriate since it relies on details of Go's strange date format
262 // representation, which a caller of our functions is not expected
263 // to be familiar with.
264 //
265 // Therefore we do some light transformation to get a more suitable
266 // error that should make more sense to our callers. These are
267 // still not awesome error messages, but at least they refer to
268 // the timestamp portions by name rather than by Go's example
269 // values.
270 if err.LayoutElem == "" && err.ValueElem == "" && err.Message != "" {
271 // For some reason err.Message is populated with a ": " prefix
272 // by the time package.
273 return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp%s", err.Message)
274 }
275 var what string
276 switch err.LayoutElem {
277 case "2006":
278 what = "year"
279 case "01":
280 what = "month"
281 case "02":
282 what = "day of month"
283 case "15":
284 what = "hour"
285 case "04":
286 what = "minute"
287 case "05":
288 what = "second"
289 case "Z07:00":
290 what = "UTC offset"
291 case "T":
292 return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: missing required time introducer 'T'")
293 case ":", "-":
294 if err.ValueElem == "" {
295 return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: end of string where %q is expected", err.LayoutElem)
296 } else {
297 return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: found %q where %q is expected", err.ValueElem, err.LayoutElem)
298 }
299 default:
300 // Should never get here, because time.RFC3339 includes only the
301 // above portions, but since that might change in future we'll
302 // be robust here.
303 what = "timestamp segment"
304 }
305 if err.ValueElem == "" {
306 return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: end of string before %s", what)
307 } else {
308 return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: cannot use %q as %s", err.ValueElem, what)
309 }
310 }
311 return time.Time{}, err
312 }
313 return t, nil
314}
315
316// splitDataFormat is a bufio.SplitFunc used to tokenize a date format.
317func splitDateFormat(data []byte, atEOF bool) (advance int, token []byte, err error) {
318 if len(data) == 0 {
319 return 0, nil, nil
320 }
321
322 const esc = '\''
323
324 switch {
325
326 case data[0] == esc:
327 // If we have another quote immediately after then this is a single
328 // escaped escape.
329 if len(data) > 1 && data[1] == esc {
330 return 2, data[:2], nil
331 }
332
333 // Beginning of quoted sequence, so we will seek forward until we find
334 // the closing quote, ignoring escaped quotes along the way.
335 for i := 1; i < len(data); i++ {
336 if data[i] == esc {
337 if (i + 1) == len(data) {
338 // We need at least one more byte to decide if this is an
339 // escape or a terminator.
340 return 0, nil, nil
341 }
342 if data[i+1] == esc {
343 i++ // doubled-up quotes are an escape sequence
344 continue
345 }
346 // We've found the closing quote
347 return i + 1, data[:i+1], nil
348 }
349 }
350 // If we fall out here then we need more bytes to find the end,
351 // unless we're already at the end with an unclosed quote.
352 if atEOF {
353 return len(data), data, nil
354 }
355 return 0, nil, nil
356
357 case startsDateFormatVerb(data[0]):
358 rep := data[0]
359 for i := 1; i < len(data); i++ {
360 if data[i] != rep {
361 return i, data[:i], nil
362 }
363 }
364 if atEOF {
365 return len(data), data, nil
366 }
367 // We need more data to decide if we've found the end
368 return 0, nil, nil
369
370 default:
371 for i := 1; i < len(data); i++ {
372 if data[i] == esc || startsDateFormatVerb(data[i]) {
373 return i, data[:i], nil
374 }
375 }
376 // We might not actually be at the end of a literal sequence,
377 // but that doesn't matter since we'll concat them back together
378 // anyway.
379 return len(data), data, nil
380 }
381}
382
383func startsDateFormatVerb(b byte) bool {
384 return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')
385}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
index fb24f20..664790b 100644
--- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
@@ -84,6 +84,11 @@ var FormatListFunc = function.New(&function.Spec{
84 argTy := arg.Type() 84 argTy := arg.Type()
85 switch { 85 switch {
86 case (argTy.IsListType() || argTy.IsSetType() || argTy.IsTupleType()) && !arg.IsNull(): 86 case (argTy.IsListType() || argTy.IsSetType() || argTy.IsTupleType()) && !arg.IsNull():
87 if !argTy.IsTupleType() && !arg.IsKnown() {
88 // We can't iterate this one at all yet then, so we can't
89 // yet produce a result.
90 return cty.UnknownVal(retType), nil
91 }
87 thisLen := arg.LengthInt() 92 thisLen := arg.LengthInt()
88 if iterLen == -1 { 93 if iterLen == -1 {
89 iterLen = thisLen 94 iterLen = thisLen
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
index 86876ba..32b1ac9 100644
--- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
@@ -11,9 +11,10 @@ import (
11 "unicode/utf8" 11 "unicode/utf8"
12 12
13 "github.com/zclconf/go-cty/cty" 13 "github.com/zclconf/go-cty/cty"
14 "github.com/zclconf/go-cty/cty/function"
14) 15)
15 16
16// line 20 "format_fsm.go" 17// line 21 "format_fsm.go"
17var _formatfsm_actions []byte = []byte{ 18var _formatfsm_actions []byte = []byte{
18 0, 1, 0, 1, 1, 1, 2, 1, 4, 19 0, 1, 0, 1, 1, 1, 2, 1, 4,
19 1, 5, 1, 6, 1, 7, 1, 8, 20 1, 5, 1, 6, 1, 7, 1, 8,
@@ -86,15 +87,16 @@ const formatfsm_error int = 0
86 87
87const formatfsm_en_main int = 8 88const formatfsm_en_main int = 8
88 89
89// line 19 "format_fsm.rl" 90// line 20 "format_fsm.rl"
90 91
91func formatFSM(format string, a []cty.Value) (string, error) { 92func formatFSM(format string, a []cty.Value) (string, error) {
92 var buf bytes.Buffer 93 var buf bytes.Buffer
93 data := format 94 data := format
94 nextArg := 1 // arg numbers are 1-based 95 nextArg := 1 // arg numbers are 1-based
95 var verb formatVerb 96 var verb formatVerb
97 highestArgIdx := 0 // zero means "none", since arg numbers are 1-based
96 98
97 // line 153 "format_fsm.rl" 99 // line 159 "format_fsm.rl"
98 100
99 // Ragel state 101 // Ragel state
100 p := 0 // "Pointer" into data 102 p := 0 // "Pointer" into data
@@ -109,12 +111,12 @@ func formatFSM(format string, a []cty.Value) (string, error) {
109 _ = te 111 _ = te
110 _ = eof 112 _ = eof
111 113
112 // line 121 "format_fsm.go" 114 // line 123 "format_fsm.go"
113 { 115 {
114 cs = formatfsm_start 116 cs = formatfsm_start
115 } 117 }
116 118
117 // line 126 "format_fsm.go" 119 // line 128 "format_fsm.go"
118 { 120 {
119 var _klen int 121 var _klen int
120 var _trans int 122 var _trans int
@@ -195,7 +197,7 @@ func formatFSM(format string, a []cty.Value) (string, error) {
195 _acts++ 197 _acts++
196 switch _formatfsm_actions[_acts-1] { 198 switch _formatfsm_actions[_acts-1] {
197 case 0: 199 case 0:
198 // line 29 "format_fsm.rl" 200 // line 31 "format_fsm.rl"
199 201
200 verb = formatVerb{ 202 verb = formatVerb{
201 ArgNum: nextArg, 203 ArgNum: nextArg,
@@ -205,12 +207,12 @@ func formatFSM(format string, a []cty.Value) (string, error) {
205 ts = p 207 ts = p
206 208
207 case 1: 209 case 1:
208 // line 38 "format_fsm.rl" 210 // line 40 "format_fsm.rl"
209 211
210 buf.WriteByte(data[p]) 212 buf.WriteByte(data[p])
211 213
212 case 4: 214 case 4:
213 // line 49 "format_fsm.rl" 215 // line 51 "format_fsm.rl"
214 216
215 // We'll try to slurp a whole UTF-8 sequence here, to give the user 217 // We'll try to slurp a whole UTF-8 sequence here, to give the user
216 // better feedback. 218 // better feedback.
@@ -218,85 +220,89 @@ func formatFSM(format string, a []cty.Value) (string, error) {
218 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p) 220 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
219 221
220 case 5: 222 case 5:
221 // line 56 "format_fsm.rl" 223 // line 58 "format_fsm.rl"
222 224
223 verb.Sharp = true 225 verb.Sharp = true
224 226
225 case 6: 227 case 6:
226 // line 59 "format_fsm.rl" 228 // line 61 "format_fsm.rl"
227 229
228 verb.Zero = true 230 verb.Zero = true
229 231
230 case 7: 232 case 7:
231 // line 62 "format_fsm.rl" 233 // line 64 "format_fsm.rl"
232 234
233 verb.Minus = true 235 verb.Minus = true
234 236
235 case 8: 237 case 8:
236 // line 65 "format_fsm.rl" 238 // line 67 "format_fsm.rl"
237 239
238 verb.Plus = true 240 verb.Plus = true
239 241
240 case 9: 242 case 9:
241 // line 68 "format_fsm.rl" 243 // line 70 "format_fsm.rl"
242 244
243 verb.Space = true 245 verb.Space = true
244 246
245 case 10: 247 case 10:
246 // line 72 "format_fsm.rl" 248 // line 74 "format_fsm.rl"
247 249
248 verb.ArgNum = 0 250 verb.ArgNum = 0
249 251
250 case 11: 252 case 11:
251 // line 75 "format_fsm.rl" 253 // line 77 "format_fsm.rl"
252 254
253 verb.ArgNum = (10 * verb.ArgNum) + (int(data[p]) - '0') 255 verb.ArgNum = (10 * verb.ArgNum) + (int(data[p]) - '0')
254 256
255 case 12: 257 case 12:
256 // line 79 "format_fsm.rl" 258 // line 81 "format_fsm.rl"
257 259
258 verb.HasWidth = true 260 verb.HasWidth = true
259 261
260 case 13: 262 case 13:
261 // line 82 "format_fsm.rl" 263 // line 84 "format_fsm.rl"
262 264
263 verb.Width = 0 265 verb.Width = 0
264 266
265 case 14: 267 case 14:
266 // line 85 "format_fsm.rl" 268 // line 87 "format_fsm.rl"
267 269
268 verb.Width = (10 * verb.Width) + (int(data[p]) - '0') 270 verb.Width = (10 * verb.Width) + (int(data[p]) - '0')
269 271
270 case 15: 272 case 15:
271 // line 89 "format_fsm.rl" 273 // line 91 "format_fsm.rl"
272 274
273 verb.HasPrec = true 275 verb.HasPrec = true
274 276
275 case 16: 277 case 16:
276 // line 92 "format_fsm.rl" 278 // line 94 "format_fsm.rl"
277 279
278 verb.Prec = 0 280 verb.Prec = 0
279 281
280 case 17: 282 case 17:
281 // line 95 "format_fsm.rl" 283 // line 97 "format_fsm.rl"
282 284
283 verb.Prec = (10 * verb.Prec) + (int(data[p]) - '0') 285 verb.Prec = (10 * verb.Prec) + (int(data[p]) - '0')
284 286
285 case 18: 287 case 18:
286 // line 99 "format_fsm.rl" 288 // line 101 "format_fsm.rl"
287 289
288 verb.Mode = rune(data[p]) 290 verb.Mode = rune(data[p])
289 te = p + 1 291 te = p + 1
290 verb.Raw = data[ts:te] 292 verb.Raw = data[ts:te]
291 verb.Offset = ts 293 verb.Offset = ts
292 294
295 if verb.ArgNum > highestArgIdx {
296 highestArgIdx = verb.ArgNum
297 }
298
293 err := formatAppend(&verb, &buf, a) 299 err := formatAppend(&verb, &buf, a)
294 if err != nil { 300 if err != nil {
295 return buf.String(), err 301 return buf.String(), err
296 } 302 }
297 nextArg = verb.ArgNum + 1 303 nextArg = verb.ArgNum + 1
298 304
299 // line 324 "format_fsm.go" 305 // line 330 "format_fsm.go"
300 } 306 }
301 } 307 }
302 308
@@ -319,22 +325,22 @@ func formatFSM(format string, a []cty.Value) (string, error) {
319 __acts++ 325 __acts++
320 switch _formatfsm_actions[__acts-1] { 326 switch _formatfsm_actions[__acts-1] {
321 case 2: 327 case 2:
322 // line 42 "format_fsm.rl" 328 // line 44 "format_fsm.rl"
323 329
324 case 3: 330 case 3:
325 // line 45 "format_fsm.rl" 331 // line 47 "format_fsm.rl"
326 332
327 return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p) 333 return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
328 334
329 case 4: 335 case 4:
330 // line 49 "format_fsm.rl" 336 // line 51 "format_fsm.rl"
331 337
332 // We'll try to slurp a whole UTF-8 sequence here, to give the user 338 // We'll try to slurp a whole UTF-8 sequence here, to give the user
333 // better feedback. 339 // better feedback.
334 r, _ := utf8.DecodeRuneInString(data[p:]) 340 r, _ := utf8.DecodeRuneInString(data[p:])
335 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p) 341 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
336 342
337 // line 363 "format_fsm.go" 343 // line 369 "format_fsm.go"
338 } 344 }
339 } 345 }
340 } 346 }
@@ -344,14 +350,24 @@ func formatFSM(format string, a []cty.Value) (string, error) {
344 } 350 }
345 } 351 }
346 352
347 // line 171 "format_fsm.rl" 353 // line 177 "format_fsm.rl"
348 354
349 // If we fall out here without being in a final state then we've 355 // If we fall out here without being in a final state then we've
350 // encountered something that the scanner can't match, which should 356 // encountered something that the scanner can't match, which should
351 // be impossible (the scanner matches all bytes _somehow_) but we'll 357 // be impossible (the scanner matches all bytes _somehow_) but we'll
352 // flag it anyway rather than just losing data from the end. 358 // flag it anyway rather than just losing data from the end.
353 if cs < formatfsm_first_final { 359 if cs < formatfsm_first_final {
354 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %i", p) 360 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %d", p)
361 }
362
363 if highestArgIdx < len(a) {
364 // Extraneous args are an error, to more easily detect mistakes
365 firstBad := highestArgIdx + 1
366 if highestArgIdx == 0 {
367 // Custom error message for this case
368 return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; no verbs in format string")
369 }
370 return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; only %d used by format string", highestArgIdx)
355 } 371 }
356 372
357 return buf.String(), nil 373 return buf.String(), nil
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
index 85d43bb..3c642d9 100644
--- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
@@ -12,6 +12,7 @@ import (
12 "unicode/utf8" 12 "unicode/utf8"
13 13
14 "github.com/zclconf/go-cty/cty" 14 "github.com/zclconf/go-cty/cty"
15 "github.com/zclconf/go-cty/cty/function"
15) 16)
16 17
17%%{ 18%%{
@@ -23,6 +24,7 @@ func formatFSM(format string, a []cty.Value) (string, error) {
23 data := format 24 data := format
24 nextArg := 1 // arg numbers are 1-based 25 nextArg := 1 // arg numbers are 1-based
25 var verb formatVerb 26 var verb formatVerb
27 highestArgIdx := 0 // zero means "none", since arg numbers are 1-based
26 28
27 %%{ 29 %%{
28 30
@@ -102,6 +104,10 @@ func formatFSM(format string, a []cty.Value) (string, error) {
102 verb.Raw = data[ts:te] 104 verb.Raw = data[ts:te]
103 verb.Offset = ts 105 verb.Offset = ts
104 106
107 if verb.ArgNum > highestArgIdx {
108 highestArgIdx = verb.ArgNum
109 }
110
105 err := formatAppend(&verb, &buf, a) 111 err := formatAppend(&verb, &buf, a)
106 if err != nil { 112 if err != nil {
107 return buf.String(), err 113 return buf.String(), err
@@ -175,7 +181,17 @@ func formatFSM(format string, a []cty.Value) (string, error) {
175 // be impossible (the scanner matches all bytes _somehow_) but we'll 181 // be impossible (the scanner matches all bytes _somehow_) but we'll
176 // flag it anyway rather than just losing data from the end. 182 // flag it anyway rather than just losing data from the end.
177 if cs < formatfsm_first_final { 183 if cs < formatfsm_first_final {
178 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %i", p) 184 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %d", p)
185 }
186
187 if highestArgIdx < len(a) {
188 // Extraneous args are an error, to more easily detect mistakes
189 firstBad := highestArgIdx+1
190 if highestArgIdx == 0 {
191 // Custom error message for this case
192 return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; no verbs in format string")
193 }
194 return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; only %d used by format string", highestArgIdx)
179 } 195 }
180 196
181 return buf.String(), nil 197 return buf.String(), nil
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go
new file mode 100644
index 0000000..2dd6348
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go
@@ -0,0 +1,233 @@
1package stdlib
2
3import (
4 "fmt"
5 "regexp"
6 resyntax "regexp/syntax"
7
8 "github.com/zclconf/go-cty/cty"
9 "github.com/zclconf/go-cty/cty/function"
10)
11
12var RegexFunc = function.New(&function.Spec{
13 Params: []function.Parameter{
14 {
15 Name: "pattern",
16 Type: cty.String,
17 },
18 {
19 Name: "string",
20 Type: cty.String,
21 },
22 },
23 Type: func(args []cty.Value) (cty.Type, error) {
24 if !args[0].IsKnown() {
25 // We can't predict our type without seeing our pattern
26 return cty.DynamicPseudoType, nil
27 }
28
29 retTy, err := regexPatternResultType(args[0].AsString())
30 if err != nil {
31 err = function.NewArgError(0, err)
32 }
33 return retTy, err
34 },
35 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
36 if retType == cty.DynamicPseudoType {
37 return cty.DynamicVal, nil
38 }
39
40 re, err := regexp.Compile(args[0].AsString())
41 if err != nil {
42 // Should never happen, since we checked this in the Type function above.
43 return cty.NilVal, function.NewArgErrorf(0, "error parsing pattern: %s", err)
44 }
45 str := args[1].AsString()
46
47 captureIdxs := re.FindStringSubmatchIndex(str)
48 if captureIdxs == nil {
49 return cty.NilVal, fmt.Errorf("pattern did not match any part of the given string")
50 }
51
52 return regexPatternResult(re, str, captureIdxs, retType), nil
53 },
54})
55
56var RegexAllFunc = function.New(&function.Spec{
57 Params: []function.Parameter{
58 {
59 Name: "pattern",
60 Type: cty.String,
61 },
62 {
63 Name: "string",
64 Type: cty.String,
65 },
66 },
67 Type: func(args []cty.Value) (cty.Type, error) {
68 if !args[0].IsKnown() {
69 // We can't predict our type without seeing our pattern,
70 // but we do know it'll always be a list of something.
71 return cty.List(cty.DynamicPseudoType), nil
72 }
73
74 retTy, err := regexPatternResultType(args[0].AsString())
75 if err != nil {
76 err = function.NewArgError(0, err)
77 }
78 return cty.List(retTy), err
79 },
80 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
81 ety := retType.ElementType()
82 if ety == cty.DynamicPseudoType {
83 return cty.DynamicVal, nil
84 }
85
86 re, err := regexp.Compile(args[0].AsString())
87 if err != nil {
88 // Should never happen, since we checked this in the Type function above.
89 return cty.NilVal, function.NewArgErrorf(0, "error parsing pattern: %s", err)
90 }
91 str := args[1].AsString()
92
93 captureIdxsEach := re.FindAllStringSubmatchIndex(str, -1)
94 if len(captureIdxsEach) == 0 {
95 return cty.ListValEmpty(ety), nil
96 }
97
98 elems := make([]cty.Value, len(captureIdxsEach))
99 for i, captureIdxs := range captureIdxsEach {
100 elems[i] = regexPatternResult(re, str, captureIdxs, ety)
101 }
102 return cty.ListVal(elems), nil
103 },
104})
105
106// Regex is a function that extracts one or more substrings from a given
107// string by applying a regular expression pattern, describing the first
108// match.
109//
110// The return type depends on the composition of the capture groups (if any)
111// in the pattern:
112//
113// - If there are no capture groups at all, the result is a single string
114// representing the entire matched pattern.
115// - If all of the capture groups are named, the result is an object whose
116// keys are the named groups and whose values are their sub-matches, or
117// null if a particular sub-group was inside another group that didn't
118// match.
119// - If none of the capture groups are named, the result is a tuple whose
120// elements are the sub-groups in order and whose values are their
121// sub-matches, or null if a particular sub-group was inside another group
122// that didn't match.
123// - It is invalid to use both named and un-named capture groups together in
124// the same pattern.
125//
126// If the pattern doesn't match, this function returns an error. To test for
127// a match, call RegexAll and check if the length of the result is greater
128// than zero.
129func Regex(pattern, str cty.Value) (cty.Value, error) {
130 return RegexFunc.Call([]cty.Value{pattern, str})
131}
132
133// RegexAll is similar to Regex but it finds all of the non-overlapping matches
134// in the given string and returns a list of them.
135//
136// The result type is always a list, whose element type is deduced from the
137// pattern in the same way as the return type for Regex is decided.
138//
139// If the pattern doesn't match at all, this function returns an empty list.
140func RegexAll(pattern, str cty.Value) (cty.Value, error) {
141 return RegexAllFunc.Call([]cty.Value{pattern, str})
142}
143
144// regexPatternResultType parses the given regular expression pattern and
145// returns the structural type that would be returned to represent its
146// capture groups.
147//
148// Returns an error if parsing fails or if the pattern uses a mixture of
149// named and unnamed capture groups, which is not permitted.
150func regexPatternResultType(pattern string) (cty.Type, error) {
151 re, rawErr := regexp.Compile(pattern)
152 switch err := rawErr.(type) {
153 case *resyntax.Error:
154 return cty.NilType, fmt.Errorf("invalid regexp pattern: %s in %s", err.Code, err.Expr)
155 case error:
156 // Should never happen, since all regexp compile errors should
157 // be resyntax.Error, but just in case...
158 return cty.NilType, fmt.Errorf("error parsing pattern: %s", err)
159 }
160
161 allNames := re.SubexpNames()[1:]
162 var names []string
163 unnamed := 0
164 for _, name := range allNames {
165 if name == "" {
166 unnamed++
167 } else {
168 if names == nil {
169 names = make([]string, 0, len(allNames))
170 }
171 names = append(names, name)
172 }
173 }
174 switch {
175 case unnamed == 0 && len(names) == 0:
176 // If there are no capture groups at all then we'll return just a
177 // single string for the whole match.
178 return cty.String, nil
179 case unnamed > 0 && len(names) > 0:
180 return cty.NilType, fmt.Errorf("invalid regexp pattern: cannot mix both named and unnamed capture groups")
181 case unnamed > 0:
182 // For unnamed captures, we return a tuple of them all in order.
183 etys := make([]cty.Type, unnamed)
184 for i := range etys {
185 etys[i] = cty.String
186 }
187 return cty.Tuple(etys), nil
188 default:
189 // For named captures, we return an object using the capture names
190 // as keys.
191 atys := make(map[string]cty.Type, len(names))
192 for _, name := range names {
193 atys[name] = cty.String
194 }
195 return cty.Object(atys), nil
196 }
197}
198
199func regexPatternResult(re *regexp.Regexp, str string, captureIdxs []int, retType cty.Type) cty.Value {
200 switch {
201 case retType == cty.String:
202 start, end := captureIdxs[0], captureIdxs[1]
203 return cty.StringVal(str[start:end])
204 case retType.IsTupleType():
205 captureIdxs = captureIdxs[2:] // index 0 is the whole pattern span, which we ignore by skipping one pair
206 vals := make([]cty.Value, len(captureIdxs)/2)
207 for i := range vals {
208 start, end := captureIdxs[i*2], captureIdxs[i*2+1]
209 if start < 0 || end < 0 {
210 vals[i] = cty.NullVal(cty.String) // Did not match anything because containing group didn't match
211 continue
212 }
213 vals[i] = cty.StringVal(str[start:end])
214 }
215 return cty.TupleVal(vals)
216 case retType.IsObjectType():
217 captureIdxs = captureIdxs[2:] // index 0 is the whole pattern span, which we ignore by skipping one pair
218 vals := make(map[string]cty.Value, len(captureIdxs)/2)
219 names := re.SubexpNames()[1:]
220 for i, name := range names {
221 start, end := captureIdxs[i*2], captureIdxs[i*2+1]
222 if start < 0 || end < 0 {
223 vals[name] = cty.NullVal(cty.String) // Did not match anything because containing group didn't match
224 continue
225 }
226 vals[name] = cty.StringVal(str[start:end])
227 }
228 return cty.ObjectVal(vals)
229 default:
230 // Should never happen
231 panic(fmt.Sprintf("invalid return type %#v", retType))
232 }
233}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
index e2c77c5..d3cc341 100644
--- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
@@ -119,6 +119,75 @@ var ConcatFunc = function.New(&function.Spec{
119 }, 119 },
120}) 120})
121 121
122var RangeFunc = function.New(&function.Spec{
123 VarParam: &function.Parameter{
124 Name: "params",
125 Type: cty.Number,
126 },
127 Type: function.StaticReturnType(cty.List(cty.Number)),
128 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
129 var start, end, step cty.Value
130 switch len(args) {
131 case 1:
132 if args[0].LessThan(cty.Zero).True() {
133 start, end, step = cty.Zero, args[0], cty.NumberIntVal(-1)
134 } else {
135 start, end, step = cty.Zero, args[0], cty.NumberIntVal(1)
136 }
137 case 2:
138 if args[1].LessThan(args[0]).True() {
139 start, end, step = args[0], args[1], cty.NumberIntVal(-1)
140 } else {
141 start, end, step = args[0], args[1], cty.NumberIntVal(1)
142 }
143 case 3:
144 start, end, step = args[0], args[1], args[2]
145 default:
146 return cty.NilVal, fmt.Errorf("must have one, two, or three arguments")
147 }
148
149 var vals []cty.Value
150
151 if step == cty.Zero {
152 return cty.NilVal, function.NewArgErrorf(2, "step must not be zero")
153 }
154 down := step.LessThan(cty.Zero).True()
155
156 if down {
157 if end.GreaterThan(start).True() {
158 return cty.NilVal, function.NewArgErrorf(1, "end must be less than start when step is negative")
159 }
160 } else {
161 if end.LessThan(start).True() {
162 return cty.NilVal, function.NewArgErrorf(1, "end must be greater than start when step is positive")
163 }
164 }
165
166 num := start
167 for {
168 if down {
169 if num.LessThanOrEqualTo(end).True() {
170 break
171 }
172 } else {
173 if num.GreaterThanOrEqualTo(end).True() {
174 break
175 }
176 }
177 if len(vals) >= 1024 {
178 // Artificial limit to prevent bad arguments from consuming huge amounts of memory
179 return cty.NilVal, fmt.Errorf("more than 1024 values were generated; either decrease the difference between start and end or use a smaller step")
180 }
181 vals = append(vals, num)
182 num = num.Add(step)
183 }
184 if len(vals) == 0 {
185 return cty.ListValEmpty(cty.Number), nil
186 }
187 return cty.ListVal(vals), nil
188 },
189})
190
122// Concat takes one or more sequences (lists or tuples) and returns the single 191// Concat takes one or more sequences (lists or tuples) and returns the single
123// sequence that results from concatenating them together in order. 192// sequence that results from concatenating them together in order.
124// 193//
@@ -128,3 +197,22 @@ var ConcatFunc = function.New(&function.Spec{
128func Concat(seqs ...cty.Value) (cty.Value, error) { 197func Concat(seqs ...cty.Value) (cty.Value, error) {
129 return ConcatFunc.Call(seqs) 198 return ConcatFunc.Call(seqs)
130} 199}
200
201// Range creates a list of numbers by starting from the given starting value,
202// then adding the given step value until the result is greater than or
203// equal to the given stopping value. Each intermediate result becomes an
204// element in the resulting list.
205//
206// When all three parameters are set, the order is (start, end, step). If
207// only two parameters are set, they are the start and end respectively and
208// step defaults to 1. If only one argument is set, it gives the end value
209// with start defaulting to 0 and step defaulting to 1.
210//
211// Because the resulting list must be fully buffered in memory, there is an
212// artificial cap of 1024 elements, after which this function will return
213// an error to avoid consuming unbounded amounts of memory. The Range function
214// is primarily intended for creating small lists of indices to iterate over,
215// so there should be no reason to generate huge lists with it.
216func Range(params ...cty.Value) (cty.Value, error) {
217 return RangeFunc.Call(params)
218}
diff --git a/vendor/github.com/zclconf/go-cty/cty/gob.go b/vendor/github.com/zclconf/go-cty/cty/gob.go
index 3d73199..a77dace 100644
--- a/vendor/github.com/zclconf/go-cty/cty/gob.go
+++ b/vendor/github.com/zclconf/go-cty/cty/gob.go
@@ -103,11 +103,11 @@ func (t *Type) GobDecode(buf []byte) error {
103// Capsule types cannot currently be gob-encoded, because they rely on pointer 103// Capsule types cannot currently be gob-encoded, because they rely on pointer
104// equality and we have no way to recover the original pointer on decode. 104// equality and we have no way to recover the original pointer on decode.
105func (t *capsuleType) GobEncode() ([]byte, error) { 105func (t *capsuleType) GobEncode() ([]byte, error) {
106 return nil, fmt.Errorf("cannot gob-encode capsule type %q", t.FriendlyName()) 106 return nil, fmt.Errorf("cannot gob-encode capsule type %q", t.FriendlyName(friendlyTypeName))
107} 107}
108 108
109func (t *capsuleType) GobDecode() ([]byte, error) { 109func (t *capsuleType) GobDecode() ([]byte, error) {
110 return nil, fmt.Errorf("cannot gob-decode capsule type %q", t.FriendlyName()) 110 return nil, fmt.Errorf("cannot gob-decode capsule type %q", t.FriendlyName(friendlyTypeName))
111} 111}
112 112
113type gobValue struct { 113type gobValue struct {
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/in.go b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go
index 642501b..ca9de21 100644
--- a/vendor/github.com/zclconf/go-cty/cty/gocty/in.go
+++ b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go
@@ -5,6 +5,7 @@ import (
5 "reflect" 5 "reflect"
6 6
7 "github.com/zclconf/go-cty/cty" 7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/convert"
8 "github.com/zclconf/go-cty/cty/set" 9 "github.com/zclconf/go-cty/cty/set"
9) 10)
10 11
@@ -32,6 +33,11 @@ func ToCtyValue(val interface{}, ty cty.Type) (cty.Value, error) {
32} 33}
33 34
34func toCtyValue(val reflect.Value, ty cty.Type, path cty.Path) (cty.Value, error) { 35func toCtyValue(val reflect.Value, ty cty.Type, path cty.Path) (cty.Value, error) {
36 if val != (reflect.Value{}) && val.Type().AssignableTo(valueType) {
37 // If the source value is a cty.Value then we'll try to just pass
38 // through to the target type directly.
39 return toCtyPassthrough(val, ty, path)
40 }
35 41
36 switch ty { 42 switch ty {
37 case cty.Bool: 43 case cty.Bool:
@@ -505,6 +511,20 @@ func toCtyDynamic(val reflect.Value, path cty.Path) (cty.Value, error) {
505 511
506} 512}
507 513
514func toCtyPassthrough(wrappedVal reflect.Value, wantTy cty.Type, path cty.Path) (cty.Value, error) {
515 if wrappedVal = toCtyUnwrapPointer(wrappedVal); !wrappedVal.IsValid() {
516 return cty.NullVal(wantTy), nil
517 }
518
519 givenVal := wrappedVal.Interface().(cty.Value)
520
521 val, err := convert.Convert(givenVal, wantTy)
522 if err != nil {
523 return cty.NilVal, path.NewErrorf("unsuitable value: %s", err)
524 }
525 return val, nil
526}
527
508// toCtyUnwrapPointer is a helper for dealing with Go pointers. It has three 528// toCtyUnwrapPointer is a helper for dealing with Go pointers. It has three
509// possible outcomes: 529// possible outcomes:
510// 530//
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/out.go b/vendor/github.com/zclconf/go-cty/cty/gocty/out.go
index 99b65a7..e9c2599 100644
--- a/vendor/github.com/zclconf/go-cty/cty/gocty/out.go
+++ b/vendor/github.com/zclconf/go-cty/cty/gocty/out.go
@@ -1,11 +1,10 @@
1package gocty 1package gocty
2 2
3import ( 3import (
4 "math"
4 "math/big" 5 "math/big"
5 "reflect" 6 "reflect"
6 7
7 "math"
8
9 "github.com/zclconf/go-cty/cty" 8 "github.com/zclconf/go-cty/cty"
10) 9)
11 10
@@ -112,11 +111,7 @@ func fromCtyBool(val cty.Value, target reflect.Value, path cty.Path) error {
112 switch target.Kind() { 111 switch target.Kind() {
113 112
114 case reflect.Bool: 113 case reflect.Bool:
115 if val.True() { 114 target.SetBool(val.True())
116 target.Set(reflect.ValueOf(true))
117 } else {
118 target.Set(reflect.ValueOf(false))
119 }
120 return nil 115 return nil
121 116
122 default: 117 default:
@@ -175,8 +170,7 @@ func fromCtyNumberInt(bf *big.Float, target reflect.Value, path cty.Path) error
175 return path.NewErrorf("value must be a whole number, between %d and %d", min, max) 170 return path.NewErrorf("value must be a whole number, between %d and %d", min, max)
176 } 171 }
177 172
178 target.Set(reflect.ValueOf(iv).Convert(target.Type())) 173 target.SetInt(iv)
179
180 return nil 174 return nil
181} 175}
182 176
@@ -202,25 +196,13 @@ func fromCtyNumberUInt(bf *big.Float, target reflect.Value, path cty.Path) error
202 return path.NewErrorf("value must be a whole number, between 0 and %d inclusive", max) 196 return path.NewErrorf("value must be a whole number, between 0 and %d inclusive", max)
203 } 197 }
204 198
205 target.Set(reflect.ValueOf(iv).Convert(target.Type())) 199 target.SetUint(iv)
206
207 return nil 200 return nil
208} 201}
209 202
210func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) error { 203func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) error {
211 switch target.Kind() { 204 switch target.Kind() {
212 case reflect.Float32: 205 case reflect.Float32, reflect.Float64:
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() 206 fv, accuracy := bf.Float64()
225 if accuracy != big.Exact { 207 if accuracy != big.Exact {
226 // We allow the precision to be truncated as part of our conversion, 208 // We allow the precision to be truncated as part of our conversion,
@@ -229,7 +211,7 @@ func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) erro
229 return path.NewErrorf("value must be between %f and %f inclusive", -math.MaxFloat64, math.MaxFloat64) 211 return path.NewErrorf("value must be between %f and %f inclusive", -math.MaxFloat64, math.MaxFloat64)
230 } 212 }
231 } 213 }
232 target.Set(reflect.ValueOf(fv)) 214 target.SetFloat(fv)
233 return nil 215 return nil
234 default: 216 default:
235 panic("unsupported kind of float") 217 panic("unsupported kind of float")
@@ -239,17 +221,17 @@ func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) erro
239func fromCtyNumberBig(bf *big.Float, target reflect.Value, path cty.Path) error { 221func fromCtyNumberBig(bf *big.Float, target reflect.Value, path cty.Path) error {
240 switch { 222 switch {
241 223
242 case bigFloatType.AssignableTo(target.Type()): 224 case bigFloatType.ConvertibleTo(target.Type()):
243 // Easy! 225 // Easy!
244 target.Set(reflect.ValueOf(bf).Elem()) 226 target.Set(reflect.ValueOf(bf).Elem().Convert(target.Type()))
245 return nil 227 return nil
246 228
247 case bigIntType.AssignableTo(target.Type()): 229 case bigIntType.ConvertibleTo(target.Type()):
248 bi, accuracy := bf.Int(nil) 230 bi, accuracy := bf.Int(nil)
249 if accuracy != big.Exact { 231 if accuracy != big.Exact {
250 return path.NewErrorf("value must be a whole number") 232 return path.NewErrorf("value must be a whole number")
251 } 233 }
252 target.Set(reflect.ValueOf(bi).Elem()) 234 target.Set(reflect.ValueOf(bi).Elem().Convert(target.Type()))
253 return nil 235 return nil
254 236
255 default: 237 default:
@@ -259,9 +241,8 @@ func fromCtyNumberBig(bf *big.Float, target reflect.Value, path cty.Path) error
259 241
260func fromCtyString(val cty.Value, target reflect.Value, path cty.Path) error { 242func fromCtyString(val cty.Value, target reflect.Value, path cty.Path) error {
261 switch target.Kind() { 243 switch target.Kind() {
262
263 case reflect.String: 244 case reflect.String:
264 target.Set(reflect.ValueOf(val.AsString())) 245 target.SetString(val.AsString())
265 return nil 246 return nil
266 247
267 default: 248 default:
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go b/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go
index 1a97306..0fa13f6 100644
--- a/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go
+++ b/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go
@@ -138,7 +138,7 @@ func impliedObjectType(dec *json.Decoder) (cty.Type, error) {
138} 138}
139 139
140func impliedTupleType(dec *json.Decoder) (cty.Type, error) { 140func impliedTupleType(dec *json.Decoder) (cty.Type, error) {
141 // By the time we get in here, we've already consumed the { delimiter 141 // By the time we get in here, we've already consumed the [ delimiter
142 // and so our next token should be the first value. 142 // and so our next token should be the first value.
143 143
144 var etys []cty.Type 144 var etys []cty.Type
@@ -150,10 +150,9 @@ func impliedTupleType(dec *json.Decoder) (cty.Type, error) {
150 } 150 }
151 151
152 if ttok, ok := tok.(json.Delim); ok { 152 if ttok, ok := tok.(json.Delim); ok {
153 if rune(ttok) != ']' { 153 if rune(ttok) == ']' {
154 return cty.NilType, fmt.Errorf("unexpected delimiter %q", ttok) 154 break
155 } 155 }
156 break
157 } 156 }
158 157
159 ety, err := impliedTypeForTok(tok, dec) 158 ety, err := impliedTypeForTok(tok, dec)
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go b/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
index 155f0b8..3810645 100644
--- a/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
+++ b/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
@@ -72,7 +72,7 @@ func unmarshalPrimitive(tok json.Token, t cty.Type, path cty.Path) (cty.Value, e
72 } 72 }
73 switch v := tok.(type) { 73 switch v := tok.(type) {
74 case string: 74 case string:
75 val, err := convert.Convert(cty.StringVal(v), t) 75 val, err := cty.ParseNumberVal(v)
76 if err != nil { 76 if err != nil {
77 return cty.NilVal, path.NewError(err) 77 return cty.NilVal, path.NewError(err)
78 } 78 }
diff --git a/vendor/github.com/zclconf/go-cty/cty/list_type.go b/vendor/github.com/zclconf/go-cty/cty/list_type.go
index eadc865..2ef02a1 100644
--- a/vendor/github.com/zclconf/go-cty/cty/list_type.go
+++ b/vendor/github.com/zclconf/go-cty/cty/list_type.go
@@ -33,8 +33,14 @@ func (t typeList) Equals(other Type) bool {
33 return t.ElementTypeT.Equals(ot.ElementTypeT) 33 return t.ElementTypeT.Equals(ot.ElementTypeT)
34} 34}
35 35
36func (t typeList) FriendlyName() string { 36func (t typeList) FriendlyName(mode friendlyTypeNameMode) string {
37 return "list of " + t.ElementTypeT.FriendlyName() 37 elemName := t.ElementTypeT.friendlyNameMode(mode)
38 if mode == friendlyTypeConstraintName {
39 if t.ElementTypeT == DynamicPseudoType {
40 elemName = "any single type"
41 }
42 }
43 return "list of " + elemName
38} 44}
39 45
40func (t typeList) ElementType() Type { 46func (t typeList) ElementType() Type {
diff --git a/vendor/github.com/zclconf/go-cty/cty/map_type.go b/vendor/github.com/zclconf/go-cty/cty/map_type.go
index ae9abae..82d36c6 100644
--- a/vendor/github.com/zclconf/go-cty/cty/map_type.go
+++ b/vendor/github.com/zclconf/go-cty/cty/map_type.go
@@ -33,8 +33,14 @@ func (t typeMap) Equals(other Type) bool {
33 return t.ElementTypeT.Equals(ot.ElementTypeT) 33 return t.ElementTypeT.Equals(ot.ElementTypeT)
34} 34}
35 35
36func (t typeMap) FriendlyName() string { 36func (t typeMap) FriendlyName(mode friendlyTypeNameMode) string {
37 return "map of " + t.ElementTypeT.FriendlyName() 37 elemName := t.ElementTypeT.friendlyNameMode(mode)
38 if mode == friendlyTypeConstraintName {
39 if t.ElementTypeT == DynamicPseudoType {
40 elemName = "any single type"
41 }
42 }
43 return "map of " + elemName
38} 44}
39 45
40func (t typeMap) ElementType() Type { 46func (t typeMap) ElementType() Type {
diff --git a/vendor/github.com/zclconf/go-cty/cty/msgpack/doc.go b/vendor/github.com/zclconf/go-cty/cty/msgpack/doc.go
new file mode 100644
index 0000000..1eb99f2
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/msgpack/doc.go
@@ -0,0 +1,14 @@
1// Package msgpack provides functions for serializing cty values in the
2// msgpack encoding, and decoding them again.
3//
4// If the same type information is provided both at encoding and decoding time
5// then values can be round-tripped without loss, except for capsule types
6// which are not currently supported.
7//
8// If any unknown values are passed to Marshal then they will be represented
9// using a msgpack extension with type code zero, which is understood by
10// the Unmarshal function within this package but will not be understood by
11// a generic (non-cty-aware) msgpack decoder. Ensure that no unknown values
12// are used if interoperability with other msgpack implementations is
13// required.
14package msgpack
diff --git a/vendor/github.com/zclconf/go-cty/cty/msgpack/dynamic.go b/vendor/github.com/zclconf/go-cty/cty/msgpack/dynamic.go
new file mode 100644
index 0000000..1b631d0
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/msgpack/dynamic.go
@@ -0,0 +1,31 @@
1package msgpack
2
3import (
4 "bytes"
5
6 "github.com/vmihailenco/msgpack"
7 "github.com/zclconf/go-cty/cty"
8)
9
10type dynamicVal struct {
11 Value cty.Value
12 Path cty.Path
13}
14
15func (dv *dynamicVal) MarshalMsgpack() ([]byte, error) {
16 // Rather than defining a msgpack-specific serialization of types,
17 // instead we use the existing JSON serialization.
18 typeJSON, err := dv.Value.Type().MarshalJSON()
19 if err != nil {
20 return nil, dv.Path.NewErrorf("failed to serialize type: %s", err)
21 }
22 var buf bytes.Buffer
23 enc := msgpack.NewEncoder(&buf)
24 enc.EncodeArrayLen(2)
25 enc.EncodeBytes(typeJSON)
26 err = marshal(dv.Value, dv.Value.Type(), dv.Path, enc)
27 if err != nil {
28 return nil, err
29 }
30 return buf.Bytes(), nil
31}
diff --git a/vendor/github.com/zclconf/go-cty/cty/msgpack/infinity.go b/vendor/github.com/zclconf/go-cty/cty/msgpack/infinity.go
new file mode 100644
index 0000000..6db0815
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/msgpack/infinity.go
@@ -0,0 +1,8 @@
1package msgpack
2
3import (
4 "math"
5)
6
7var negativeInfinity = math.Inf(-1)
8var positiveInfinity = math.Inf(1)
diff --git a/vendor/github.com/zclconf/go-cty/cty/msgpack/marshal.go b/vendor/github.com/zclconf/go-cty/cty/msgpack/marshal.go
new file mode 100644
index 0000000..87b096c
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/msgpack/marshal.go
@@ -0,0 +1,207 @@
1package msgpack
2
3import (
4 "bytes"
5 "math/big"
6 "sort"
7
8 "github.com/vmihailenco/msgpack"
9 "github.com/zclconf/go-cty/cty"
10 "github.com/zclconf/go-cty/cty/convert"
11)
12
13// Marshal produces a msgpack serialization of the given value that
14// can be decoded into the given type later using Unmarshal.
15//
16// The given value must conform to the given type, or an error will
17// be returned.
18func Marshal(val cty.Value, ty cty.Type) ([]byte, error) {
19 errs := val.Type().TestConformance(ty)
20 if errs != nil {
21 // Attempt a conversion
22 var err error
23 val, err = convert.Convert(val, ty)
24 if err != nil {
25 return nil, err
26 }
27 }
28
29 // From this point onward, val can be assumed to be conforming to t.
30
31 var path cty.Path
32 var buf bytes.Buffer
33 enc := msgpack.NewEncoder(&buf)
34
35 err := marshal(val, ty, path, enc)
36 if err != nil {
37 return nil, err
38 }
39
40 return buf.Bytes(), nil
41}
42
43func marshal(val cty.Value, ty cty.Type, path cty.Path, enc *msgpack.Encoder) error {
44 // If we're going to decode as DynamicPseudoType then we need to save
45 // dynamic type information to recover the real type.
46 if ty == cty.DynamicPseudoType && val.Type() != cty.DynamicPseudoType {
47 return marshalDynamic(val, path, enc)
48 }
49
50 if !val.IsKnown() {
51 err := enc.Encode(unknownVal)
52 if err != nil {
53 return path.NewError(err)
54 }
55 return nil
56 }
57 if val.IsNull() {
58 err := enc.EncodeNil()
59 if err != nil {
60 return path.NewError(err)
61 }
62 return nil
63 }
64
65 // The caller should've guaranteed that the given val is conformant with
66 // the given type ty, so we'll proceed under that assumption here.
67 switch {
68 case ty.IsPrimitiveType():
69 switch ty {
70 case cty.String:
71 err := enc.EncodeString(val.AsString())
72 if err != nil {
73 return path.NewError(err)
74 }
75 return nil
76 case cty.Number:
77 var err error
78 switch {
79 case val.RawEquals(cty.PositiveInfinity):
80 err = enc.EncodeFloat64(positiveInfinity)
81 case val.RawEquals(cty.NegativeInfinity):
82 err = enc.EncodeFloat64(negativeInfinity)
83 default:
84 bf := val.AsBigFloat()
85 if iv, acc := bf.Int64(); acc == big.Exact {
86 err = enc.EncodeInt(iv)
87 } else if fv, acc := bf.Float64(); acc == big.Exact {
88 err = enc.EncodeFloat64(fv)
89 } else {
90 err = enc.EncodeString(bf.Text('f', -1))
91 }
92 }
93 if err != nil {
94 return path.NewError(err)
95 }
96 return nil
97 case cty.Bool:
98 err := enc.EncodeBool(val.True())
99 if err != nil {
100 return path.NewError(err)
101 }
102 return nil
103 default:
104 panic("unsupported primitive type")
105 }
106 case ty.IsListType(), ty.IsSetType():
107 enc.EncodeArrayLen(val.LengthInt())
108 ety := ty.ElementType()
109 it := val.ElementIterator()
110 path := append(path, nil) // local override of 'path' with extra element
111 for it.Next() {
112 ek, ev := it.Element()
113 path[len(path)-1] = cty.IndexStep{
114 Key: ek,
115 }
116 err := marshal(ev, ety, path, enc)
117 if err != nil {
118 return err
119 }
120 }
121 return nil
122 case ty.IsMapType():
123 enc.EncodeMapLen(val.LengthInt())
124 ety := ty.ElementType()
125 it := val.ElementIterator()
126 path := append(path, nil) // local override of 'path' with extra element
127 for it.Next() {
128 ek, ev := it.Element()
129 path[len(path)-1] = cty.IndexStep{
130 Key: ek,
131 }
132 var err error
133 err = marshal(ek, ek.Type(), path, enc)
134 if err != nil {
135 return err
136 }
137 err = marshal(ev, ety, path, enc)
138 if err != nil {
139 return err
140 }
141 }
142 return nil
143 case ty.IsTupleType():
144 etys := ty.TupleElementTypes()
145 it := val.ElementIterator()
146 path := append(path, nil) // local override of 'path' with extra element
147 i := 0
148 enc.EncodeArrayLen(len(etys))
149 for it.Next() {
150 ety := etys[i]
151 ek, ev := it.Element()
152 path[len(path)-1] = cty.IndexStep{
153 Key: ek,
154 }
155 err := marshal(ev, ety, path, enc)
156 if err != nil {
157 return err
158 }
159 i++
160 }
161 return nil
162 case ty.IsObjectType():
163 atys := ty.AttributeTypes()
164 path := append(path, nil) // local override of 'path' with extra element
165
166 names := make([]string, 0, len(atys))
167 for k := range atys {
168 names = append(names, k)
169 }
170 sort.Strings(names)
171
172 enc.EncodeMapLen(len(names))
173
174 for _, k := range names {
175 aty := atys[k]
176 av := val.GetAttr(k)
177 path[len(path)-1] = cty.GetAttrStep{
178 Name: k,
179 }
180 var err error
181 err = marshal(cty.StringVal(k), cty.String, path, enc)
182 if err != nil {
183 return err
184 }
185 err = marshal(av, aty, path, enc)
186 if err != nil {
187 return err
188 }
189 }
190 return nil
191 case ty.IsCapsuleType():
192 return path.NewErrorf("capsule types not supported for msgpack encoding")
193 default:
194 // should never happen
195 return path.NewErrorf("cannot msgpack-serialize %s", ty.FriendlyName())
196 }
197}
198
199// marshalDynamic adds an extra wrapping object containing dynamic type
200// information for the given value.
201func marshalDynamic(val cty.Value, path cty.Path, enc *msgpack.Encoder) error {
202 dv := dynamicVal{
203 Value: val,
204 Path: path,
205 }
206 return enc.Encode(&dv)
207}
diff --git a/vendor/github.com/zclconf/go-cty/cty/msgpack/type_implied.go b/vendor/github.com/zclconf/go-cty/cty/msgpack/type_implied.go
new file mode 100644
index 0000000..6f6022e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/msgpack/type_implied.go
@@ -0,0 +1,167 @@
1package msgpack
2
3import (
4 "bytes"
5 "fmt"
6 "io"
7
8 "github.com/vmihailenco/msgpack"
9 msgpackcodes "github.com/vmihailenco/msgpack/codes"
10 "github.com/zclconf/go-cty/cty"
11)
12
13// ImpliedType returns the cty Type implied by the structure of the given
14// msgpack-compliant buffer. This function implements the default type mapping
15// behavior used when decoding arbitrary msgpack without explicit cty Type
16// information.
17//
18// The rules are as follows:
19//
20// msgpack strings, numbers and bools map to their equivalent primitive type in
21// cty.
22//
23// msgpack maps become cty object types, with the attributes defined by the
24// map keys and the types of their values.
25//
26// msgpack arrays become cty tuple types, with the elements defined by the
27// types of the array members.
28//
29// Any nulls are typed as DynamicPseudoType, so callers of this function
30// must be prepared to deal with this. Callers that do not wish to deal with
31// dynamic typing should not use this function and should instead describe
32// their required types explicitly with a cty.Type instance when decoding.
33//
34// Any unknown values are similarly typed as DynamicPseudoType, because these
35// do not carry type information on the wire.
36//
37// Any parse errors will be returned as an error, and the type will be the
38// invalid value cty.NilType.
39func ImpliedType(buf []byte) (cty.Type, error) {
40 r := bytes.NewReader(buf)
41 dec := msgpack.NewDecoder(r)
42
43 ty, err := impliedType(dec)
44 if err != nil {
45 return cty.NilType, err
46 }
47
48 // We must now be at the end of the buffer
49 err = dec.Skip()
50 if err != io.EOF {
51 return ty, fmt.Errorf("extra bytes after msgpack value")
52 }
53
54 return ty, nil
55}
56
57func impliedType(dec *msgpack.Decoder) (cty.Type, error) {
58 // If this function returns with a nil error then it must have already
59 // consumed the next value from the decoder, since when called recursively
60 // the caller will be expecting to find a following value here.
61
62 code, err := dec.PeekCode()
63 if err != nil {
64 return cty.NilType, err
65 }
66
67 switch {
68
69 case code == msgpackcodes.Nil || msgpackcodes.IsExt(code):
70 err := dec.Skip()
71 return cty.DynamicPseudoType, err
72
73 case code == msgpackcodes.True || code == msgpackcodes.False:
74 _, err := dec.DecodeBool()
75 return cty.Bool, err
76
77 case msgpackcodes.IsFixedNum(code):
78 _, err := dec.DecodeInt64()
79 return cty.Number, err
80
81 case code == msgpackcodes.Int8 || code == msgpackcodes.Int16 || code == msgpackcodes.Int32 || code == msgpackcodes.Int64:
82 _, err := dec.DecodeInt64()
83 return cty.Number, err
84
85 case code == msgpackcodes.Uint8 || code == msgpackcodes.Uint16 || code == msgpackcodes.Uint32 || code == msgpackcodes.Uint64:
86 _, err := dec.DecodeUint64()
87 return cty.Number, err
88
89 case code == msgpackcodes.Float || code == msgpackcodes.Double:
90 _, err := dec.DecodeFloat64()
91 return cty.Number, err
92
93 case msgpackcodes.IsString(code):
94 _, err := dec.DecodeString()
95 return cty.String, err
96
97 case msgpackcodes.IsFixedMap(code) || code == msgpackcodes.Map16 || code == msgpackcodes.Map32:
98 return impliedObjectType(dec)
99
100 case msgpackcodes.IsFixedArray(code) || code == msgpackcodes.Array16 || code == msgpackcodes.Array32:
101 return impliedTupleType(dec)
102
103 default:
104 return cty.NilType, fmt.Errorf("unsupported msgpack code %#v", code)
105 }
106}
107
108func impliedObjectType(dec *msgpack.Decoder) (cty.Type, error) {
109 // If we get in here then we've already peeked the next code and know
110 // it's some sort of map.
111 l, err := dec.DecodeMapLen()
112 if err != nil {
113 return cty.DynamicPseudoType, nil
114 }
115
116 var atys map[string]cty.Type
117
118 for i := 0; i < l; i++ {
119 // Read the map key first. We require maps to be strings, but msgpack
120 // doesn't so we're prepared to error here if not.
121 k, err := dec.DecodeString()
122 if err != nil {
123 return cty.DynamicPseudoType, err
124 }
125
126 aty, err := impliedType(dec)
127 if err != nil {
128 return cty.DynamicPseudoType, err
129 }
130
131 if atys == nil {
132 atys = make(map[string]cty.Type)
133 }
134 atys[k] = aty
135 }
136
137 if len(atys) == 0 {
138 return cty.EmptyObject, nil
139 }
140
141 return cty.Object(atys), nil
142}
143
144func impliedTupleType(dec *msgpack.Decoder) (cty.Type, error) {
145 // If we get in here then we've already peeked the next code and know
146 // it's some sort of array.
147 l, err := dec.DecodeArrayLen()
148 if err != nil {
149 return cty.DynamicPseudoType, nil
150 }
151
152 if l == 0 {
153 return cty.EmptyTuple, nil
154 }
155
156 etys := make([]cty.Type, l)
157
158 for i := 0; i < l; i++ {
159 ety, err := impliedType(dec)
160 if err != nil {
161 return cty.DynamicPseudoType, err
162 }
163 etys[i] = ety
164 }
165
166 return cty.Tuple(etys), nil
167}
diff --git a/vendor/github.com/zclconf/go-cty/cty/msgpack/unknown.go b/vendor/github.com/zclconf/go-cty/cty/msgpack/unknown.go
new file mode 100644
index 0000000..6507bc4
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/msgpack/unknown.go
@@ -0,0 +1,16 @@
1package msgpack
2
3type unknownType struct{}
4
5var unknownVal = unknownType{}
6
7// unknownValBytes is the raw bytes of the msgpack fixext1 value we
8// write to represent an unknown value. It's an extension value of
9// type zero whose value is irrelevant. Since it's irrelevant, we
10// set it to a single byte whose value is also zero, since that's
11// the most compact possible representation.
12var unknownValBytes = []byte{0xd4, 0, 0}
13
14func (uv unknownType) MarshalMsgpack() ([]byte, error) {
15 return unknownValBytes, nil
16}
diff --git a/vendor/github.com/zclconf/go-cty/cty/msgpack/unmarshal.go b/vendor/github.com/zclconf/go-cty/cty/msgpack/unmarshal.go
new file mode 100644
index 0000000..51bb76a
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/msgpack/unmarshal.go
@@ -0,0 +1,334 @@
1package msgpack
2
3import (
4 "bytes"
5
6 "github.com/vmihailenco/msgpack"
7 msgpackCodes "github.com/vmihailenco/msgpack/codes"
8 "github.com/zclconf/go-cty/cty"
9)
10
11// Unmarshal interprets the given bytes as a msgpack-encoded cty Value of
12// the given type, returning the result.
13//
14// If an error is returned, the error is written with a hypothetical
15// end-user that wrote the msgpack file as its audience, using cty type
16// system concepts rather than Go type system concepts.
17func Unmarshal(b []byte, ty cty.Type) (cty.Value, error) {
18 r := bytes.NewReader(b)
19 dec := msgpack.NewDecoder(r)
20
21 var path cty.Path
22 return unmarshal(dec, ty, path)
23}
24
25func unmarshal(dec *msgpack.Decoder, ty cty.Type, path cty.Path) (cty.Value, error) {
26 peek, err := dec.PeekCode()
27 if err != nil {
28 return cty.DynamicVal, path.NewError(err)
29 }
30 if msgpackCodes.IsExt(peek) {
31 // We just assume _all_ extensions are unknown values,
32 // since we don't have any other extensions.
33 dec.Skip() // skip what we've peeked
34 return cty.UnknownVal(ty), nil
35 }
36 if ty == cty.DynamicPseudoType {
37 return unmarshalDynamic(dec, path)
38 }
39 if peek == msgpackCodes.Nil {
40 dec.Skip() // skip what we've peeked
41 return cty.NullVal(ty), nil
42 }
43
44 switch {
45 case ty.IsPrimitiveType():
46 val, err := unmarshalPrimitive(dec, ty, path)
47 if err != nil {
48 return cty.NilVal, err
49 }
50 return val, nil
51 case ty.IsListType():
52 return unmarshalList(dec, ty.ElementType(), path)
53 case ty.IsSetType():
54 return unmarshalSet(dec, ty.ElementType(), path)
55 case ty.IsMapType():
56 return unmarshalMap(dec, ty.ElementType(), path)
57 case ty.IsTupleType():
58 return unmarshalTuple(dec, ty.TupleElementTypes(), path)
59 case ty.IsObjectType():
60 return unmarshalObject(dec, ty.AttributeTypes(), path)
61 default:
62 return cty.NilVal, path.NewErrorf("unsupported type %s", ty.FriendlyName())
63 }
64}
65
66func unmarshalPrimitive(dec *msgpack.Decoder, ty cty.Type, path cty.Path) (cty.Value, error) {
67 switch ty {
68 case cty.Bool:
69 rv, err := dec.DecodeBool()
70 if err != nil {
71 return cty.DynamicVal, path.NewErrorf("bool is required")
72 }
73 return cty.BoolVal(rv), nil
74 case cty.Number:
75 // Marshal will try int and float first, if the value can be
76 // losslessly represented in these encodings, and then fall
77 // back on a string if the number is too large or too precise.
78 peek, err := dec.PeekCode()
79 if err != nil {
80 return cty.DynamicVal, path.NewErrorf("number is required")
81 }
82
83 if msgpackCodes.IsFixedNum(peek) {
84 rv, err := dec.DecodeInt64()
85 if err != nil {
86 return cty.DynamicVal, path.NewErrorf("number is required")
87 }
88 return cty.NumberIntVal(rv), nil
89 }
90
91 switch peek {
92 case msgpackCodes.Int8, msgpackCodes.Int16, msgpackCodes.Int32, msgpackCodes.Int64:
93 rv, err := dec.DecodeInt64()
94 if err != nil {
95 return cty.DynamicVal, path.NewErrorf("number is required")
96 }
97 return cty.NumberIntVal(rv), nil
98 case msgpackCodes.Uint8, msgpackCodes.Uint16, msgpackCodes.Uint32, msgpackCodes.Uint64:
99 rv, err := dec.DecodeUint64()
100 if err != nil {
101 return cty.DynamicVal, path.NewErrorf("number is required")
102 }
103 return cty.NumberUIntVal(rv), nil
104 case msgpackCodes.Float, msgpackCodes.Double:
105 rv, err := dec.DecodeFloat64()
106 if err != nil {
107 return cty.DynamicVal, path.NewErrorf("number is required")
108 }
109 return cty.NumberFloatVal(rv), nil
110 default:
111 rv, err := dec.DecodeString()
112 if err != nil {
113 return cty.DynamicVal, path.NewErrorf("number is required")
114 }
115 v, err := cty.ParseNumberVal(rv)
116 if err != nil {
117 return cty.DynamicVal, path.NewErrorf("number is required")
118 }
119 return v, nil
120 }
121 case cty.String:
122 rv, err := dec.DecodeString()
123 if err != nil {
124 return cty.DynamicVal, path.NewErrorf("string is required")
125 }
126 return cty.StringVal(rv), nil
127 default:
128 // should never happen
129 panic("unsupported primitive type")
130 }
131}
132
133func unmarshalList(dec *msgpack.Decoder, ety cty.Type, path cty.Path) (cty.Value, error) {
134 length, err := dec.DecodeArrayLen()
135 if err != nil {
136 return cty.DynamicVal, path.NewErrorf("a list is required")
137 }
138
139 switch {
140 case length < 0:
141 return cty.NullVal(cty.List(ety)), nil
142 case length == 0:
143 return cty.ListValEmpty(ety), nil
144 }
145
146 vals := make([]cty.Value, 0, length)
147 path = append(path, nil)
148 for i := 0; i < length; i++ {
149 path[len(path)-1] = cty.IndexStep{
150 Key: cty.NumberIntVal(int64(i)),
151 }
152
153 val, err := unmarshal(dec, ety, path)
154 if err != nil {
155 return cty.DynamicVal, err
156 }
157
158 vals = append(vals, val)
159 }
160
161 return cty.ListVal(vals), nil
162}
163
164func unmarshalSet(dec *msgpack.Decoder, ety cty.Type, path cty.Path) (cty.Value, error) {
165 length, err := dec.DecodeArrayLen()
166 if err != nil {
167 return cty.DynamicVal, path.NewErrorf("a set is required")
168 }
169
170 switch {
171 case length < 0:
172 return cty.NullVal(cty.Set(ety)), nil
173 case length == 0:
174 return cty.SetValEmpty(ety), nil
175 }
176
177 vals := make([]cty.Value, 0, length)
178 path = append(path, nil)
179 for i := 0; i < length; i++ {
180 path[len(path)-1] = cty.IndexStep{
181 Key: cty.NumberIntVal(int64(i)),
182 }
183
184 val, err := unmarshal(dec, ety, path)
185 if err != nil {
186 return cty.DynamicVal, err
187 }
188
189 vals = append(vals, val)
190 }
191
192 return cty.SetVal(vals), nil
193}
194
195func unmarshalMap(dec *msgpack.Decoder, ety cty.Type, path cty.Path) (cty.Value, error) {
196 length, err := dec.DecodeMapLen()
197 if err != nil {
198 return cty.DynamicVal, path.NewErrorf("a map is required")
199 }
200
201 switch {
202 case length < 0:
203 return cty.NullVal(cty.Map(ety)), nil
204 case length == 0:
205 return cty.MapValEmpty(ety), nil
206 }
207
208 vals := make(map[string]cty.Value, length)
209 path = append(path, nil)
210 for i := 0; i < length; i++ {
211 key, err := dec.DecodeString()
212 if err != nil {
213 path[:len(path)-1].NewErrorf("non-string key in map")
214 }
215
216 path[len(path)-1] = cty.IndexStep{
217 Key: cty.StringVal(key),
218 }
219
220 val, err := unmarshal(dec, ety, path)
221 if err != nil {
222 return cty.DynamicVal, err
223 }
224
225 vals[key] = val
226 }
227
228 return cty.MapVal(vals), nil
229}
230
231func unmarshalTuple(dec *msgpack.Decoder, etys []cty.Type, path cty.Path) (cty.Value, error) {
232 length, err := dec.DecodeArrayLen()
233 if err != nil {
234 return cty.DynamicVal, path.NewErrorf("a tuple is required")
235 }
236
237 switch {
238 case length < 0:
239 return cty.NullVal(cty.Tuple(etys)), nil
240 case length == 0:
241 return cty.TupleVal(nil), nil
242 case length != len(etys):
243 return cty.DynamicVal, path.NewErrorf("a tuple of length %d is required", len(etys))
244 }
245
246 vals := make([]cty.Value, 0, length)
247 path = append(path, nil)
248 for i := 0; i < length; i++ {
249 path[len(path)-1] = cty.IndexStep{
250 Key: cty.NumberIntVal(int64(i)),
251 }
252 ety := etys[i]
253
254 val, err := unmarshal(dec, ety, path)
255 if err != nil {
256 return cty.DynamicVal, err
257 }
258
259 vals = append(vals, val)
260 }
261
262 return cty.TupleVal(vals), nil
263}
264
265func unmarshalObject(dec *msgpack.Decoder, atys map[string]cty.Type, path cty.Path) (cty.Value, error) {
266 length, err := dec.DecodeMapLen()
267 if err != nil {
268 return cty.DynamicVal, path.NewErrorf("an object is required")
269 }
270
271 switch {
272 case length < 0:
273 return cty.NullVal(cty.Object(atys)), nil
274 case length == 0:
275 return cty.ObjectVal(nil), nil
276 case length != len(atys):
277 return cty.DynamicVal, path.NewErrorf("an object with %d attributes is required (%d given)",
278 len(atys), length)
279 }
280
281 vals := make(map[string]cty.Value, length)
282 path = append(path, nil)
283 for i := 0; i < length; i++ {
284 key, err := dec.DecodeString()
285 if err != nil {
286 return cty.DynamicVal, path[:len(path)-1].NewErrorf("all keys must be strings")
287 }
288
289 path[len(path)-1] = cty.IndexStep{
290 Key: cty.StringVal(key),
291 }
292 aty, exists := atys[key]
293 if !exists {
294 return cty.DynamicVal, path.NewErrorf("unsupported attribute")
295 }
296
297 val, err := unmarshal(dec, aty, path)
298 if err != nil {
299 return cty.DynamicVal, err
300 }
301
302 vals[key] = val
303 }
304
305 return cty.ObjectVal(vals), nil
306}
307
308func unmarshalDynamic(dec *msgpack.Decoder, path cty.Path) (cty.Value, error) {
309 length, err := dec.DecodeArrayLen()
310 if err != nil {
311 return cty.DynamicVal, path.NewError(err)
312 }
313
314 switch {
315 case length == -1:
316 return cty.NullVal(cty.DynamicPseudoType), nil
317 case length != 2:
318 return cty.DynamicVal, path.NewErrorf(
319 "dynamic value array must have exactly two elements",
320 )
321 }
322
323 typeJSON, err := dec.DecodeBytes()
324 if err != nil {
325 return cty.DynamicVal, path.NewError(err)
326 }
327 var ty cty.Type
328 err = (&ty).UnmarshalJSON(typeJSON)
329 if err != nil {
330 return cty.DynamicVal, path.NewError(err)
331 }
332
333 return unmarshal(dec, ty, path)
334}
diff --git a/vendor/github.com/zclconf/go-cty/cty/object_type.go b/vendor/github.com/zclconf/go-cty/cty/object_type.go
index 2540883..187d387 100644
--- a/vendor/github.com/zclconf/go-cty/cty/object_type.go
+++ b/vendor/github.com/zclconf/go-cty/cty/object_type.go
@@ -51,7 +51,7 @@ func (t typeObject) Equals(other Type) bool {
51 return false 51 return false
52} 52}
53 53
54func (t typeObject) FriendlyName() string { 54func (t typeObject) FriendlyName(mode friendlyTypeNameMode) string {
55 // There isn't really a friendly way to write an object type due to its 55 // There isn't really a friendly way to write an object type due to its
56 // complexity, so we'll just do something English-ish. Callers will 56 // complexity, so we'll just do something English-ish. Callers will
57 // probably want to make some extra effort to avoid ever printing out 57 // probably want to make some extra effort to avoid ever printing out
diff --git a/vendor/github.com/zclconf/go-cty/cty/path.go b/vendor/github.com/zclconf/go-cty/cty/path.go
index 84a9de0..bf1a7c1 100644
--- a/vendor/github.com/zclconf/go-cty/cty/path.go
+++ b/vendor/github.com/zclconf/go-cty/cty/path.go
@@ -15,6 +15,10 @@ import (
15// but callers can also feel free to just produce a slice of PathStep manually 15// but callers can also feel free to just produce a slice of PathStep manually
16// and convert to this type, which may be more appropriate in environments 16// and convert to this type, which may be more appropriate in environments
17// where memory pressure is a concern. 17// where memory pressure is a concern.
18//
19// Although a Path is technically mutable, by convention callers should not
20// mutate a path once it has been built and passed to some other subsystem.
21// Instead, use Copy and then mutate the copy before using it.
18type Path []PathStep 22type Path []PathStep
19 23
20// PathStep represents a single step down into a data structure, as part 24// PathStep represents a single step down into a data structure, as part
@@ -47,6 +51,11 @@ func (p Path) Index(v Value) Path {
47 return ret 51 return ret
48} 52}
49 53
54// IndexPath is a convenience method to start a new Path with an IndexStep.
55func IndexPath(v Value) Path {
56 return Path{}.Index(v)
57}
58
50// GetAttr returns a new Path that is the reciever with a GetAttrStep appended 59// GetAttr returns a new Path that is the reciever with a GetAttrStep appended
51// to the end. 60// to the end.
52// 61//
@@ -62,6 +71,11 @@ func (p Path) GetAttr(name string) Path {
62 return ret 71 return ret
63} 72}
64 73
74// GetAttrPath is a convenience method to start a new Path with a GetAttrStep.
75func GetAttrPath(name string) Path {
76 return Path{}.GetAttr(name)
77}
78
65// Apply applies each of the steps in turn to successive values starting with 79// Apply applies each of the steps in turn to successive values starting with
66// the given value, and returns the result. If any step returns an error, 80// the given value, and returns the result. If any step returns an error,
67// the whole operation returns an error. 81// the whole operation returns an error.
@@ -132,9 +146,13 @@ type IndexStep struct {
132// Apply returns the value resulting from indexing the given value with 146// Apply returns the value resulting from indexing the given value with
133// our key value. 147// our key value.
134func (s IndexStep) Apply(val Value) (Value, error) { 148func (s IndexStep) Apply(val Value) (Value, error) {
149 if val == NilVal || val.IsNull() {
150 return NilVal, errors.New("cannot index a null value")
151 }
152
135 switch s.Key.Type() { 153 switch s.Key.Type() {
136 case Number: 154 case Number:
137 if !val.Type().IsListType() { 155 if !(val.Type().IsListType() || val.Type().IsTupleType()) {
138 return NilVal, errors.New("not a list type") 156 return NilVal, errors.New("not a list type")
139 } 157 }
140 case String: 158 case String:
@@ -170,6 +188,10 @@ type GetAttrStep struct {
170// Apply returns the value of our named attribute from the given value, which 188// Apply returns the value of our named attribute from the given value, which
171// must be of an object type that has a value of that name. 189// must be of an object type that has a value of that name.
172func (s GetAttrStep) Apply(val Value) (Value, error) { 190func (s GetAttrStep) Apply(val Value) (Value, error) {
191 if val == NilVal || val.IsNull() {
192 return NilVal, errors.New("cannot access attributes on a null value")
193 }
194
173 if !val.Type().IsObjectType() { 195 if !val.Type().IsObjectType() {
174 return NilVal, errors.New("not an object type") 196 return NilVal, errors.New("not an object type")
175 } 197 }
diff --git a/vendor/github.com/zclconf/go-cty/cty/path_set.go b/vendor/github.com/zclconf/go-cty/cty/path_set.go
new file mode 100644
index 0000000..f1c892b
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/path_set.go
@@ -0,0 +1,198 @@
1package cty
2
3import (
4 "fmt"
5 "hash/crc64"
6
7 "github.com/zclconf/go-cty/cty/set"
8)
9
10// PathSet represents a set of Path objects. This can be used, for example,
11// to talk about a subset of paths within a value that meet some criteria,
12// without directly modifying the values at those paths.
13type PathSet struct {
14 set set.Set
15}
16
17// NewPathSet creates and returns a PathSet, with initial contents optionally
18// set by the given arguments.
19func NewPathSet(paths ...Path) PathSet {
20 ret := PathSet{
21 set: set.NewSet(pathSetRules{}),
22 }
23
24 for _, path := range paths {
25 ret.Add(path)
26 }
27
28 return ret
29}
30
31// Add inserts a single given path into the set.
32//
33// Paths are immutable after construction by convention. It is particularly
34// important not to mutate a path after it has been placed into a PathSet.
35// If a Path is mutated while in a set, behavior is undefined.
36func (s PathSet) Add(path Path) {
37 s.set.Add(path)
38}
39
40// AddAllSteps is like Add but it also adds all of the steps leading to
41// the given path.
42//
43// For example, if given a path representing "foo.bar", it will add both
44// "foo" and "bar".
45func (s PathSet) AddAllSteps(path Path) {
46 for i := 1; i <= len(path); i++ {
47 s.Add(path[:i])
48 }
49}
50
51// Has returns true if the given path is in the receiving set.
52func (s PathSet) Has(path Path) bool {
53 return s.set.Has(path)
54}
55
56// List makes and returns a slice of all of the paths in the receiving set,
57// in an undefined but consistent order.
58func (s PathSet) List() []Path {
59 if s.Empty() {
60 return nil
61 }
62 ret := make([]Path, 0, s.set.Length())
63 for it := s.set.Iterator(); it.Next(); {
64 ret = append(ret, it.Value().(Path))
65 }
66 return ret
67}
68
69// Remove modifies the receving set to no longer include the given path.
70// If the given path was already absent, this is a no-op.
71func (s PathSet) Remove(path Path) {
72 s.set.Remove(path)
73}
74
75// Empty returns true if the length of the receiving set is zero.
76func (s PathSet) Empty() bool {
77 return s.set.Length() == 0
78}
79
80// Union returns a new set whose contents are the union of the receiver and
81// the given other set.
82func (s PathSet) Union(other PathSet) PathSet {
83 return PathSet{
84 set: s.set.Union(other.set),
85 }
86}
87
88// Intersection returns a new set whose contents are the intersection of the
89// receiver and the given other set.
90func (s PathSet) Intersection(other PathSet) PathSet {
91 return PathSet{
92 set: s.set.Intersection(other.set),
93 }
94}
95
96// Subtract returns a new set whose contents are those from the receiver with
97// any elements of the other given set subtracted.
98func (s PathSet) Subtract(other PathSet) PathSet {
99 return PathSet{
100 set: s.set.Subtract(other.set),
101 }
102}
103
104// SymmetricDifference returns a new set whose contents are the symmetric
105// difference of the receiver and the given other set.
106func (s PathSet) SymmetricDifference(other PathSet) PathSet {
107 return PathSet{
108 set: s.set.SymmetricDifference(other.set),
109 }
110}
111
112// Equal returns true if and only if both the receiver and the given other
113// set contain exactly the same paths.
114func (s PathSet) Equal(other PathSet) bool {
115 if s.set.Length() != other.set.Length() {
116 return false
117 }
118 // Now we know the lengths are the same we only need to test in one
119 // direction whether everything in one is in the other.
120 for it := s.set.Iterator(); it.Next(); {
121 if !other.set.Has(it.Value()) {
122 return false
123 }
124 }
125 return true
126}
127
128var crc64Table = crc64.MakeTable(crc64.ISO)
129
130var indexStepPlaceholder = []byte("#")
131
132// pathSetRules is an implementation of set.Rules from the set package,
133// used internally within PathSet.
134type pathSetRules struct {
135}
136
137func (r pathSetRules) Hash(v interface{}) int {
138 path := v.(Path)
139 hash := crc64.New(crc64Table)
140
141 for _, rawStep := range path {
142 switch step := rawStep.(type) {
143 case GetAttrStep:
144 // (this creates some garbage converting the string name to a
145 // []byte, but that's okay since cty is not designed to be
146 // used in tight loops under memory pressure.)
147 hash.Write([]byte(step.Name))
148 default:
149 // For any other step type we just append a predefined value,
150 // which means that e.g. all indexes into a given collection will
151 // hash to the same value but we assume that collections are
152 // small and thus this won't hurt too much.
153 hash.Write(indexStepPlaceholder)
154 }
155 }
156
157 // We discard half of the hash on 32-bit platforms; collisions just make
158 // our lookups take marginally longer, so not a big deal.
159 return int(hash.Sum64())
160}
161
162func (r pathSetRules) Equivalent(a, b interface{}) bool {
163 aPath := a.(Path)
164 bPath := b.(Path)
165
166 if len(aPath) != len(bPath) {
167 return false
168 }
169
170 for i := range aPath {
171 switch aStep := aPath[i].(type) {
172 case GetAttrStep:
173 bStep, ok := bPath[i].(GetAttrStep)
174 if !ok {
175 return false
176 }
177
178 if aStep.Name != bStep.Name {
179 return false
180 }
181 case IndexStep:
182 bStep, ok := bPath[i].(IndexStep)
183 if !ok {
184 return false
185 }
186
187 eq := aStep.Key.Equals(bStep.Key)
188 if !eq.IsKnown() || eq.False() {
189 return false
190 }
191 default:
192 // Should never happen, since we document PathStep as a closed type.
193 panic(fmt.Errorf("unsupported step type %T", aStep))
194 }
195 }
196
197 return true
198}
diff --git a/vendor/github.com/zclconf/go-cty/cty/primitive_type.go b/vendor/github.com/zclconf/go-cty/cty/primitive_type.go
index b8682dd..7b3d119 100644
--- a/vendor/github.com/zclconf/go-cty/cty/primitive_type.go
+++ b/vendor/github.com/zclconf/go-cty/cty/primitive_type.go
@@ -24,7 +24,7 @@ func (t primitiveType) Equals(other Type) bool {
24 return false 24 return false
25} 25}
26 26
27func (t primitiveType) FriendlyName() string { 27func (t primitiveType) FriendlyName(mode friendlyTypeNameMode) string {
28 switch t.Kind { 28 switch t.Kind {
29 case primitiveTypeBool: 29 case primitiveTypeBool:
30 return "bool" 30 return "bool"
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/iterator.go b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
index f15498e..4a60494 100644
--- a/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
+++ b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
@@ -1,36 +1,15 @@
1package set 1package set
2 2
3type Iterator struct { 3type Iterator struct {
4 bucketIds []int 4 vals []interface{}
5 vals map[int][]interface{} 5 idx int
6 bucketIdx int
7 valIdx int
8} 6}
9 7
10func (it *Iterator) Value() interface{} { 8func (it *Iterator) Value() interface{} {
11 return it.currentBucket()[it.valIdx] 9 return it.vals[it.idx]
12} 10}
13 11
14func (it *Iterator) Next() bool { 12func (it *Iterator) Next() bool {
15 if it.bucketIdx == -1 { 13 it.idx++
16 // init 14 return it.idx < len(it.vals)
17 if len(it.bucketIds) == 0 {
18 return false
19 }
20
21 it.valIdx = 0
22 it.bucketIdx = 0
23 return true
24 }
25
26 it.valIdx++
27 if it.valIdx >= len(it.currentBucket()) {
28 it.valIdx = 0
29 it.bucketIdx++
30 }
31 return it.bucketIdx < len(it.bucketIds)
32}
33
34func (it *Iterator) currentBucket() []interface{} {
35 return it.vals[it.bucketIds[it.bucketIdx]]
36} 15}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/ops.go b/vendor/github.com/zclconf/go-cty/cty/set/ops.go
index 726e707..fd1555f 100644
--- a/vendor/github.com/zclconf/go-cty/cty/set/ops.go
+++ b/vendor/github.com/zclconf/go-cty/cty/set/ops.go
@@ -75,8 +75,12 @@ func (s Set) Copy() Set {
75 return ret 75 return ret
76} 76}
77 77
78// Iterator returns an iterator over values in the set, in an undefined order 78// Iterator returns an iterator over values in the set. If the set's rules
79// that callers should not depend on. 79// implement OrderedRules then the result is ordered per those rules. If
80// no order is provided, or if it is not a total order, then the iteration
81// order is undefined but consistent for a particular version of cty. Do not
82// rely on specific ordering between cty releases unless the rules order is a
83// total order.
80// 84//
81// The pattern for using the returned iterator is: 85// The pattern for using the returned iterator is:
82// 86//
@@ -89,18 +93,11 @@ func (s Set) Copy() Set {
89// Once an iterator has been created for a set, the set *must not* be mutated 93// Once an iterator has been created for a set, the set *must not* be mutated
90// until the iterator is no longer in use. 94// until the iterator is no longer in use.
91func (s Set) Iterator() *Iterator { 95func (s Set) Iterator() *Iterator {
92 // Sort the bucketIds to ensure that we always traverse in a 96 vals := s.Values()
93 // consistent order.
94 bucketIds := make([]int, 0, len(s.vals))
95 for id := range s.vals {
96 bucketIds = append(bucketIds, id)
97 }
98 sort.Ints(bucketIds)
99 97
100 return &Iterator{ 98 return &Iterator{
101 bucketIds: bucketIds, 99 vals: vals,
102 vals: s.vals, 100 idx: -1,
103 bucketIdx: -1,
104 } 101 }
105} 102}
106 103
@@ -113,16 +110,30 @@ func (s Set) EachValue(cb func(interface{})) {
113 } 110 }
114} 111}
115 112
116// Values returns a slice of all of the values in the set in no particular 113// Values returns a slice of all the values in the set. If the set rules have
117// order. This is just a wrapper around EachValue that accumulates the results 114// an order then the result is in that order. If no order is provided or if
118// in a slice for caller convenience. 115// it is not a total order then the result order is undefined, but consistent
119// 116// for a particular set value within a specific release of cty.
120// The returned slice will be nil if there are no values in the set.
121func (s Set) Values() []interface{} { 117func (s Set) Values() []interface{} {
122 var ret []interface{} 118 var ret []interface{}
123 s.EachValue(func(v interface{}) { 119 // Sort the bucketIds to ensure that we always traverse in a
124 ret = append(ret, v) 120 // consistent order.
125 }) 121 bucketIDs := make([]int, 0, len(s.vals))
122 for id := range s.vals {
123 bucketIDs = append(bucketIDs, id)
124 }
125 sort.Ints(bucketIDs)
126
127 for _, bucketID := range bucketIDs {
128 ret = append(ret, s.vals[bucketID]...)
129 }
130
131 if orderRules, ok := s.rules.(OrderedRules); ok {
132 sort.SliceStable(ret, func(i, j int) bool {
133 return orderRules.Less(ret[i], ret[j])
134 })
135 }
136
126 return ret 137 return ret
127} 138}
128 139
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/rules.go b/vendor/github.com/zclconf/go-cty/cty/set/rules.go
index 7200184..51f744b 100644
--- a/vendor/github.com/zclconf/go-cty/cty/set/rules.go
+++ b/vendor/github.com/zclconf/go-cty/cty/set/rules.go
@@ -23,3 +23,21 @@ type Rules interface {
23 // be equivalent. 23 // be equivalent.
24 Equivalent(interface{}, interface{}) bool 24 Equivalent(interface{}, interface{}) bool
25} 25}
26
27// OrderedRules is an extension of Rules that can apply a partial order to
28// element values. When a set's Rules implements OrderedRules an iterator
29// over the set will return items in the order described by the rules.
30//
31// If the given order is not a total order (that is, some pairs of non-equivalent
32// elements do not have a defined order) then the resulting iteration order
33// is undefined but consistent for a particular version of cty. The exact
34// order in that case is not part of the contract and is subject to change
35// between versions.
36type OrderedRules interface {
37 Rules
38
39 // Less returns true if and only if the first argument should sort before
40 // the second argument. If the second argument should sort before the first
41 // or if there is no defined order for the values, return false.
42 Less(interface{}, interface{}) bool
43}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set_internals.go b/vendor/github.com/zclconf/go-cty/cty/set_internals.go
index ce738db..3fd4fb2 100644
--- a/vendor/github.com/zclconf/go-cty/cty/set_internals.go
+++ b/vendor/github.com/zclconf/go-cty/cty/set_internals.go
@@ -6,6 +6,8 @@ import (
6 "hash/crc32" 6 "hash/crc32"
7 "math/big" 7 "math/big"
8 "sort" 8 "sort"
9
10 "github.com/zclconf/go-cty/cty/set"
9) 11)
10 12
11// setRules provides a Rules implementation for the ./set package that 13// setRules provides a Rules implementation for the ./set package that
@@ -19,12 +21,26 @@ type setRules struct {
19 Type Type 21 Type Type
20} 22}
21 23
24var _ set.OrderedRules = setRules{}
25
26// Hash returns a hash value for the receiver that can be used for equality
27// checks where some inaccuracy is tolerable.
28//
29// The hash function is value-type-specific, so it is not meaningful to compare
30// hash results for values of different types.
31//
32// This function is not safe to use for security-related applications, since
33// the hash used is not strong enough.
34func (val Value) Hash() int {
35 hashBytes := makeSetHashBytes(val)
36 return int(crc32.ChecksumIEEE(hashBytes))
37}
38
22func (r setRules) Hash(v interface{}) int { 39func (r setRules) Hash(v interface{}) int {
23 hashBytes := makeSetHashBytes(Value{ 40 return Value{
24 ty: r.Type, 41 ty: r.Type,
25 v: v, 42 v: v,
26 }) 43 }.Hash()
27 return int(crc32.ChecksumIEEE(hashBytes))
28} 44}
29 45
30func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool { 46func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool {
@@ -46,6 +62,60 @@ func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool {
46 return eqv.v == true 62 return eqv.v == true
47} 63}
48 64
65// Less is an implementation of set.OrderedRules so that we can iterate over
66// set elements in a consistent order, where such an order is possible.
67func (r setRules) Less(v1, v2 interface{}) bool {
68 v1v := Value{
69 ty: r.Type,
70 v: v1,
71 }
72 v2v := Value{
73 ty: r.Type,
74 v: v2,
75 }
76
77 if v1v.RawEquals(v2v) { // Easy case: if they are equal then v1 can't be less
78 return false
79 }
80
81 // Null values always sort after non-null values
82 if v2v.IsNull() && !v1v.IsNull() {
83 return true
84 } else if v1v.IsNull() {
85 return false
86 }
87 // Unknown values always sort after known values
88 if v1v.IsKnown() && !v2v.IsKnown() {
89 return true
90 } else if !v1v.IsKnown() {
91 return false
92 }
93
94 switch r.Type {
95 case String:
96 // String values sort lexicographically
97 return v1v.AsString() < v2v.AsString()
98 case Bool:
99 // Weird to have a set of bools, but if we do then false sorts before true.
100 if v2v.True() || !v1v.True() {
101 return true
102 }
103 return false
104 case Number:
105 v1f := v1v.AsBigFloat()
106 v2f := v2v.AsBigFloat()
107 return v1f.Cmp(v2f) < 0
108 default:
109 // No other types have a well-defined ordering, so we just produce a
110 // default consistent-but-undefined ordering then. This situation is
111 // not considered a compatibility constraint; callers should rely only
112 // on the ordering rules for primitive values.
113 v1h := makeSetHashBytes(v1v)
114 v2h := makeSetHashBytes(v2v)
115 return bytes.Compare(v1h, v2h) < 0
116 }
117}
118
49func makeSetHashBytes(val Value) []byte { 119func makeSetHashBytes(val Value) []byte {
50 var buf bytes.Buffer 120 var buf bytes.Buffer
51 appendSetHashBytes(val, &buf) 121 appendSetHashBytes(val, &buf)
diff --git a/vendor/github.com/zclconf/go-cty/cty/set_type.go b/vendor/github.com/zclconf/go-cty/cty/set_type.go
index 952a2d2..cbc3706 100644
--- a/vendor/github.com/zclconf/go-cty/cty/set_type.go
+++ b/vendor/github.com/zclconf/go-cty/cty/set_type.go
@@ -31,8 +31,14 @@ func (t typeSet) Equals(other Type) bool {
31 return t.ElementTypeT.Equals(ot.ElementTypeT) 31 return t.ElementTypeT.Equals(ot.ElementTypeT)
32} 32}
33 33
34func (t typeSet) FriendlyName() string { 34func (t typeSet) FriendlyName(mode friendlyTypeNameMode) string {
35 return "set of " + t.ElementTypeT.FriendlyName() 35 elemName := t.ElementTypeT.friendlyNameMode(mode)
36 if mode == friendlyTypeConstraintName {
37 if t.ElementTypeT == DynamicPseudoType {
38 elemName = "any single type"
39 }
40 }
41 return "set of " + elemName
36} 42}
37 43
38func (t typeSet) ElementType() Type { 44func (t typeSet) ElementType() Type {
diff --git a/vendor/github.com/zclconf/go-cty/cty/tuple_type.go b/vendor/github.com/zclconf/go-cty/cty/tuple_type.go
index b98349e..798cacd 100644
--- a/vendor/github.com/zclconf/go-cty/cty/tuple_type.go
+++ b/vendor/github.com/zclconf/go-cty/cty/tuple_type.go
@@ -44,7 +44,7 @@ func (t typeTuple) Equals(other Type) bool {
44 return false 44 return false
45} 45}
46 46
47func (t typeTuple) FriendlyName() string { 47func (t typeTuple) FriendlyName(mode friendlyTypeNameMode) string {
48 // There isn't really a friendly way to write a tuple type due to its 48 // There isn't really a friendly way to write a tuple type due to its
49 // complexity, so we'll just do something English-ish. Callers will 49 // complexity, so we'll just do something English-ish. Callers will
50 // probably want to make some extra effort to avoid ever printing out 50 // probably want to make some extra effort to avoid ever printing out
diff --git a/vendor/github.com/zclconf/go-cty/cty/type.go b/vendor/github.com/zclconf/go-cty/cty/type.go
index ae5f1c8..730cb98 100644
--- a/vendor/github.com/zclconf/go-cty/cty/type.go
+++ b/vendor/github.com/zclconf/go-cty/cty/type.go
@@ -19,7 +19,7 @@ type typeImpl interface {
19 19
20 // FriendlyName returns a human-friendly *English* name for the given 20 // FriendlyName returns a human-friendly *English* name for the given
21 // type. 21 // type.
22 FriendlyName() string 22 FriendlyName(mode friendlyTypeNameMode) string
23 23
24 // GoString implements the GoStringer interface from package fmt. 24 // GoString implements the GoStringer interface from package fmt.
25 GoString() string 25 GoString() string
@@ -41,7 +41,25 @@ func (t Type) Equals(other Type) bool {
41 41
42// FriendlyName returns a human-friendly *English* name for the given type. 42// FriendlyName returns a human-friendly *English* name for the given type.
43func (t Type) FriendlyName() string { 43func (t Type) FriendlyName() string {
44 return t.typeImpl.FriendlyName() 44 return t.typeImpl.FriendlyName(friendlyTypeName)
45}
46
47// FriendlyNameForConstraint is similar to FriendlyName except that the
48// result is specialized for describing type _constraints_ rather than types
49// themselves. This is more appropriate when reporting that a particular value
50// does not conform to an expected type constraint.
51//
52// In particular, this function uses the term "any type" to refer to
53// cty.DynamicPseudoType, rather than "dynamic" as returned by FriendlyName.
54func (t Type) FriendlyNameForConstraint() string {
55 return t.typeImpl.FriendlyName(friendlyTypeConstraintName)
56}
57
58// friendlyNameMode is an internal combination of the various FriendlyName*
59// variants that just directly takes a mode, for easy passthrough for
60// recursive name construction.
61func (t Type) friendlyNameMode(mode friendlyTypeNameMode) string {
62 return t.typeImpl.FriendlyName(mode)
45} 63}
46 64
47// GoString returns a string approximating how the receiver type would be 65// GoString returns a string approximating how the receiver type would be
@@ -93,3 +111,10 @@ func (t Type) HasDynamicTypes() bool {
93 panic("HasDynamicTypes does not support the given type") 111 panic("HasDynamicTypes does not support the given type")
94 } 112 }
95} 113}
114
115type friendlyTypeNameMode rune
116
117const (
118 friendlyTypeName friendlyTypeNameMode = 'N'
119 friendlyTypeConstraintName friendlyTypeNameMode = 'C'
120)
diff --git a/vendor/github.com/zclconf/go-cty/cty/type_conform.go b/vendor/github.com/zclconf/go-cty/cty/type_conform.go
index b417dc7..476eeea 100644
--- a/vendor/github.com/zclconf/go-cty/cty/type_conform.go
+++ b/vendor/github.com/zclconf/go-cty/cty/type_conform.go
@@ -50,23 +50,20 @@ func testConformance(given Type, want Type, path Path, errs *[]error) {
50 givenAttrs := given.AttributeTypes() 50 givenAttrs := given.AttributeTypes()
51 wantAttrs := want.AttributeTypes() 51 wantAttrs := want.AttributeTypes()
52 52
53 if len(givenAttrs) != len(wantAttrs) { 53 for k := range givenAttrs {
54 // Something is missing from one of them. 54 if _, exists := wantAttrs[k]; !exists {
55 for k := range givenAttrs { 55 *errs = append(
56 if _, exists := wantAttrs[k]; !exists { 56 *errs,
57 *errs = append( 57 errorf(path, "unsupported attribute %q", k),
58 *errs, 58 )
59 errorf(path, "unsupported attribute %q", k),
60 )
61 }
62 } 59 }
63 for k := range wantAttrs { 60 }
64 if _, exists := givenAttrs[k]; !exists { 61 for k := range wantAttrs {
65 *errs = append( 62 if _, exists := givenAttrs[k]; !exists {
66 *errs, 63 *errs = append(
67 errorf(path, "missing required attribute %q", k), 64 *errs,
68 ) 65 errorf(path, "missing required attribute %q", k),
69 } 66 )
70 } 67 }
71 } 68 }
72 69
diff --git a/vendor/github.com/zclconf/go-cty/cty/unknown.go b/vendor/github.com/zclconf/go-cty/cty/unknown.go
index 9f6fce9..e54179e 100644
--- a/vendor/github.com/zclconf/go-cty/cty/unknown.go
+++ b/vendor/github.com/zclconf/go-cty/cty/unknown.go
@@ -54,8 +54,13 @@ func (t pseudoTypeDynamic) Equals(other Type) bool {
54 return ok 54 return ok
55} 55}
56 56
57func (t pseudoTypeDynamic) FriendlyName() string { 57func (t pseudoTypeDynamic) FriendlyName(mode friendlyTypeNameMode) string {
58 return "dynamic" 58 switch mode {
59 case friendlyTypeConstraintName:
60 return "any type"
61 default:
62 return "dynamic"
63 }
59} 64}
60 65
61func (t pseudoTypeDynamic) GoString() string { 66func (t pseudoTypeDynamic) GoString() string {
diff --git a/vendor/github.com/zclconf/go-cty/cty/unknown_as_null.go b/vendor/github.com/zclconf/go-cty/cty/unknown_as_null.go
new file mode 100644
index 0000000..ba92647
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/unknown_as_null.go
@@ -0,0 +1,64 @@
1package cty
2
3// UnknownAsNull returns a value of the same type as the given value but
4// with any unknown values (including nested values) replaced with null
5// values of the same type.
6//
7// This can be useful if a result is to be serialized in a format that can't
8// represent unknowns, such as JSON, as long as the caller does not need to
9// retain the unknown value information.
10func UnknownAsNull(val Value) Value {
11 ty := val.Type()
12 switch {
13 case val.IsNull():
14 return val
15 case !val.IsKnown():
16 return NullVal(ty)
17 case ty.IsListType() || ty.IsTupleType() || ty.IsSetType():
18 length := val.LengthInt()
19 if length == 0 {
20 // If there are no elements then we can't have unknowns
21 return val
22 }
23 vals := make([]Value, 0, length)
24 it := val.ElementIterator()
25 for it.Next() {
26 _, v := it.Element()
27 vals = append(vals, UnknownAsNull(v))
28 }
29 switch {
30 case ty.IsListType():
31 return ListVal(vals)
32 case ty.IsTupleType():
33 return TupleVal(vals)
34 default:
35 return SetVal(vals)
36 }
37 case ty.IsMapType() || ty.IsObjectType():
38 var length int
39 switch {
40 case ty.IsMapType():
41 length = val.LengthInt()
42 default:
43 length = len(val.Type().AttributeTypes())
44 }
45 if length == 0 {
46 // If there are no elements then we can't have unknowns
47 return val
48 }
49 vals := make(map[string]Value, length)
50 it := val.ElementIterator()
51 for it.Next() {
52 k, v := it.Element()
53 vals[k.AsString()] = UnknownAsNull(v)
54 }
55 switch {
56 case ty.IsMapType():
57 return MapVal(vals)
58 default:
59 return ObjectVal(vals)
60 }
61 }
62
63 return val
64}
diff --git a/vendor/github.com/zclconf/go-cty/cty/value_init.go b/vendor/github.com/zclconf/go-cty/cty/value_init.go
index 495a83e..3deeba3 100644
--- a/vendor/github.com/zclconf/go-cty/cty/value_init.go
+++ b/vendor/github.com/zclconf/go-cty/cty/value_init.go
@@ -30,6 +30,44 @@ func NumberVal(v *big.Float) Value {
30 } 30 }
31} 31}
32 32
33// ParseNumberVal returns a Value of type number produced by parsing the given
34// string as a decimal real number. To ensure that two identical strings will
35// always produce an equal number, always use this function to derive a number
36// from a string; it will ensure that the precision and rounding mode for the
37// internal big decimal is configured in a consistent way.
38//
39// If the given string cannot be parsed as a number, the returned error has
40// the message "a number is required", making it suitable to return to an
41// end-user to signal a type conversion error.
42//
43// If the given string contains a number that becomes a recurring fraction
44// when expressed in binary then it will be truncated to have a 512-bit
45// mantissa. Note that this is a higher precision than that of a float64,
46// so coverting the same decimal number first to float64 and then calling
47// NumberFloatVal will not produce an equal result; the conversion first
48// to float64 will round the mantissa to fewer than 512 bits.
49func ParseNumberVal(s string) (Value, error) {
50 // Base 10, precision 512, and rounding to nearest even is the standard
51 // way to handle numbers arriving as strings.
52 f, _, err := big.ParseFloat(s, 10, 512, big.ToNearestEven)
53 if err != nil {
54 return NilVal, fmt.Errorf("a number is required")
55 }
56 return NumberVal(f), nil
57}
58
59// MustParseNumberVal is like ParseNumberVal but it will panic in case of any
60// error. It can be used during initialization or any other situation where
61// the given string is a constant or otherwise known to be correct by the
62// caller.
63func MustParseNumberVal(s string) Value {
64 ret, err := ParseNumberVal(s)
65 if err != nil {
66 panic(err)
67 }
68 return ret
69}
70
33// NumberIntVal returns a Value of type Number whose internal value is equal 71// NumberIntVal returns a Value of type Number whose internal value is equal
34// to the given integer. 72// to the given integer.
35func NumberIntVal(v int64) Value { 73func NumberIntVal(v int64) Value {
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 }