aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty
diff options
context:
space:
mode:
authorAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
committerAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
commit15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch)
tree255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/zclconf/go-cty/cty
parent07971ca38143c5faf951d152fba370ddcbe26ad5 (diff)
downloadterraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.gz
terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.zst
terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.zip
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
Updated via: go get github.com/hashicorp/terraform@sdk-v0.11-with-go-modules and go mod tidy
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/capsule.go89
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/collection.go34
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/compare_types.go165
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion.go120
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go226
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go33
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go50
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/doc.go15
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/public.go83
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/sort_types.go69
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/unify.go66
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/doc.go18
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/element_iterator.go191
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/error.go55
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/argument.go50
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/doc.go6
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/error.go50
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/function.go291
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go73
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go112
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go140
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go93
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go13
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go496
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go358
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl182
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go107
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go72
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go428
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go130
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go195
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go234
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go31
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gob.go125
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/doc.go7
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go43
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/in.go528
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/out.go705
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go108
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/helper.go99
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json.go176
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/doc.go11
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/marshal.go189
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/simple.go41
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/type.go23
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/type_implied.go171
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go459
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/json/value.go65
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/list_type.go68
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/map_type.go68
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/null.go14
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/object_type.go135
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/path.go186
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/primitive_type.go122
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/gob.go76
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/iterator.go36
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/ops.go199
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/rules.go25
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set/set.go62
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set_helper.go126
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set_internals.go146
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/set_type.go66
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/tuple_type.go121
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/type.go95
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/type_conform.go142
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/types_to_register.go57
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/unknown.go79
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/value.go98
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/value_init.go276
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/value_ops.go1071
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/walk.go182
71 files changed, 10475 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/capsule.go b/vendor/github.com/zclconf/go-cty/cty/capsule.go
new file mode 100644
index 0000000..4fce92a
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/capsule.go
@@ -0,0 +1,89 @@
1package cty
2
3import (
4 "fmt"
5 "reflect"
6)
7
8type capsuleType struct {
9 typeImplSigil
10 Name string
11 GoType reflect.Type
12}
13
14func (t *capsuleType) Equals(other Type) bool {
15 if otherP, ok := other.typeImpl.(*capsuleType); ok {
16 // capsule types compare by pointer identity
17 return otherP == t
18 }
19 return false
20}
21
22func (t *capsuleType) FriendlyName() string {
23 return t.Name
24}
25
26func (t *capsuleType) GoString() string {
27 // To get a useful representation of our native type requires some
28 // shenanigans.
29 victimVal := reflect.Zero(t.GoType)
30 return fmt.Sprintf("cty.Capsule(%q, reflect.TypeOf(%#v))", t.Name, victimVal.Interface())
31}
32
33// Capsule creates a new Capsule type.
34//
35// A Capsule type is a special type that can be used to transport arbitrary
36// Go native values of a given type through the cty type system. A language
37// that uses cty as its type system might, for example, provide functions
38// that return capsule-typed values and then other functions that operate
39// on those values.
40//
41// From cty's perspective, Capsule types have a few interesting characteristics,
42// described in the following paragraphs.
43//
44// Each capsule type has an associated Go native type that it is able to
45// transport. Capsule types compare by identity, so each call to the
46// Capsule function creates an entirely-distinct cty Type, even if two calls
47// use the same native type.
48//
49// Each capsule-typed value contains a pointer to a value of the given native
50// type. A capsule-typed value supports no operations except equality, and
51// equality is implemented by pointer identity of the encapsulated pointer.
52//
53// The given name is used as the new type's "friendly name". This can be any
54// string in principle, but will usually be a short, all-lowercase name aimed
55// at users of the embedding language (i.e. not mention Go-specific details)
56// and will ideally not create ambiguity with any predefined cty type.
57//
58// Capsule types are never introduced by any standard cty operation, so a
59// calling application opts in to including them within its own type system
60// by creating them and introducing them via its own functions. At that point,
61// the application is responsible for dealing with any capsule-typed values
62// that might be returned.
63func Capsule(name string, nativeType reflect.Type) Type {
64 return Type{
65 &capsuleType{
66 Name: name,
67 GoType: nativeType,
68 },
69 }
70}
71
72// IsCapsuleType returns true if this type is a capsule type, as created
73// by cty.Capsule .
74func (t Type) IsCapsuleType() bool {
75 _, ok := t.typeImpl.(*capsuleType)
76 return ok
77}
78
79// EncapsulatedType returns the encapsulated native type of a capsule type,
80// or panics if the receiver is not a Capsule type.
81//
82// Is IsCapsuleType to determine if this method is safe to call.
83func (t Type) EncapsulatedType() reflect.Type {
84 impl, ok := t.typeImpl.(*capsuleType)
85 if !ok {
86 panic("not a capsule type")
87 }
88 return impl.GoType
89}
diff --git a/vendor/github.com/zclconf/go-cty/cty/collection.go b/vendor/github.com/zclconf/go-cty/cty/collection.go
new file mode 100644
index 0000000..ab3919b
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/collection.go
@@ -0,0 +1,34 @@
1package cty
2
3import (
4 "errors"
5)
6
7type collectionTypeImpl interface {
8 ElementType() Type
9}
10
11// IsCollectionType returns true if the given type supports the operations
12// that are defined for all collection types.
13func (t Type) IsCollectionType() bool {
14 _, ok := t.typeImpl.(collectionTypeImpl)
15 return ok
16}
17
18// ElementType returns the element type of the receiver if it is a collection
19// type, or panics if it is not. Use IsCollectionType first to test whether
20// this method will succeed.
21func (t Type) ElementType() Type {
22 if ct, ok := t.typeImpl.(collectionTypeImpl); ok {
23 return ct.ElementType()
24 }
25 panic(errors.New("not a collection type"))
26}
27
28// ElementCallback is a callback type used for iterating over elements of
29// collections and attributes of objects.
30//
31// The types of key and value depend on what type is being iterated over.
32// Return true to stop iterating after the current element, or false to
33// continue iterating.
34type ElementCallback func(key Value, val Value) (stop bool)
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/compare_types.go b/vendor/github.com/zclconf/go-cty/cty/convert/compare_types.go
new file mode 100644
index 0000000..d84f6ac
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/compare_types.go
@@ -0,0 +1,165 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// compareTypes implements a preference order for unification.
8//
9// The result of this method is not useful for anything other than unification
10// preferences, since it assumes that the caller will verify that any suggested
11// conversion is actually possible and it is thus able to to make certain
12// optimistic assumptions.
13func compareTypes(a cty.Type, b cty.Type) int {
14
15 // DynamicPseudoType always has lowest preference, because anything can
16 // convert to it (it acts as a placeholder for "any type") and we want
17 // to optimistically assume that any dynamics will converge on matching
18 // their neighbors.
19 if a == cty.DynamicPseudoType || b == cty.DynamicPseudoType {
20 if a != cty.DynamicPseudoType {
21 return -1
22 }
23 if b != cty.DynamicPseudoType {
24 return 1
25 }
26 return 0
27 }
28
29 if a.IsPrimitiveType() && b.IsPrimitiveType() {
30 // String is a supertype of all primitive types, because we can
31 // represent all primitive values as specially-formatted strings.
32 if a == cty.String || b == cty.String {
33 if a != cty.String {
34 return 1
35 }
36 if b != cty.String {
37 return -1
38 }
39 return 0
40 }
41 }
42
43 if a.IsListType() && b.IsListType() {
44 return compareTypes(a.ElementType(), b.ElementType())
45 }
46 if a.IsSetType() && b.IsSetType() {
47 return compareTypes(a.ElementType(), b.ElementType())
48 }
49 if a.IsMapType() && b.IsMapType() {
50 return compareTypes(a.ElementType(), b.ElementType())
51 }
52
53 // From this point on we may have swapped the two items in order to
54 // simplify our cases. Therefore any non-zero return after this point
55 // must be multiplied by "swap" to potentially invert the return value
56 // if needed.
57 swap := 1
58 switch {
59 case a.IsTupleType() && b.IsListType():
60 fallthrough
61 case a.IsObjectType() && b.IsMapType():
62 fallthrough
63 case a.IsSetType() && b.IsTupleType():
64 fallthrough
65 case a.IsSetType() && b.IsListType():
66 a, b = b, a
67 swap = -1
68 }
69
70 if b.IsSetType() && (a.IsTupleType() || a.IsListType()) {
71 // We'll just optimistically assume that the element types are
72 // unifyable/convertible, and let a second recursive pass
73 // figure out how to make that so.
74 return -1 * swap
75 }
76
77 if a.IsListType() && b.IsTupleType() {
78 // We'll just optimistically assume that the tuple's element types
79 // can be unified into something compatible with the list's element
80 // type.
81 return -1 * swap
82 }
83
84 if a.IsMapType() && b.IsObjectType() {
85 // We'll just optimistically assume that the object's attribute types
86 // can be unified into something compatible with the map's element
87 // type.
88 return -1 * swap
89 }
90
91 // For object and tuple types, comparing two types doesn't really tell
92 // the whole story because it may be possible to construct a new type C
93 // that is the supertype of both A and B by unifying each attribute/element
94 // separately. That possibility is handled by Unify as a follow-up if
95 // type sorting is insufficient to produce a valid result.
96 //
97 // Here we will take care of the simple possibilities where no new type
98 // is needed.
99 if a.IsObjectType() && b.IsObjectType() {
100 atysA := a.AttributeTypes()
101 atysB := b.AttributeTypes()
102
103 if len(atysA) != len(atysB) {
104 return 0
105 }
106
107 hasASuper := false
108 hasBSuper := false
109 for k := range atysA {
110 if _, has := atysB[k]; !has {
111 return 0
112 }
113
114 cmp := compareTypes(atysA[k], atysB[k])
115 if cmp < 0 {
116 hasASuper = true
117 } else if cmp > 0 {
118 hasBSuper = true
119 }
120 }
121
122 switch {
123 case hasASuper && hasBSuper:
124 return 0
125 case hasASuper:
126 return -1 * swap
127 case hasBSuper:
128 return 1 * swap
129 default:
130 return 0
131 }
132 }
133 if a.IsTupleType() && b.IsTupleType() {
134 etysA := a.TupleElementTypes()
135 etysB := b.TupleElementTypes()
136
137 if len(etysA) != len(etysB) {
138 return 0
139 }
140
141 hasASuper := false
142 hasBSuper := false
143 for i := range etysA {
144 cmp := compareTypes(etysA[i], etysB[i])
145 if cmp < 0 {
146 hasASuper = true
147 } else if cmp > 0 {
148 hasBSuper = true
149 }
150 }
151
152 switch {
153 case hasASuper && hasBSuper:
154 return 0
155 case hasASuper:
156 return -1 * swap
157 case hasBSuper:
158 return 1 * swap
159 default:
160 return 0
161 }
162 }
163
164 return 0
165}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
new file mode 100644
index 0000000..7bfcc08
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
@@ -0,0 +1,120 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// conversion is an internal variant of Conversion that carries around
8// a cty.Path to be used in error responses.
9type conversion func(cty.Value, cty.Path) (cty.Value, error)
10
11func getConversion(in cty.Type, out cty.Type, unsafe bool) conversion {
12 conv := getConversionKnown(in, out, unsafe)
13 if conv == nil {
14 return nil
15 }
16
17 // Wrap the conversion in some standard checks that we don't want to
18 // have to repeat in every conversion function.
19 return func(in cty.Value, path cty.Path) (cty.Value, error) {
20 if !in.IsKnown() {
21 return cty.UnknownVal(out), nil
22 }
23 if in.IsNull() {
24 // We'll pass through nulls, albeit type converted, and let
25 // the caller deal with whatever handling they want to do in
26 // case null values are considered valid in some applications.
27 return cty.NullVal(out), nil
28 }
29
30 return conv(in, path)
31 }
32}
33
34func getConversionKnown(in cty.Type, out cty.Type, unsafe bool) conversion {
35 switch {
36
37 case out == cty.DynamicPseudoType:
38 // Conversion *to* DynamicPseudoType means that the caller wishes
39 // to allow any type in this position, so we'll produce a do-nothing
40 // conversion that just passes through the value as-is.
41 return dynamicPassthrough
42
43 case unsafe && in == cty.DynamicPseudoType:
44 // Conversion *from* DynamicPseudoType means that we have a value
45 // whose type isn't yet known during type checking. For these we will
46 // assume that conversion will succeed and deal with any errors that
47 // result (which is why we can only do this when "unsafe" is set).
48 return dynamicFixup(out)
49
50 case in.IsPrimitiveType() && out.IsPrimitiveType():
51 conv := primitiveConversionsSafe[in][out]
52 if conv != nil {
53 return conv
54 }
55 if unsafe {
56 return primitiveConversionsUnsafe[in][out]
57 }
58 return nil
59
60 case out.IsListType() && (in.IsListType() || in.IsSetType()):
61 inEty := in.ElementType()
62 outEty := out.ElementType()
63 if inEty.Equals(outEty) {
64 // This indicates that we're converting from list to set with
65 // the same element type, so we don't need an element converter.
66 return conversionCollectionToList(outEty, nil)
67 }
68
69 convEty := getConversion(inEty, outEty, unsafe)
70 if convEty == nil {
71 return nil
72 }
73 return conversionCollectionToList(outEty, convEty)
74
75 case out.IsSetType() && (in.IsListType() || in.IsSetType()):
76 if in.IsListType() && !unsafe {
77 // Conversion from list to map is unsafe because it will lose
78 // information: the ordering will not be preserved, and any
79 // duplicate elements will be conflated.
80 return nil
81 }
82 inEty := in.ElementType()
83 outEty := out.ElementType()
84 convEty := getConversion(inEty, outEty, unsafe)
85 if inEty.Equals(outEty) {
86 // This indicates that we're converting from set to list with
87 // the same element type, so we don't need an element converter.
88 return conversionCollectionToSet(outEty, nil)
89 }
90
91 if convEty == nil {
92 return nil
93 }
94 return conversionCollectionToSet(outEty, convEty)
95
96 case out.IsListType() && in.IsTupleType():
97 outEty := out.ElementType()
98 return conversionTupleToList(in, outEty, unsafe)
99
100 case out.IsMapType() && in.IsObjectType():
101 outEty := out.ElementType()
102 return conversionObjectToMap(in, outEty, unsafe)
103
104 default:
105 return nil
106
107 }
108}
109
110// retConversion wraps a conversion (internal type) so it can be returned
111// as a Conversion (public type).
112func retConversion(conv conversion) Conversion {
113 if conv == nil {
114 return nil
115 }
116
117 return func(in cty.Value) (cty.Value, error) {
118 return conv(in, cty.Path(nil))
119 }
120}
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
new file mode 100644
index 0000000..eace85d
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
@@ -0,0 +1,226 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// conversionCollectionToList returns a conversion that will apply the given
8// conversion to all of the elements of a collection (something that supports
9// ForEachElement and LengthInt) and then returns the result as a list.
10//
11// "conv" can be nil if the elements are expected to already be of the
12// correct type and just need to be re-wrapped into a list. (For example,
13// if we're converting from a set into a list of the same element type.)
14func conversionCollectionToList(ety cty.Type, conv conversion) conversion {
15 return func(val cty.Value, path cty.Path) (cty.Value, error) {
16 elems := make([]cty.Value, 0, val.LengthInt())
17 i := int64(0)
18 path = append(path, nil)
19 it := val.ElementIterator()
20 for it.Next() {
21 _, val := it.Element()
22 var err error
23
24 path[len(path)-1] = cty.IndexStep{
25 Key: cty.NumberIntVal(i),
26 }
27
28 if conv != nil {
29 val, err = conv(val, path)
30 if err != nil {
31 return cty.NilVal, err
32 }
33 }
34 elems = append(elems, val)
35
36 i++
37 }
38
39 if len(elems) == 0 {
40 return cty.ListValEmpty(ety), nil
41 }
42
43 return cty.ListVal(elems), nil
44 }
45}
46
47// conversionCollectionToSet returns a conversion that will apply the given
48// conversion to all of the elements of a collection (something that supports
49// ForEachElement and LengthInt) and then returns the result as a set.
50//
51// "conv" can be nil if the elements are expected to already be of the
52// correct type and just need to be re-wrapped into a set. (For example,
53// if we're converting from a list into a set of the same element type.)
54func conversionCollectionToSet(ety cty.Type, conv conversion) conversion {
55 return func(val cty.Value, path cty.Path) (cty.Value, error) {
56 elems := make([]cty.Value, 0, val.LengthInt())
57 i := int64(0)
58 path = append(path, nil)
59 it := val.ElementIterator()
60 for it.Next() {
61 _, val := it.Element()
62 var err error
63
64 path[len(path)-1] = cty.IndexStep{
65 Key: cty.NumberIntVal(i),
66 }
67
68 if conv != nil {
69 val, err = conv(val, path)
70 if err != nil {
71 return cty.NilVal, err
72 }
73 }
74 elems = append(elems, val)
75
76 i++
77 }
78
79 if len(elems) == 0 {
80 return cty.SetValEmpty(ety), nil
81 }
82
83 return cty.SetVal(elems), nil
84 }
85}
86
87// conversionTupleToList returns a conversion that will take a value of the
88// given tuple type and return a list of the given element type.
89//
90// Will panic if the given tupleType isn't actually a tuple type.
91func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) conversion {
92 tupleEtys := tupleType.TupleElementTypes()
93
94 if len(tupleEtys) == 0 {
95 // Empty tuple short-circuit
96 return func(val cty.Value, path cty.Path) (cty.Value, error) {
97 return cty.ListValEmpty(listEty), nil
98 }
99 }
100
101 if listEty == cty.DynamicPseudoType {
102 // This is a special case where the caller wants us to find
103 // a suitable single type that all elements can convert to, if
104 // possible.
105 listEty, _ = unify(tupleEtys, unsafe)
106 if listEty == cty.NilType {
107 return nil
108 }
109 }
110
111 elemConvs := make([]conversion, len(tupleEtys))
112 for i, tupleEty := range tupleEtys {
113 if tupleEty.Equals(listEty) {
114 // no conversion required
115 continue
116 }
117
118 elemConvs[i] = getConversion(tupleEty, listEty, unsafe)
119 if elemConvs[i] == nil {
120 // If any of our element conversions are impossible, then the our
121 // whole conversion is impossible.
122 return nil
123 }
124 }
125
126 // If we fall out here then a conversion is possible, using the
127 // element conversions in elemConvs
128 return func(val cty.Value, path cty.Path) (cty.Value, error) {
129 elems := make([]cty.Value, 0, len(elemConvs))
130 path = append(path, nil)
131 i := int64(0)
132 it := val.ElementIterator()
133 for it.Next() {
134 _, val := it.Element()
135 var err error
136
137 path[len(path)-1] = cty.IndexStep{
138 Key: cty.NumberIntVal(i),
139 }
140
141 conv := elemConvs[i]
142 if conv != nil {
143 val, err = conv(val, path)
144 if err != nil {
145 return cty.NilVal, err
146 }
147 }
148 elems = append(elems, val)
149
150 i++
151 }
152
153 return cty.ListVal(elems), nil
154 }
155}
156
157// conversionObjectToMap returns a conversion that will take a value of the
158// given object type and return a map of the given element type.
159//
160// Will panic if the given objectType isn't actually an object type.
161func conversionObjectToMap(objectType cty.Type, mapEty cty.Type, unsafe bool) conversion {
162 objectAtys := objectType.AttributeTypes()
163
164 if len(objectAtys) == 0 {
165 // Empty object short-circuit
166 return func(val cty.Value, path cty.Path) (cty.Value, error) {
167 return cty.MapValEmpty(mapEty), nil
168 }
169 }
170
171 if mapEty == cty.DynamicPseudoType {
172 // This is a special case where the caller wants us to find
173 // a suitable single type that all elements can convert to, if
174 // possible.
175 objectAtysList := make([]cty.Type, 0, len(objectAtys))
176 for _, aty := range objectAtys {
177 objectAtysList = append(objectAtysList, aty)
178 }
179 mapEty, _ = unify(objectAtysList, unsafe)
180 if mapEty == cty.NilType {
181 return nil
182 }
183 }
184
185 elemConvs := make(map[string]conversion, len(objectAtys))
186 for name, objectAty := range objectAtys {
187 if objectAty.Equals(mapEty) {
188 // no conversion required
189 continue
190 }
191
192 elemConvs[name] = getConversion(objectAty, mapEty, unsafe)
193 if elemConvs[name] == nil {
194 // If any of our element conversions are impossible, then the our
195 // whole conversion is impossible.
196 return nil
197 }
198 }
199
200 // If we fall out here then a conversion is possible, using the
201 // element conversions in elemConvs
202 return func(val cty.Value, path cty.Path) (cty.Value, error) {
203 elems := make(map[string]cty.Value, len(elemConvs))
204 path = append(path, nil)
205 it := val.ElementIterator()
206 for it.Next() {
207 name, val := it.Element()
208 var err error
209
210 path[len(path)-1] = cty.IndexStep{
211 Key: name,
212 }
213
214 conv := elemConvs[name.AsString()]
215 if conv != nil {
216 val, err = conv(val, path)
217 if err != nil {
218 return cty.NilVal, err
219 }
220 }
221 elems[name.AsString()] = val
222 }
223
224 return cty.MapVal(elems), nil
225 }
226}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go
new file mode 100644
index 0000000..4d19cf6
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go
@@ -0,0 +1,33 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// dynamicFixup deals with just-in-time conversions of values that were
8// input-typed as cty.DynamicPseudoType during analysis, ensuring that
9// we end up with the desired output type once the value is known, or
10// failing with an error if that is not possible.
11//
12// This is in the spirit of the cty philosophy of optimistically assuming that
13// DynamicPseudoType values will become the intended value eventually, and
14// dealing with any inconsistencies during final evaluation.
15func dynamicFixup(wantType cty.Type) conversion {
16 return func(in cty.Value, path cty.Path) (cty.Value, error) {
17 ret, err := Convert(in, wantType)
18 if err != nil {
19 // Re-wrap this error so that the returned path is relative
20 // to the caller's original value, rather than relative to our
21 // conversion value here.
22 return cty.NilVal, path.NewError(err)
23 }
24 return ret, nil
25 }
26}
27
28// dynamicPassthrough is an identity conversion that is used when the
29// target type is DynamicPseudoType, indicating that the caller doesn't care
30// which type is returned.
31func dynamicPassthrough(in cty.Value, path cty.Path) (cty.Value, error) {
32 return in, nil
33}
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
new file mode 100644
index 0000000..e563ee3
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go
@@ -0,0 +1,50 @@
1package convert
2
3import (
4 "math/big"
5
6 "github.com/zclconf/go-cty/cty"
7)
8
9var stringTrue = cty.StringVal("true")
10var stringFalse = cty.StringVal("false")
11
12var primitiveConversionsSafe = map[cty.Type]map[cty.Type]conversion{
13 cty.Number: {
14 cty.String: func(val cty.Value, path cty.Path) (cty.Value, error) {
15 f := val.AsBigFloat()
16 return cty.StringVal(f.Text('f', -1)), nil
17 },
18 },
19 cty.Bool: {
20 cty.String: func(val cty.Value, path cty.Path) (cty.Value, error) {
21 if val.True() {
22 return stringTrue, nil
23 } else {
24 return stringFalse, nil
25 }
26 },
27 },
28}
29
30var primitiveConversionsUnsafe = map[cty.Type]map[cty.Type]conversion{
31 cty.String: {
32 cty.Number: func(val cty.Value, path cty.Path) (cty.Value, error) {
33 f, _, err := big.ParseFloat(val.AsString(), 10, 512, big.ToNearestEven)
34 if err != nil {
35 return cty.NilVal, path.NewErrorf("a number is required")
36 }
37 return cty.NumberVal(f), nil
38 },
39 cty.Bool: func(val cty.Value, path cty.Path) (cty.Value, error) {
40 switch val.AsString() {
41 case "true", "1":
42 return cty.True, nil
43 case "false", "0":
44 return cty.False, nil
45 default:
46 return cty.NilVal, path.NewErrorf("a bool is required")
47 }
48 },
49 },
50}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/doc.go b/vendor/github.com/zclconf/go-cty/cty/convert/doc.go
new file mode 100644
index 0000000..2037299
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/doc.go
@@ -0,0 +1,15 @@
1// Package convert contains some routines for converting between cty types.
2// The intent of providing this package is to encourage applications using
3// cty to have consistent type conversion behavior for maximal interoperability
4// when Values pass from one application to another.
5//
6// The conversions are categorized into two categories. "Safe" conversions are
7// ones that are guaranteed to succeed if given a non-null value of the
8// appropriate source type. "Unsafe" conversions, on the other hand, are valid
9// for only a subset of input values, and thus may fail with an error when
10// called for values outside of that valid subset.
11//
12// The functions whose names end in Unsafe support all of the conversions that
13// are supported by the corresponding functions whose names do not have that
14// suffix, and then additional unsafe conversions as well.
15package convert
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/public.go b/vendor/github.com/zclconf/go-cty/cty/convert/public.go
new file mode 100644
index 0000000..55f44ae
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/public.go
@@ -0,0 +1,83 @@
1package convert
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7)
8
9// This file contains the public interface of this package, which is intended
10// to be a small, convenient interface designed for easy integration into
11// a hypothetical language type checker and interpreter.
12
13// Conversion is a named function type representing a conversion from a
14// value of one type to a value of another type.
15//
16// The source type for a conversion is always the source type given to
17// the function that returned the Conversion, but there is no way to recover
18// that from a Conversion value itself. If a Conversion is given a value
19// that is not of its expected type (with the exception of DynamicPseudoType,
20// which is always supported) then the function may panic or produce undefined
21// results.
22type Conversion func(in cty.Value) (out cty.Value, err error)
23
24// GetConversion returns a Conversion between the given in and out Types if
25// a safe one is available, or returns nil otherwise.
26func GetConversion(in cty.Type, out cty.Type) Conversion {
27 return retConversion(getConversion(in, out, false))
28}
29
30// GetConversionUnsafe returns a Conversion between the given in and out Types
31// if either a safe or unsafe one is available, or returns nil otherwise.
32func GetConversionUnsafe(in cty.Type, out cty.Type) Conversion {
33 return retConversion(getConversion(in, out, true))
34}
35
36// Convert returns the result of converting the given value to the given type
37// if an safe or unsafe conversion is available, or returns an error if such a
38// conversion is impossible.
39//
40// This is a convenience wrapper around calling GetConversionUnsafe and then
41// immediately passing the given value to the resulting function.
42func Convert(in cty.Value, want cty.Type) (cty.Value, error) {
43 if in.Type().Equals(want) {
44 return in, nil
45 }
46
47 conv := GetConversionUnsafe(in.Type(), want)
48 if conv == nil {
49 return cty.NilVal, fmt.Errorf("incorrect type; %s required", want.FriendlyName())
50 }
51 return conv(in)
52}
53
54// Unify attempts to find the most general type that can be converted from
55// all of the given types. If this is possible, that type is returned along
56// with a slice of necessary conversions for some of the given types.
57//
58// If no common supertype can be found, this function returns cty.NilType and
59// a nil slice.
60//
61// If a common supertype *can* be found, the returned slice will always be
62// non-nil and will contain a non-nil conversion for each given type that
63// needs to be converted, with indices corresponding to the input slice.
64// Any given type that does *not* need conversion (because it is already of
65// the appropriate type) will have a nil Conversion.
66//
67// cty.DynamicPseudoType is, as usual, a special case. If the given type list
68// contains a mixture of dynamic and non-dynamic types, the dynamic types are
69// disregarded for type selection and a conversion is returned for them that
70// will attempt a late conversion of the given value to the target type,
71// failing with a conversion error if the eventual concrete type is not
72// compatible. If *all* given types are DynamicPseudoType, or in the
73// degenerate case of an empty slice of types, the returned type is itself
74// cty.DynamicPseudoType and no conversions are attempted.
75func Unify(types []cty.Type) (cty.Type, []Conversion) {
76 return unify(types, false)
77}
78
79// UnifyUnsafe is the same as Unify except that it may return unsafe
80// conversions in situations where a safe conversion isn't also available.
81func UnifyUnsafe(types []cty.Type) (cty.Type, []Conversion) {
82 return unify(types, true)
83}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/sort_types.go b/vendor/github.com/zclconf/go-cty/cty/convert/sort_types.go
new file mode 100644
index 0000000..b776910
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/sort_types.go
@@ -0,0 +1,69 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// sortTypes produces an ordering of the given types that serves as a
8// preference order for the result of unification of the given types.
9// The return value is a slice of indices into the given slice, and will
10// thus always be the same length as the given slice.
11//
12// The goal is that the most general of the given types will appear first
13// in the ordering. If there are uncomparable pairs of types in the list
14// then they will appear in an undefined order, and the unification pass
15// will presumably then fail.
16func sortTypes(tys []cty.Type) []int {
17 l := len(tys)
18
19 // First we build a graph whose edges represent "more general than",
20 // which we will then do a topological sort of.
21 edges := make([][]int, l)
22 for i := 0; i < (l - 1); i++ {
23 for j := i + 1; j < l; j++ {
24 cmp := compareTypes(tys[i], tys[j])
25 switch {
26 case cmp < 0:
27 edges[i] = append(edges[i], j)
28 case cmp > 0:
29 edges[j] = append(edges[j], i)
30 }
31 }
32 }
33
34 // Compute the in-degree of each node
35 inDegree := make([]int, l)
36 for _, outs := range edges {
37 for _, j := range outs {
38 inDegree[j]++
39 }
40 }
41
42 // The array backing our result will double as our queue for visiting
43 // the nodes, with the queue slice moving along this array until it
44 // is empty and positioned at the end of the array. Thus our visiting
45 // order is also our result order.
46 result := make([]int, l)
47 queue := result[0:0]
48
49 // Initialize the queue with any item of in-degree 0, preserving
50 // their relative order.
51 for i, n := range inDegree {
52 if n == 0 {
53 queue = append(queue, i)
54 }
55 }
56
57 for len(queue) != 0 {
58 i := queue[0]
59 queue = queue[1:]
60 for _, j := range edges[i] {
61 inDegree[j]--
62 if inDegree[j] == 0 {
63 queue = append(queue, j)
64 }
65 }
66 }
67
68 return result
69}
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/unify.go b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
new file mode 100644
index 0000000..bd6736b
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
@@ -0,0 +1,66 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// The current unify implementation is somewhat inefficient, but we accept this
8// under the assumption that it will generally be used with small numbers of
9// types and with types of reasonable complexity. However, it does have a
10// "happy path" where all of the given types are equal.
11//
12// This function is likely to have poor performance in cases where any given
13// types are very complex (lots of deeply-nested structures) or if the list
14// of types itself is very large. In particular, it will walk the nested type
15// structure under the given types several times, especially when given a
16// list of types for which unification is not possible, since each permutation
17// will be tried to determine that result.
18func unify(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
19 if len(types) == 0 {
20 // Degenerate case
21 return cty.NilType, nil
22 }
23
24 prefOrder := sortTypes(types)
25
26 // sortTypes gives us an order where earlier items are preferable as
27 // our result type. We'll now walk through these and choose the first
28 // one we encounter for which conversions exist for all source types.
29 conversions := make([]Conversion, len(types))
30Preferences:
31 for _, wantTypeIdx := range prefOrder {
32 wantType := types[wantTypeIdx]
33 for i, tryType := range types {
34 if i == wantTypeIdx {
35 // Don't need to convert our wanted type to itself
36 conversions[i] = nil
37 continue
38 }
39
40 if tryType.Equals(wantType) {
41 conversions[i] = nil
42 continue
43 }
44
45 if unsafe {
46 conversions[i] = GetConversionUnsafe(tryType, wantType)
47 } else {
48 conversions[i] = GetConversion(tryType, wantType)
49 }
50
51 if conversions[i] == nil {
52 // wantType is not a suitable unification type, so we'll
53 // try the next one in our preference order.
54 continue Preferences
55 }
56 }
57
58 return wantType, conversions
59 }
60
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
65 return cty.NilType, nil
66}
diff --git a/vendor/github.com/zclconf/go-cty/cty/doc.go b/vendor/github.com/zclconf/go-cty/cty/doc.go
new file mode 100644
index 0000000..d31f054
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/doc.go
@@ -0,0 +1,18 @@
1// Package cty (pronounced see-tie) provides some infrastructure for a type
2// system that might be useful for applications that need to represent
3// configuration values provided by the user whose types are not known
4// at compile time, particularly if the calling application also allows
5// such values to be used in expressions.
6//
7// The type system consists of primitive types Number, String and Bool, as
8// well as List and Map collection types and Object types that can have
9// arbitrarily-typed sets of attributes.
10//
11// A set of operations is defined on these types, which is accessible via
12// the wrapper struct Value, which annotates the raw, internal representation
13// of a value with its corresponding type.
14//
15// This package is oriented towards being a building block for configuration
16// languages used to bootstrap an application. It is not optimized for use
17// in tight loops where CPU time or memory pressure are a concern.
18package cty
diff --git a/vendor/github.com/zclconf/go-cty/cty/element_iterator.go b/vendor/github.com/zclconf/go-cty/cty/element_iterator.go
new file mode 100644
index 0000000..0bf84c7
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/element_iterator.go
@@ -0,0 +1,191 @@
1package cty
2
3import (
4 "sort"
5
6 "github.com/zclconf/go-cty/cty/set"
7)
8
9// ElementIterator is the interface type returned by Value.ElementIterator to
10// allow the caller to iterate over elements of a collection-typed value.
11//
12// Its usage pattern is as follows:
13//
14// it := val.ElementIterator()
15// for it.Next() {
16// key, val := it.Element()
17// // ...
18// }
19type ElementIterator interface {
20 Next() bool
21 Element() (key Value, value Value)
22}
23
24func canElementIterator(val Value) bool {
25 switch {
26 case val.ty.IsListType():
27 return true
28 case val.ty.IsMapType():
29 return true
30 case val.ty.IsSetType():
31 return true
32 case val.ty.IsTupleType():
33 return true
34 case val.ty.IsObjectType():
35 return true
36 default:
37 return false
38 }
39}
40
41func elementIterator(val Value) ElementIterator {
42 switch {
43 case val.ty.IsListType():
44 return &listElementIterator{
45 ety: val.ty.ElementType(),
46 vals: val.v.([]interface{}),
47 idx: -1,
48 }
49 case val.ty.IsMapType():
50 // We iterate the keys in a predictable lexicographical order so
51 // that results will always be stable given the same input map.
52 rawMap := val.v.(map[string]interface{})
53 keys := make([]string, 0, len(rawMap))
54 for key := range rawMap {
55 keys = append(keys, key)
56 }
57 sort.Strings(keys)
58
59 return &mapElementIterator{
60 ety: val.ty.ElementType(),
61 vals: rawMap,
62 keys: keys,
63 idx: -1,
64 }
65 case val.ty.IsSetType():
66 rawSet := val.v.(set.Set)
67 return &setElementIterator{
68 ety: val.ty.ElementType(),
69 setIt: rawSet.Iterator(),
70 }
71 case val.ty.IsTupleType():
72 return &tupleElementIterator{
73 etys: val.ty.TupleElementTypes(),
74 vals: val.v.([]interface{}),
75 idx: -1,
76 }
77 case val.ty.IsObjectType():
78 // We iterate the keys in a predictable lexicographical order so
79 // that results will always be stable given the same object type.
80 atys := val.ty.AttributeTypes()
81 keys := make([]string, 0, len(atys))
82 for key := range atys {
83 keys = append(keys, key)
84 }
85 sort.Strings(keys)
86
87 return &objectElementIterator{
88 atys: atys,
89 vals: val.v.(map[string]interface{}),
90 attrNames: keys,
91 idx: -1,
92 }
93 default:
94 panic("attempt to iterate on non-collection, non-tuple type")
95 }
96}
97
98type listElementIterator struct {
99 ety Type
100 vals []interface{}
101 idx int
102}
103
104func (it *listElementIterator) Element() (Value, Value) {
105 i := it.idx
106 return NumberIntVal(int64(i)), Value{
107 ty: it.ety,
108 v: it.vals[i],
109 }
110}
111
112func (it *listElementIterator) Next() bool {
113 it.idx++
114 return it.idx < len(it.vals)
115}
116
117type mapElementIterator struct {
118 ety Type
119 vals map[string]interface{}
120 keys []string
121 idx int
122}
123
124func (it *mapElementIterator) Element() (Value, Value) {
125 key := it.keys[it.idx]
126 return StringVal(key), Value{
127 ty: it.ety,
128 v: it.vals[key],
129 }
130}
131
132func (it *mapElementIterator) Next() bool {
133 it.idx++
134 return it.idx < len(it.keys)
135}
136
137type setElementIterator struct {
138 ety Type
139 setIt *set.Iterator
140}
141
142func (it *setElementIterator) Element() (Value, Value) {
143 val := Value{
144 ty: it.ety,
145 v: it.setIt.Value(),
146 }
147 return val, val
148}
149
150func (it *setElementIterator) Next() bool {
151 return it.setIt.Next()
152}
153
154type tupleElementIterator struct {
155 etys []Type
156 vals []interface{}
157 idx int
158}
159
160func (it *tupleElementIterator) Element() (Value, Value) {
161 i := it.idx
162 return NumberIntVal(int64(i)), Value{
163 ty: it.etys[i],
164 v: it.vals[i],
165 }
166}
167
168func (it *tupleElementIterator) Next() bool {
169 it.idx++
170 return it.idx < len(it.vals)
171}
172
173type objectElementIterator struct {
174 atys map[string]Type
175 vals map[string]interface{}
176 attrNames []string
177 idx int
178}
179
180func (it *objectElementIterator) Element() (Value, Value) {
181 key := it.attrNames[it.idx]
182 return StringVal(key), Value{
183 ty: it.atys[key],
184 v: it.vals[key],
185 }
186}
187
188func (it *objectElementIterator) Next() bool {
189 it.idx++
190 return it.idx < len(it.attrNames)
191}
diff --git a/vendor/github.com/zclconf/go-cty/cty/error.go b/vendor/github.com/zclconf/go-cty/cty/error.go
new file mode 100644
index 0000000..dd139f7
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/error.go
@@ -0,0 +1,55 @@
1package cty
2
3import (
4 "fmt"
5)
6
7// PathError is a specialization of error that represents where in a
8// potentially-deep data structure an error occured, using a Path.
9type PathError struct {
10 error
11 Path Path
12}
13
14func errorf(path Path, f string, args ...interface{}) error {
15 // We need to copy the Path because often our caller builds it by
16 // continually mutating the same underlying buffer.
17 sPath := make(Path, len(path))
18 copy(sPath, path)
19 return PathError{
20 error: fmt.Errorf(f, args...),
21 Path: sPath,
22 }
23}
24
25// NewErrorf creates a new PathError for the current path by passing the
26// given format and arguments to fmt.Errorf and then wrapping the result
27// similarly to NewError.
28func (p Path) NewErrorf(f string, args ...interface{}) error {
29 return errorf(p, f, args...)
30}
31
32// NewError creates a new PathError for the current path, wrapping the given
33// error.
34func (p Path) NewError(err error) error {
35 // if we're being asked to wrap an existing PathError then our new
36 // PathError will be the concatenation of the two paths, ensuring
37 // that we still get a single flat PathError that's thus easier for
38 // callers to deal with.
39 perr, wrappingPath := err.(PathError)
40 pathLen := len(p)
41 if wrappingPath {
42 pathLen = pathLen + len(perr.Path)
43 }
44
45 sPath := make(Path, pathLen)
46 copy(sPath, p)
47 if wrappingPath {
48 copy(sPath[len(p):], perr.Path)
49 }
50
51 return PathError{
52 error: err,
53 Path: sPath,
54 }
55}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/argument.go b/vendor/github.com/zclconf/go-cty/cty/function/argument.go
new file mode 100644
index 0000000..bfd3015
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/argument.go
@@ -0,0 +1,50 @@
1package function
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// Parameter represents a parameter to a function.
8type Parameter struct {
9 // Name is an optional name for the argument. This package ignores this
10 // value, but callers may use it for documentation, etc.
11 Name string
12
13 // A type that any argument for this parameter must conform to.
14 // cty.DynamicPseudoType can be used, either at top-level or nested
15 // in a parameterized type, to indicate that any type should be
16 // permitted, to allow the definition of type-generic functions.
17 Type cty.Type
18
19 // If AllowNull is set then null values may be passed into this
20 // argument's slot in both the type-check function and the implementation
21 // function. If not set, such values are rejected by the built-in
22 // checking rules.
23 AllowNull bool
24
25 // If AllowUnknown is set then unknown values may be passed into this
26 // argument's slot in the implementation function. If not set, any
27 // unknown values will cause the function to immediately return
28 // an unkonwn value without calling the implementation function, thus
29 // freeing the function implementer from dealing with this case.
30 AllowUnknown bool
31
32 // If AllowDynamicType is set then DynamicVal may be passed into this
33 // argument's slot in the implementation function. If not set, any
34 // dynamic values will cause the function to immediately return
35 // DynamicVal value without calling the implementation function, thus
36 // freeing the function implementer from dealing with this case.
37 //
38 // Note that DynamicVal is also unknown, so in order to receive dynamic
39 // *values* it is also necessary to set AllowUnknown.
40 //
41 // However, it is valid to set AllowDynamicType without AllowUnknown, in
42 // which case a dynamic value may be passed to the type checking function
43 // but will not make it to the *implementation* function. Instead, an
44 // unknown value of the type returned by the type-check function will be
45 // returned. This is suggested for functions that have a static return
46 // type since it allows the return value to be typed even if the input
47 // values are not, thus improving the type-check accuracy of derived
48 // values.
49 AllowDynamicType bool
50}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/doc.go b/vendor/github.com/zclconf/go-cty/cty/function/doc.go
new file mode 100644
index 0000000..393b311
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/doc.go
@@ -0,0 +1,6 @@
1// Package function builds on the functionality of cty by modeling functions
2// that operate on cty Values.
3//
4// Functions are, at their core, Go anonymous functions. However, this package
5// wraps around them utility functions for parameter type checking, etc.
6package function
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/error.go b/vendor/github.com/zclconf/go-cty/cty/function/error.go
new file mode 100644
index 0000000..2b56779
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/error.go
@@ -0,0 +1,50 @@
1package function
2
3import (
4 "fmt"
5 "runtime/debug"
6)
7
8// ArgError represents an error with one of the arguments in a call. The
9// attribute Index represents the zero-based index of the argument in question.
10//
11// Its error *may* be a cty.PathError, in which case the error actually
12// pertains to a nested value within the data structure passed as the argument.
13type ArgError struct {
14 error
15 Index int
16}
17
18func NewArgErrorf(i int, f string, args ...interface{}) error {
19 return ArgError{
20 error: fmt.Errorf(f, args...),
21 Index: i,
22 }
23}
24
25func NewArgError(i int, err error) error {
26 return ArgError{
27 error: err,
28 Index: i,
29 }
30}
31
32// PanicError indicates that a panic occurred while executing either a
33// function's type or implementation function. This is captured and wrapped
34// into a normal error so that callers (expected to be language runtimes)
35// are freed from having to deal with panics in buggy functions.
36type PanicError struct {
37 Value interface{}
38 Stack []byte
39}
40
41func errorForPanic(val interface{}) error {
42 return PanicError{
43 Value: val,
44 Stack: debug.Stack(),
45 }
46}
47
48func (e PanicError) Error() string {
49 return fmt.Sprintf("panic in function implementation: %s\n%s", e.Value, e.Stack)
50}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/function.go b/vendor/github.com/zclconf/go-cty/cty/function/function.go
new file mode 100644
index 0000000..162f7bf
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/function.go
@@ -0,0 +1,291 @@
1package function
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7)
8
9// Function represents a function. This is the main type in this package.
10type Function struct {
11 spec *Spec
12}
13
14// Spec is the specification of a function, used to instantiate
15// a new Function.
16type Spec struct {
17 // Params is a description of the positional parameters for the function.
18 // The standard checking logic rejects any calls that do not provide
19 // arguments conforming to this definition, freeing the function
20 // implementer from dealing with such inconsistencies.
21 Params []Parameter
22
23 // VarParam is an optional specification of additional "varargs" the
24 // function accepts. If this is non-nil then callers may provide an
25 // arbitrary number of additional arguments (after those matching with
26 // the fixed parameters in Params) that conform to the given specification,
27 // which will appear as additional values in the slices of values
28 // provided to the type and implementation functions.
29 VarParam *Parameter
30
31 // Type is the TypeFunc that decides the return type of the function
32 // given its arguments, which may be Unknown. See the documentation
33 // of TypeFunc for more information.
34 //
35 // Use StaticReturnType if the function's return type does not vary
36 // depending on its arguments.
37 Type TypeFunc
38
39 // Impl is the ImplFunc that implements the function's behavior.
40 //
41 // Functions are expected to behave as pure functions, and not create
42 // any visible side-effects.
43 //
44 // If a TypeFunc is also provided, the value returned from Impl *must*
45 // conform to the type it returns, or a call to the function will panic.
46 Impl ImplFunc
47}
48
49// New creates a new function with the given specification.
50//
51// After passing a Spec to this function, the caller must no longer read from
52// or mutate it.
53func New(spec *Spec) Function {
54 f := Function{
55 spec: spec,
56 }
57 return f
58}
59
60// TypeFunc is a callback type for determining the return type of a function
61// given its arguments.
62//
63// Any of the values passed to this function may be unknown, even if the
64// parameters are not configured to accept unknowns.
65//
66// If any of the given values are *not* unknown, the TypeFunc may use the
67// values for pre-validation and for choosing the return type. For example,
68// a hypothetical JSON-unmarshalling function could return
69// cty.DynamicPseudoType if the given JSON string is unknown, but return
70// a concrete type based on the JSON structure if the JSON string is already
71// known.
72type TypeFunc func(args []cty.Value) (cty.Type, error)
73
74// ImplFunc is a callback type for the main implementation of a function.
75//
76// "args" are the values for the arguments, and this slice will always be at
77// least as long as the argument definition slice for the function.
78//
79// "retType" is the type returned from the Type callback, included as a
80// convenience to avoid the need to re-compute the return type for generic
81// functions whose return type is a function of the arguments.
82type ImplFunc func(args []cty.Value, retType cty.Type) (cty.Value, error)
83
84// StaticReturnType returns a TypeFunc that always returns the given type.
85//
86// This is provided as a convenience for defining a function whose return
87// type does not depend on the argument types.
88func StaticReturnType(ty cty.Type) TypeFunc {
89 return func([]cty.Value) (cty.Type, error) {
90 return ty, nil
91 }
92}
93
94// ReturnType returns the return type of a function given a set of candidate
95// argument types, or returns an error if the given types are unacceptable.
96//
97// If the caller already knows values for at least some of the arguments
98// it can be better to call ReturnTypeForValues, since certain functions may
99// determine their return types from their values and return DynamicVal if
100// the values are unknown.
101func (f Function) ReturnType(argTypes []cty.Type) (cty.Type, error) {
102 vals := make([]cty.Value, len(argTypes))
103 for i, ty := range argTypes {
104 vals[i] = cty.UnknownVal(ty)
105 }
106 return f.ReturnTypeForValues(vals)
107}
108
109// ReturnTypeForValues is similar to ReturnType but can be used if the caller
110// already knows the values of some or all of the arguments, in which case
111// the function may be able to determine a more definite result if its
112// return type depends on the argument *values*.
113//
114// For any arguments whose values are not known, pass an Unknown value of
115// the appropriate type.
116func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error) {
117 var posArgs []cty.Value
118 var varArgs []cty.Value
119
120 if f.spec.VarParam == nil {
121 if len(args) != len(f.spec.Params) {
122 return cty.Type{}, fmt.Errorf(
123 "wrong number of arguments (%d required; %d given)",
124 len(f.spec.Params), len(args),
125 )
126 }
127
128 posArgs = args
129 varArgs = nil
130 } else {
131 if len(args) < len(f.spec.Params) {
132 return cty.Type{}, fmt.Errorf(
133 "wrong number of arguments (at least %d required; %d given)",
134 len(f.spec.Params), len(args),
135 )
136 }
137
138 posArgs = args[0:len(f.spec.Params)]
139 varArgs = args[len(f.spec.Params):]
140 }
141
142 for i, spec := range f.spec.Params {
143 val := posArgs[i]
144
145 if val.IsNull() && !spec.AllowNull {
146 return cty.Type{}, NewArgErrorf(i, "must not be null")
147 }
148
149 // AllowUnknown is ignored for type-checking, since we expect to be
150 // able to type check with unknown values. We *do* still need to deal
151 // with DynamicPseudoType here though, since the Type function might
152 // not be ready to deal with that.
153
154 if val.Type() == cty.DynamicPseudoType {
155 if !spec.AllowDynamicType {
156 return cty.DynamicPseudoType, nil
157 }
158 } else if errs := val.Type().TestConformance(spec.Type); errs != nil {
159 // For now we'll just return the first error in the set, since
160 // we don't have a good way to return the whole list here.
161 // Would be good to do something better at some point...
162 return cty.Type{}, NewArgError(i, errs[0])
163 }
164 }
165
166 if varArgs != nil {
167 spec := f.spec.VarParam
168 for i, val := range varArgs {
169 realI := i + len(posArgs)
170
171 if val.IsNull() && !spec.AllowNull {
172 return cty.Type{}, NewArgErrorf(realI, "must not be null")
173 }
174
175 if val.Type() == cty.DynamicPseudoType {
176 if !spec.AllowDynamicType {
177 return cty.DynamicPseudoType, nil
178 }
179 } else if errs := val.Type().TestConformance(spec.Type); errs != nil {
180 // For now we'll just return the first error in the set, since
181 // we don't have a good way to return the whole list here.
182 // Would be good to do something better at some point...
183 return cty.Type{}, NewArgError(i, errs[0])
184 }
185 }
186 }
187
188 // Intercept any panics from the function and return them as normal errors,
189 // so a calling language runtime doesn't need to deal with panics.
190 defer func() {
191 if r := recover(); r != nil {
192 ty = cty.NilType
193 err = errorForPanic(r)
194 }
195 }()
196
197 return f.spec.Type(args)
198}
199
200// Call actually calls the function with the given arguments, which must
201// conform to the function's parameter specification or an error will be
202// returned.
203func (f Function) Call(args []cty.Value) (val cty.Value, err error) {
204 expectedType, err := f.ReturnTypeForValues(args)
205 if err != nil {
206 return cty.NilVal, err
207 }
208
209 // Type checking already dealt with most situations relating to our
210 // parameter specification, but we still need to deal with unknown
211 // values.
212 posArgs := args[:len(f.spec.Params)]
213 varArgs := args[len(f.spec.Params):]
214
215 for i, spec := range f.spec.Params {
216 val := posArgs[i]
217
218 if !val.IsKnown() && !spec.AllowUnknown {
219 return cty.UnknownVal(expectedType), nil
220 }
221 }
222
223 if f.spec.VarParam != nil {
224 spec := f.spec.VarParam
225 for _, val := range varArgs {
226 if !val.IsKnown() && !spec.AllowUnknown {
227 return cty.UnknownVal(expectedType), nil
228 }
229 }
230 }
231
232 var retVal cty.Value
233 {
234 // Intercept any panics from the function and return them as normal errors,
235 // so a calling language runtime doesn't need to deal with panics.
236 defer func() {
237 if r := recover(); r != nil {
238 val = cty.NilVal
239 err = errorForPanic(r)
240 }
241 }()
242
243 retVal, err = f.spec.Impl(args, expectedType)
244 if err != nil {
245 return cty.NilVal, err
246 }
247 }
248
249 // Returned value must conform to what the Type function expected, to
250 // protect callers from having to deal with inconsistencies.
251 if errs := retVal.Type().TestConformance(expectedType); errs != nil {
252 panic(fmt.Errorf(
253 "returned value %#v does not conform to expected return type %#v: %s",
254 retVal, expectedType, errs[0],
255 ))
256 }
257
258 return retVal, nil
259}
260
261// ProxyFunc the type returned by the method Function.Proxy.
262type ProxyFunc func(args ...cty.Value) (cty.Value, error)
263
264// Proxy returns a function that can be called with cty.Value arguments
265// to run the function. This is provided as a convenience for when using
266// a function directly within Go code.
267func (f Function) Proxy() ProxyFunc {
268 return func(args ...cty.Value) (cty.Value, error) {
269 return f.Call(args)
270 }
271}
272
273// Params returns information about the function's fixed positional parameters.
274// This does not include information about any variadic arguments accepted;
275// for that, call VarParam.
276func (f Function) Params() []Parameter {
277 new := make([]Parameter, len(f.spec.Params))
278 copy(new, f.spec.Params)
279 return new
280}
281
282// VarParam returns information about the variadic arguments the function
283// expects, or nil if the function is not variadic.
284func (f Function) VarParam() *Parameter {
285 if f.spec.VarParam == nil {
286 return nil
287 }
288
289 ret := *f.spec.VarParam
290 return &ret
291}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go
new file mode 100644
index 0000000..a473d0e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go
@@ -0,0 +1,73 @@
1package stdlib
2
3import (
4 "github.com/zclconf/go-cty/cty"
5 "github.com/zclconf/go-cty/cty/function"
6)
7
8var NotFunc = function.New(&function.Spec{
9 Params: []function.Parameter{
10 {
11 Name: "val",
12 Type: cty.Bool,
13 AllowDynamicType: true,
14 },
15 },
16 Type: function.StaticReturnType(cty.Bool),
17 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
18 return args[0].Not(), nil
19 },
20})
21
22var AndFunc = function.New(&function.Spec{
23 Params: []function.Parameter{
24 {
25 Name: "a",
26 Type: cty.Bool,
27 AllowDynamicType: true,
28 },
29 {
30 Name: "b",
31 Type: cty.Bool,
32 AllowDynamicType: true,
33 },
34 },
35 Type: function.StaticReturnType(cty.Bool),
36 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
37 return args[0].And(args[1]), nil
38 },
39})
40
41var OrFunc = function.New(&function.Spec{
42 Params: []function.Parameter{
43 {
44 Name: "a",
45 Type: cty.Bool,
46 AllowDynamicType: true,
47 },
48 {
49 Name: "b",
50 Type: cty.Bool,
51 AllowDynamicType: true,
52 },
53 },
54 Type: function.StaticReturnType(cty.Bool),
55 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
56 return args[0].Or(args[1]), nil
57 },
58})
59
60// Not returns the logical complement of the given boolean value.
61func Not(num cty.Value) (cty.Value, error) {
62 return NotFunc.Call([]cty.Value{num})
63}
64
65// And returns true if and only if both of the given boolean values are true.
66func And(a, b cty.Value) (cty.Value, error) {
67 return AndFunc.Call([]cty.Value{a, b})
68}
69
70// Or returns true if either of the given boolean values are true.
71func Or(a, b cty.Value) (cty.Value, error) {
72 return OrFunc.Call([]cty.Value{a, b})
73}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go
new file mode 100644
index 0000000..a132e0c
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go
@@ -0,0 +1,112 @@
1package stdlib
2
3import (
4 "fmt"
5 "reflect"
6
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/function"
9 "github.com/zclconf/go-cty/cty/gocty"
10)
11
12// Bytes is a capsule type that can be used with the binary functions to
13// support applications that need to support raw buffers in addition to
14// UTF-8 strings.
15var Bytes = cty.Capsule("bytes", reflect.TypeOf([]byte(nil)))
16
17// BytesVal creates a new Bytes value from the given buffer, which must be
18// non-nil or this function will panic.
19//
20// Once a byte slice has been wrapped in a Bytes capsule, its underlying array
21// must be considered immutable.
22func BytesVal(buf []byte) cty.Value {
23 if buf == nil {
24 panic("can't make Bytes value from nil slice")
25 }
26
27 return cty.CapsuleVal(Bytes, &buf)
28}
29
30// BytesLen is a Function that returns the length of the buffer encapsulated
31// in a Bytes value.
32var BytesLenFunc = function.New(&function.Spec{
33 Params: []function.Parameter{
34 {
35 Name: "buf",
36 Type: Bytes,
37 AllowDynamicType: true,
38 },
39 },
40 Type: function.StaticReturnType(cty.Number),
41 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
42 bufPtr := args[0].EncapsulatedValue().(*[]byte)
43 return cty.NumberIntVal(int64(len(*bufPtr))), nil
44 },
45})
46
47// BytesSlice is a Function that returns a slice of the given Bytes value.
48var BytesSliceFunc = function.New(&function.Spec{
49 Params: []function.Parameter{
50 {
51 Name: "buf",
52 Type: Bytes,
53 AllowDynamicType: true,
54 },
55 {
56 Name: "offset",
57 Type: cty.Number,
58 AllowDynamicType: true,
59 },
60 {
61 Name: "length",
62 Type: cty.Number,
63 AllowDynamicType: true,
64 },
65 },
66 Type: function.StaticReturnType(Bytes),
67 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
68 bufPtr := args[0].EncapsulatedValue().(*[]byte)
69
70 var offset, length int
71
72 var err error
73 err = gocty.FromCtyValue(args[1], &offset)
74 if err != nil {
75 return cty.NilVal, err
76 }
77 err = gocty.FromCtyValue(args[2], &length)
78 if err != nil {
79 return cty.NilVal, err
80 }
81
82 if offset < 0 || length < 0 {
83 return cty.NilVal, fmt.Errorf("offset and length must be non-negative")
84 }
85
86 if offset > len(*bufPtr) {
87 return cty.NilVal, fmt.Errorf(
88 "offset %d is greater than total buffer length %d",
89 offset, len(*bufPtr),
90 )
91 }
92
93 end := offset + length
94
95 if end > len(*bufPtr) {
96 return cty.NilVal, fmt.Errorf(
97 "offset %d + length %d is greater than total buffer length %d",
98 offset, length, len(*bufPtr),
99 )
100 }
101
102 return BytesVal((*bufPtr)[offset:end]), nil
103 },
104})
105
106func BytesLen(buf cty.Value) (cty.Value, error) {
107 return BytesLenFunc.Call([]cty.Value{buf})
108}
109
110func BytesSlice(buf cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) {
111 return BytesSliceFunc.Call([]cty.Value{buf, offset, length})
112}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
new file mode 100644
index 0000000..967ba03
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
@@ -0,0 +1,140 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/function"
8 "github.com/zclconf/go-cty/cty/gocty"
9)
10
11var HasIndexFunc = function.New(&function.Spec{
12 Params: []function.Parameter{
13 {
14 Name: "collection",
15 Type: cty.DynamicPseudoType,
16 AllowDynamicType: true,
17 },
18 {
19 Name: "key",
20 Type: cty.DynamicPseudoType,
21 AllowDynamicType: true,
22 },
23 },
24 Type: func(args []cty.Value) (ret cty.Type, err error) {
25 collTy := args[0].Type()
26 if !(collTy.IsTupleType() || collTy.IsListType() || collTy.IsMapType() || collTy == cty.DynamicPseudoType) {
27 return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
28 }
29 return cty.Bool, nil
30 },
31 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
32 return args[0].HasIndex(args[1]), nil
33 },
34})
35
36var IndexFunc = function.New(&function.Spec{
37 Params: []function.Parameter{
38 {
39 Name: "collection",
40 Type: cty.DynamicPseudoType,
41 },
42 {
43 Name: "key",
44 Type: cty.DynamicPseudoType,
45 AllowDynamicType: true,
46 },
47 },
48 Type: func(args []cty.Value) (ret cty.Type, err error) {
49 collTy := args[0].Type()
50 key := args[1]
51 keyTy := key.Type()
52 switch {
53 case collTy.IsTupleType():
54 if keyTy != cty.Number && keyTy != cty.DynamicPseudoType {
55 return cty.NilType, fmt.Errorf("key for tuple must be number")
56 }
57 if !key.IsKnown() {
58 return cty.DynamicPseudoType, nil
59 }
60 var idx int
61 err := gocty.FromCtyValue(key, &idx)
62 if err != nil {
63 return cty.NilType, fmt.Errorf("invalid key for tuple: %s", err)
64 }
65
66 etys := collTy.TupleElementTypes()
67
68 if idx >= len(etys) || idx < 0 {
69 return cty.NilType, fmt.Errorf("key must be between 0 and %d inclusive", len(etys))
70 }
71
72 return etys[idx], nil
73
74 case collTy.IsListType():
75 if keyTy != cty.Number && keyTy != cty.DynamicPseudoType {
76 return cty.NilType, fmt.Errorf("key for list must be number")
77 }
78
79 return collTy.ElementType(), nil
80
81 case collTy.IsMapType():
82 if keyTy != cty.String && keyTy != cty.DynamicPseudoType {
83 return cty.NilType, fmt.Errorf("key for map must be string")
84 }
85
86 return collTy.ElementType(), nil
87
88 default:
89 return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
90 }
91 },
92 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
93 has, err := HasIndex(args[0], args[1])
94 if err != nil {
95 return cty.NilVal, err
96 }
97 if has.False() { // safe because collection and key are guaranteed known here
98 return cty.NilVal, fmt.Errorf("invalid index")
99 }
100
101 return args[0].Index(args[1]), nil
102 },
103})
104
105var LengthFunc = function.New(&function.Spec{
106 Params: []function.Parameter{
107 {
108 Name: "collection",
109 Type: cty.DynamicPseudoType,
110 AllowDynamicType: true,
111 },
112 },
113 Type: func(args []cty.Value) (ret cty.Type, err error) {
114 collTy := args[0].Type()
115 if !(collTy.IsTupleType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType) {
116 return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
117 }
118 return cty.Number, nil
119 },
120 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
121 return args[0].Length(), nil
122 },
123})
124
125// HasIndex determines whether the given collection can be indexed with the
126// given key.
127func HasIndex(collection cty.Value, key cty.Value) (cty.Value, error) {
128 return HasIndexFunc.Call([]cty.Value{collection, key})
129}
130
131// Index returns an element from the given collection using the given key,
132// or returns an error if there is no element for the given key.
133func Index(collection cty.Value, key cty.Value) (cty.Value, error) {
134 return IndexFunc.Call([]cty.Value{collection, key})
135}
136
137// Length returns the number of elements in the given collection.
138func Length(collection cty.Value) (cty.Value, error) {
139 return LengthFunc.Call([]cty.Value{collection})
140}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
new file mode 100644
index 0000000..5070a5a
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
@@ -0,0 +1,93 @@
1package stdlib
2
3import (
4 "encoding/csv"
5 "fmt"
6 "io"
7 "strings"
8
9 "github.com/zclconf/go-cty/cty"
10 "github.com/zclconf/go-cty/cty/function"
11)
12
13var CSVDecodeFunc = function.New(&function.Spec{
14 Params: []function.Parameter{
15 {
16 Name: "str",
17 Type: cty.String,
18 },
19 },
20 Type: func(args []cty.Value) (cty.Type, error) {
21 str := args[0]
22 if !str.IsKnown() {
23 return cty.DynamicPseudoType, nil
24 }
25
26 r := strings.NewReader(str.AsString())
27 cr := csv.NewReader(r)
28 headers, err := cr.Read()
29 if err == io.EOF {
30 return cty.DynamicPseudoType, fmt.Errorf("missing header line")
31 }
32 if err != nil {
33 return cty.DynamicPseudoType, err
34 }
35
36 atys := make(map[string]cty.Type, len(headers))
37 for _, name := range headers {
38 if _, exists := atys[name]; exists {
39 return cty.DynamicPseudoType, fmt.Errorf("duplicate column name %q", name)
40 }
41 atys[name] = cty.String
42 }
43 return cty.List(cty.Object(atys)), nil
44 },
45 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
46 ety := retType.ElementType()
47 atys := ety.AttributeTypes()
48 str := args[0]
49 r := strings.NewReader(str.AsString())
50 cr := csv.NewReader(r)
51 cr.FieldsPerRecord = len(atys)
52
53 // Read the header row first, since that'll tell us which indices
54 // map to which attribute names.
55 headers, err := cr.Read()
56 if err != nil {
57 return cty.DynamicVal, err
58 }
59
60 var rows []cty.Value
61 for {
62 cols, err := cr.Read()
63 if err == io.EOF {
64 break
65 }
66 if err != nil {
67 return cty.DynamicVal, err
68 }
69
70 vals := make(map[string]cty.Value, len(cols))
71 for i, str := range cols {
72 name := headers[i]
73 vals[name] = cty.StringVal(str)
74 }
75 rows = append(rows, cty.ObjectVal(vals))
76 }
77
78 if len(rows) == 0 {
79 return cty.ListValEmpty(ety), nil
80 }
81 return cty.ListVal(rows), nil
82 },
83})
84
85// CSVDecode parses the given CSV (RFC 4180) string and, if it is valid,
86// returns a list of objects representing the rows.
87//
88// The result is always a list of some object type. The first row of the
89// input is used to determine the object attributes, and subsequent rows
90// determine the values of those attributes.
91func CSVDecode(str cty.Value) (cty.Value, error) {
92 return CSVDecodeFunc.Call([]cty.Value{str})
93}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go
new file mode 100644
index 0000000..cfb613e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go
@@ -0,0 +1,13 @@
1// Package stdlib is a collection of cty functions that are expected to be
2// generally useful, and are thus factored out into this shared library in
3// the hope that cty-using applications will have consistent behavior when
4// using these functions.
5//
6// See the parent package "function" for more information on the purpose
7// and usage of cty functions.
8//
9// This package contains both Go functions, which provide convenient access
10// to call the functions from Go code, and the Function objects themselves.
11// The latter follow the naming scheme of appending "Func" to the end of
12// the function name.
13package stdlib
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
new file mode 100644
index 0000000..fb24f20
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
@@ -0,0 +1,496 @@
1package stdlib
2
3import (
4 "bytes"
5 "fmt"
6 "math/big"
7 "strings"
8
9 "github.com/apparentlymart/go-textseg/textseg"
10
11 "github.com/zclconf/go-cty/cty"
12 "github.com/zclconf/go-cty/cty/convert"
13 "github.com/zclconf/go-cty/cty/function"
14 "github.com/zclconf/go-cty/cty/json"
15)
16
17//go:generate ragel -Z format_fsm.rl
18//go:generate gofmt -w format_fsm.go
19
20var FormatFunc = function.New(&function.Spec{
21 Params: []function.Parameter{
22 {
23 Name: "format",
24 Type: cty.String,
25 },
26 },
27 VarParam: &function.Parameter{
28 Name: "args",
29 Type: cty.DynamicPseudoType,
30 AllowNull: true,
31 },
32 Type: function.StaticReturnType(cty.String),
33 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
34 for _, arg := range args[1:] {
35 if !arg.IsWhollyKnown() {
36 // We require all nested values to be known because the only
37 // thing we can do for a collection/structural type is print
38 // it as JSON and that requires it to be wholly known.
39 return cty.UnknownVal(cty.String), nil
40 }
41 }
42 str, err := formatFSM(args[0].AsString(), args[1:])
43 return cty.StringVal(str), err
44 },
45})
46
47var FormatListFunc = function.New(&function.Spec{
48 Params: []function.Parameter{
49 {
50 Name: "format",
51 Type: cty.String,
52 },
53 },
54 VarParam: &function.Parameter{
55 Name: "args",
56 Type: cty.DynamicPseudoType,
57 AllowNull: true,
58 AllowUnknown: true,
59 },
60 Type: function.StaticReturnType(cty.List(cty.String)),
61 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
62 fmtVal := args[0]
63 args = args[1:]
64
65 if len(args) == 0 {
66 // With no arguments, this function is equivalent to Format, but
67 // returning a single-element list result.
68 result, err := Format(fmtVal, args...)
69 return cty.ListVal([]cty.Value{result}), err
70 }
71
72 fmtStr := fmtVal.AsString()
73
74 // Each of our arguments will be dealt with either as an iterator
75 // or as a single value. Iterators are used for sequence-type values
76 // (lists, sets, tuples) while everything else is treated as a
77 // single value. The sequences we iterate over are required to be
78 // all the same length.
79 iterLen := -1
80 lenChooser := -1
81 iterators := make([]cty.ElementIterator, len(args))
82 singleVals := make([]cty.Value, len(args))
83 for i, arg := range args {
84 argTy := arg.Type()
85 switch {
86 case (argTy.IsListType() || argTy.IsSetType() || argTy.IsTupleType()) && !arg.IsNull():
87 thisLen := arg.LengthInt()
88 if iterLen == -1 {
89 iterLen = thisLen
90 lenChooser = i
91 } else {
92 if thisLen != iterLen {
93 return cty.NullVal(cty.List(cty.String)), function.NewArgErrorf(
94 i+1,
95 "argument %d has length %d, which is inconsistent with argument %d of length %d",
96 i+1, thisLen,
97 lenChooser+1, iterLen,
98 )
99 }
100 }
101 iterators[i] = arg.ElementIterator()
102 default:
103 singleVals[i] = arg
104 }
105 }
106
107 if iterLen == 0 {
108 // If our sequences are all empty then our result must be empty.
109 return cty.ListValEmpty(cty.String), nil
110 }
111
112 if iterLen == -1 {
113 // If we didn't encounter any iterables at all then we're going
114 // to just do one iteration with items from singleVals.
115 iterLen = 1
116 }
117
118 ret := make([]cty.Value, 0, iterLen)
119 fmtArgs := make([]cty.Value, len(iterators))
120 Results:
121 for iterIdx := 0; iterIdx < iterLen; iterIdx++ {
122
123 // Construct our arguments for a single format call
124 for i := range fmtArgs {
125 switch {
126 case iterators[i] != nil:
127 iterator := iterators[i]
128 iterator.Next()
129 _, val := iterator.Element()
130 fmtArgs[i] = val
131 default:
132 fmtArgs[i] = singleVals[i]
133 }
134
135 // If any of the arguments to this call would be unknown then
136 // this particular result is unknown, but we'll keep going
137 // to see if any other iterations can produce known values.
138 if !fmtArgs[i].IsWhollyKnown() {
139 // We require all nested values to be known because the only
140 // thing we can do for a collection/structural type is print
141 // it as JSON and that requires it to be wholly known.
142 ret = append(ret, cty.UnknownVal(cty.String))
143 continue Results
144 }
145 }
146
147 str, err := formatFSM(fmtStr, fmtArgs)
148 if err != nil {
149 return cty.NullVal(cty.List(cty.String)), fmt.Errorf(
150 "error on format iteration %d: %s", iterIdx, err,
151 )
152 }
153
154 ret = append(ret, cty.StringVal(str))
155 }
156
157 return cty.ListVal(ret), nil
158 },
159})
160
161// Format produces a string representation of zero or more values using a
162// format string similar to the "printf" function in C.
163//
164// It supports the following "verbs":
165//
166// %% Literal percent sign, consuming no value
167// %v A default formatting of the value based on type, as described below.
168// %#v JSON serialization of the value
169// %t Converts to boolean and then produces "true" or "false"
170// %b Converts to number, requires integer, produces binary representation
171// %d Converts to number, requires integer, produces decimal representation
172// %o Converts to number, requires integer, produces octal representation
173// %x Converts to number, requires integer, produces hexadecimal representation
174// with lowercase letters
175// %X Like %x but with uppercase letters
176// %e Converts to number, produces scientific notation like -1.234456e+78
177// %E Like %e but with an uppercase "E" representing the exponent
178// %f Converts to number, produces decimal representation with fractional
179// part but no exponent, like 123.456
180// %g %e for large exponents or %f otherwise
181// %G %E for large exponents or %f otherwise
182// %s Converts to string and produces the string's characters
183// %q Converts to string and produces JSON-quoted string representation,
184// like %v.
185//
186// The default format selections made by %v are:
187//
188// string %s
189// number %g
190// bool %t
191// other %#v
192//
193// Null values produce the literal keyword "null" for %v and %#v, and produce
194// an error otherwise.
195//
196// Width is specified by an optional decimal number immediately preceding the
197// verb letter. If absent, the width is whatever is necessary to represent the
198// value. Precision is specified after the (optional) width by a period
199// followed by a decimal number. If no period is present, a default precision
200// is used. A period with no following number is invalid.
201// For examples:
202//
203// %f default width, default precision
204// %9f width 9, default precision
205// %.2f default width, precision 2
206// %9.2f width 9, precision 2
207//
208// Width and precision are measured in unicode characters (grapheme clusters).
209//
210// For most values, width is the minimum number of characters to output,
211// padding the formatted form with spaces if necessary.
212//
213// For strings, precision limits the length of the input to be formatted (not
214// the size of the output), truncating if necessary.
215//
216// For numbers, width sets the minimum width of the field and precision sets
217// the number of places after the decimal, if appropriate, except that for
218// %g/%G precision sets the total number of significant digits.
219//
220// The following additional symbols can be used immediately after the percent
221// introducer as flags:
222//
223// (a space) leave a space where the sign would be if number is positive
224// + Include a sign for a number even if it is positive (numeric only)
225// - Pad with spaces on the left rather than the right
226// 0 Pad with zeros rather than spaces.
227//
228// Flag characters are ignored for verbs that do not support them.
229//
230// By default, % sequences consume successive arguments starting with the first.
231// Introducing a [n] sequence immediately before the verb letter, where n is a
232// decimal integer, explicitly chooses a particular value argument by its
233// one-based index. Subsequent calls without an explicit index will then
234// proceed with n+1, n+2, etc.
235//
236// An error is produced if the format string calls for an impossible conversion
237// or accesses more values than are given. An error is produced also for
238// an unsupported format verb.
239func Format(format cty.Value, vals ...cty.Value) (cty.Value, error) {
240 args := make([]cty.Value, 0, len(vals)+1)
241 args = append(args, format)
242 args = append(args, vals...)
243 return FormatFunc.Call(args)
244}
245
246// FormatList applies the same formatting behavior as Format, but accepts
247// a mixture of list and non-list values as arguments. Any list arguments
248// passed must have the same length, which dictates the length of the
249// resulting list.
250//
251// Any non-list arguments are used repeatedly for each iteration over the
252// list arguments. The list arguments are iterated in order by key, so
253// corresponding items are formatted together.
254func FormatList(format cty.Value, vals ...cty.Value) (cty.Value, error) {
255 args := make([]cty.Value, 0, len(vals)+1)
256 args = append(args, format)
257 args = append(args, vals...)
258 return FormatListFunc.Call(args)
259}
260
261type formatVerb struct {
262 Raw string
263 Offset int
264
265 ArgNum int
266 Mode rune
267
268 Zero bool
269 Sharp bool
270 Plus bool
271 Minus bool
272 Space bool
273
274 HasPrec bool
275 Prec int
276
277 HasWidth bool
278 Width int
279}
280
281// formatAppend is called by formatFSM (generated by format_fsm.rl) for each
282// formatting sequence that is encountered.
283func formatAppend(verb *formatVerb, buf *bytes.Buffer, args []cty.Value) error {
284 argIdx := verb.ArgNum - 1
285 if argIdx >= len(args) {
286 return fmt.Errorf(
287 "not enough arguments for %q at %d: need index %d but have %d total",
288 verb.Raw, verb.Offset,
289 verb.ArgNum, len(args),
290 )
291 }
292 arg := args[argIdx]
293
294 if verb.Mode != 'v' && arg.IsNull() {
295 return fmt.Errorf("unsupported value for %q at %d: null value cannot be formatted", verb.Raw, verb.Offset)
296 }
297
298 // Normalize to make some things easier for downstream formatters
299 if !verb.HasWidth {
300 verb.Width = -1
301 }
302 if !verb.HasPrec {
303 verb.Prec = -1
304 }
305
306 // For our first pass we'll ensure the verb is supported and then fan
307 // out to other functions based on what conversion is needed.
308 switch verb.Mode {
309
310 case 'v':
311 return formatAppendAsIs(verb, buf, arg)
312
313 case 't':
314 return formatAppendBool(verb, buf, arg)
315
316 case 'b', 'd', 'o', 'x', 'X', 'e', 'E', 'f', 'g', 'G':
317 return formatAppendNumber(verb, buf, arg)
318
319 case 's', 'q':
320 return formatAppendString(verb, buf, arg)
321
322 default:
323 return fmt.Errorf("unsupported format verb %q in %q at offset %d", verb.Mode, verb.Raw, verb.Offset)
324 }
325}
326
327func formatAppendAsIs(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
328
329 if !verb.Sharp && !arg.IsNull() {
330 // Unless the caller overrode it with the sharp flag, we'll try some
331 // specialized formats before we fall back on JSON.
332 switch arg.Type() {
333 case cty.String:
334 fmted := arg.AsString()
335 fmted = formatPadWidth(verb, fmted)
336 buf.WriteString(fmted)
337 return nil
338 case cty.Number:
339 bf := arg.AsBigFloat()
340 fmted := bf.Text('g', -1)
341 fmted = formatPadWidth(verb, fmted)
342 buf.WriteString(fmted)
343 return nil
344 }
345 }
346
347 jb, err := json.Marshal(arg, arg.Type())
348 if err != nil {
349 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
350 }
351 fmted := formatPadWidth(verb, string(jb))
352 buf.WriteString(fmted)
353
354 return nil
355}
356
357func formatAppendBool(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
358 var err error
359 arg, err = convert.Convert(arg, cty.Bool)
360 if err != nil {
361 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
362 }
363
364 if arg.True() {
365 buf.WriteString("true")
366 } else {
367 buf.WriteString("false")
368 }
369 return nil
370}
371
372func formatAppendNumber(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
373 var err error
374 arg, err = convert.Convert(arg, cty.Number)
375 if err != nil {
376 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
377 }
378
379 switch verb.Mode {
380 case 'b', 'd', 'o', 'x', 'X':
381 return formatAppendInteger(verb, buf, arg)
382 default:
383 bf := arg.AsBigFloat()
384
385 // For floats our format syntax is a subset of Go's, so it's
386 // safe for us to just lean on the existing Go implementation.
387 fmtstr := formatStripIndexSegment(verb.Raw)
388 fmted := fmt.Sprintf(fmtstr, bf)
389 buf.WriteString(fmted)
390 return nil
391 }
392}
393
394func formatAppendInteger(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
395 bf := arg.AsBigFloat()
396 bi, acc := bf.Int(nil)
397 if acc != big.Exact {
398 return fmt.Errorf("unsupported value for %q at %d: an integer is required", verb.Raw, verb.Offset)
399 }
400
401 // For integers our format syntax is a subset of Go's, so it's
402 // safe for us to just lean on the existing Go implementation.
403 fmtstr := formatStripIndexSegment(verb.Raw)
404 fmted := fmt.Sprintf(fmtstr, bi)
405 buf.WriteString(fmted)
406 return nil
407}
408
409func formatAppendString(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
410 var err error
411 arg, err = convert.Convert(arg, cty.String)
412 if err != nil {
413 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
414 }
415
416 // We _cannot_ directly use the Go fmt.Sprintf implementation for strings
417 // because it measures widths and precisions in runes rather than grapheme
418 // clusters.
419
420 str := arg.AsString()
421 if verb.Prec > 0 {
422 strB := []byte(str)
423 pos := 0
424 wanted := verb.Prec
425 for i := 0; i < wanted; i++ {
426 next := strB[pos:]
427 if len(next) == 0 {
428 // ran out of characters before we hit our max width
429 break
430 }
431 d, _, _ := textseg.ScanGraphemeClusters(strB[pos:], true)
432 pos += d
433 }
434 str = str[:pos]
435 }
436
437 switch verb.Mode {
438 case 's':
439 fmted := formatPadWidth(verb, str)
440 buf.WriteString(fmted)
441 case 'q':
442 jb, err := json.Marshal(cty.StringVal(str), cty.String)
443 if err != nil {
444 // Should never happen, since we know this is a known, non-null string
445 panic(fmt.Errorf("failed to marshal %#v as JSON: %s", arg, err))
446 }
447 fmted := formatPadWidth(verb, string(jb))
448 buf.WriteString(fmted)
449 default:
450 // Should never happen because formatAppend should've already validated
451 panic(fmt.Errorf("invalid string formatting mode %q", verb.Mode))
452 }
453 return nil
454}
455
456func formatPadWidth(verb *formatVerb, fmted string) string {
457 if verb.Width < 0 {
458 return fmted
459 }
460
461 // Safe to ignore errors because ScanGraphemeClusters cannot produce errors
462 givenLen, _ := textseg.TokenCount([]byte(fmted), textseg.ScanGraphemeClusters)
463 wantLen := verb.Width
464 if givenLen >= wantLen {
465 return fmted
466 }
467
468 padLen := wantLen - givenLen
469 padChar := " "
470 if verb.Zero {
471 padChar = "0"
472 }
473 pads := strings.Repeat(padChar, padLen)
474
475 if verb.Minus {
476 return fmted + pads
477 }
478 return pads + fmted
479}
480
481// formatStripIndexSegment strips out any [nnn] segment present in a verb
482// string so that we can pass it through to Go's fmt.Sprintf with a single
483// argument. This is used in cases where we're just leaning on Go's formatter
484// because it's a superset of ours.
485func formatStripIndexSegment(rawVerb string) string {
486 // We assume the string has already been validated here, since we should
487 // only be using this function with strings that were accepted by our
488 // scanner in formatFSM.
489 start := strings.Index(rawVerb, "[")
490 end := strings.Index(rawVerb, "]")
491 if start == -1 || end == -1 {
492 return rawVerb
493 }
494
495 return rawVerb[:start] + rawVerb[end+1:]
496}
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
new file mode 100644
index 0000000..86876ba
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
@@ -0,0 +1,358 @@
1// line 1 "format_fsm.rl"
2// This file is generated from format_fsm.rl. DO NOT EDIT.
3
4// line 5 "format_fsm.rl"
5
6package stdlib
7
8import (
9 "bytes"
10 "fmt"
11 "unicode/utf8"
12
13 "github.com/zclconf/go-cty/cty"
14)
15
16// line 20 "format_fsm.go"
17var _formatfsm_actions []byte = []byte{
18 0, 1, 0, 1, 1, 1, 2, 1, 4,
19 1, 5, 1, 6, 1, 7, 1, 8,
20 1, 9, 1, 10, 1, 11, 1, 14,
21 1, 16, 1, 17, 1, 18, 2, 3,
22 4, 2, 12, 10, 2, 12, 16, 2,
23 12, 18, 2, 13, 14, 2, 15, 10,
24 2, 15, 18,
25}
26
27var _formatfsm_key_offsets []byte = []byte{
28 0, 0, 14, 27, 34, 36, 39, 43,
29 51,
30}
31
32var _formatfsm_trans_keys []byte = []byte{
33 32, 35, 37, 43, 45, 46, 48, 91,
34 49, 57, 65, 90, 97, 122, 32, 35,
35 43, 45, 46, 48, 91, 49, 57, 65,
36 90, 97, 122, 91, 48, 57, 65, 90,
37 97, 122, 49, 57, 93, 48, 57, 65,
38 90, 97, 122, 46, 91, 48, 57, 65,
39 90, 97, 122, 37,
40}
41
42var _formatfsm_single_lengths []byte = []byte{
43 0, 8, 7, 1, 0, 1, 0, 2,
44 1,
45}
46
47var _formatfsm_range_lengths []byte = []byte{
48 0, 3, 3, 3, 1, 1, 2, 3,
49 0,
50}
51
52var _formatfsm_index_offsets []byte = []byte{
53 0, 0, 12, 23, 28, 30, 33, 36,
54 42,
55}
56
57var _formatfsm_indicies []byte = []byte{
58 1, 2, 3, 4, 5, 6, 7, 10,
59 8, 9, 9, 0, 1, 2, 4, 5,
60 6, 7, 10, 8, 9, 9, 0, 13,
61 11, 12, 12, 0, 14, 0, 15, 14,
62 0, 9, 9, 0, 16, 19, 17, 18,
63 18, 0, 20, 3,
64}
65
66var _formatfsm_trans_targs []byte = []byte{
67 0, 2, 2, 8, 2, 2, 3, 2,
68 7, 8, 4, 3, 8, 4, 5, 6,
69 3, 7, 8, 4, 1,
70}
71
72var _formatfsm_trans_actions []byte = []byte{
73 7, 17, 9, 3, 15, 13, 25, 11,
74 43, 29, 19, 27, 49, 46, 21, 0,
75 37, 23, 40, 34, 1,
76}
77
78var _formatfsm_eof_actions []byte = []byte{
79 0, 31, 31, 31, 31, 31, 31, 31,
80 5,
81}
82
83const formatfsm_start int = 8
84const formatfsm_first_final int = 8
85const formatfsm_error int = 0
86
87const formatfsm_en_main int = 8
88
89// line 19 "format_fsm.rl"
90
91func formatFSM(format string, a []cty.Value) (string, error) {
92 var buf bytes.Buffer
93 data := format
94 nextArg := 1 // arg numbers are 1-based
95 var verb formatVerb
96
97 // line 153 "format_fsm.rl"
98
99 // Ragel state
100 p := 0 // "Pointer" into data
101 pe := len(data) // End-of-data "pointer"
102 cs := 0 // current state (will be initialized by ragel-generated code)
103 ts := 0
104 te := 0
105 eof := pe
106
107 // Keep Go compiler happy even if generated code doesn't use these
108 _ = ts
109 _ = te
110 _ = eof
111
112 // line 121 "format_fsm.go"
113 {
114 cs = formatfsm_start
115 }
116
117 // line 126 "format_fsm.go"
118 {
119 var _klen int
120 var _trans int
121 var _acts int
122 var _nacts uint
123 var _keys int
124 if p == pe {
125 goto _test_eof
126 }
127 if cs == 0 {
128 goto _out
129 }
130 _resume:
131 _keys = int(_formatfsm_key_offsets[cs])
132 _trans = int(_formatfsm_index_offsets[cs])
133
134 _klen = int(_formatfsm_single_lengths[cs])
135 if _klen > 0 {
136 _lower := int(_keys)
137 var _mid int
138 _upper := int(_keys + _klen - 1)
139 for {
140 if _upper < _lower {
141 break
142 }
143
144 _mid = _lower + ((_upper - _lower) >> 1)
145 switch {
146 case data[p] < _formatfsm_trans_keys[_mid]:
147 _upper = _mid - 1
148 case data[p] > _formatfsm_trans_keys[_mid]:
149 _lower = _mid + 1
150 default:
151 _trans += int(_mid - int(_keys))
152 goto _match
153 }
154 }
155 _keys += _klen
156 _trans += _klen
157 }
158
159 _klen = int(_formatfsm_range_lengths[cs])
160 if _klen > 0 {
161 _lower := int(_keys)
162 var _mid int
163 _upper := int(_keys + (_klen << 1) - 2)
164 for {
165 if _upper < _lower {
166 break
167 }
168
169 _mid = _lower + (((_upper - _lower) >> 1) & ^1)
170 switch {
171 case data[p] < _formatfsm_trans_keys[_mid]:
172 _upper = _mid - 2
173 case data[p] > _formatfsm_trans_keys[_mid+1]:
174 _lower = _mid + 2
175 default:
176 _trans += int((_mid - int(_keys)) >> 1)
177 goto _match
178 }
179 }
180 _trans += _klen
181 }
182
183 _match:
184 _trans = int(_formatfsm_indicies[_trans])
185 cs = int(_formatfsm_trans_targs[_trans])
186
187 if _formatfsm_trans_actions[_trans] == 0 {
188 goto _again
189 }
190
191 _acts = int(_formatfsm_trans_actions[_trans])
192 _nacts = uint(_formatfsm_actions[_acts])
193 _acts++
194 for ; _nacts > 0; _nacts-- {
195 _acts++
196 switch _formatfsm_actions[_acts-1] {
197 case 0:
198 // line 29 "format_fsm.rl"
199
200 verb = formatVerb{
201 ArgNum: nextArg,
202 Prec: -1,
203 Width: -1,
204 }
205 ts = p
206
207 case 1:
208 // line 38 "format_fsm.rl"
209
210 buf.WriteByte(data[p])
211
212 case 4:
213 // line 49 "format_fsm.rl"
214
215 // We'll try to slurp a whole UTF-8 sequence here, to give the user
216 // better feedback.
217 r, _ := utf8.DecodeRuneInString(data[p:])
218 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
219
220 case 5:
221 // line 56 "format_fsm.rl"
222
223 verb.Sharp = true
224
225 case 6:
226 // line 59 "format_fsm.rl"
227
228 verb.Zero = true
229
230 case 7:
231 // line 62 "format_fsm.rl"
232
233 verb.Minus = true
234
235 case 8:
236 // line 65 "format_fsm.rl"
237
238 verb.Plus = true
239
240 case 9:
241 // line 68 "format_fsm.rl"
242
243 verb.Space = true
244
245 case 10:
246 // line 72 "format_fsm.rl"
247
248 verb.ArgNum = 0
249
250 case 11:
251 // line 75 "format_fsm.rl"
252
253 verb.ArgNum = (10 * verb.ArgNum) + (int(data[p]) - '0')
254
255 case 12:
256 // line 79 "format_fsm.rl"
257
258 verb.HasWidth = true
259
260 case 13:
261 // line 82 "format_fsm.rl"
262
263 verb.Width = 0
264
265 case 14:
266 // line 85 "format_fsm.rl"
267
268 verb.Width = (10 * verb.Width) + (int(data[p]) - '0')
269
270 case 15:
271 // line 89 "format_fsm.rl"
272
273 verb.HasPrec = true
274
275 case 16:
276 // line 92 "format_fsm.rl"
277
278 verb.Prec = 0
279
280 case 17:
281 // line 95 "format_fsm.rl"
282
283 verb.Prec = (10 * verb.Prec) + (int(data[p]) - '0')
284
285 case 18:
286 // line 99 "format_fsm.rl"
287
288 verb.Mode = rune(data[p])
289 te = p + 1
290 verb.Raw = data[ts:te]
291 verb.Offset = ts
292
293 err := formatAppend(&verb, &buf, a)
294 if err != nil {
295 return buf.String(), err
296 }
297 nextArg = verb.ArgNum + 1
298
299 // line 324 "format_fsm.go"
300 }
301 }
302
303 _again:
304 if cs == 0 {
305 goto _out
306 }
307 p++
308 if p != pe {
309 goto _resume
310 }
311 _test_eof:
312 {
313 }
314 if p == eof {
315 __acts := _formatfsm_eof_actions[cs]
316 __nacts := uint(_formatfsm_actions[__acts])
317 __acts++
318 for ; __nacts > 0; __nacts-- {
319 __acts++
320 switch _formatfsm_actions[__acts-1] {
321 case 2:
322 // line 42 "format_fsm.rl"
323
324 case 3:
325 // line 45 "format_fsm.rl"
326
327 return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
328
329 case 4:
330 // line 49 "format_fsm.rl"
331
332 // We'll try to slurp a whole UTF-8 sequence here, to give the user
333 // better feedback.
334 r, _ := utf8.DecodeRuneInString(data[p:])
335 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
336
337 // line 363 "format_fsm.go"
338 }
339 }
340 }
341
342 _out:
343 {
344 }
345 }
346
347 // line 171 "format_fsm.rl"
348
349 // 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
351 // be impossible (the scanner matches all bytes _somehow_) but we'll
352 // flag it anyway rather than just losing data from the end.
353 if cs < formatfsm_first_final {
354 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %i", p)
355 }
356
357 return buf.String(), nil
358}
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
new file mode 100644
index 0000000..85d43bb
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
@@ -0,0 +1,182 @@
1// This file is generated from format_fsm.rl. DO NOT EDIT.
2%%{
3 # (except you are actually in scan_tokens.rl here, so edit away!)
4 machine formatfsm;
5}%%
6
7package stdlib
8
9import (
10 "bytes"
11 "fmt"
12 "unicode/utf8"
13
14 "github.com/zclconf/go-cty/cty"
15)
16
17%%{
18 write data;
19}%%
20
21func formatFSM(format string, a []cty.Value) (string, error) {
22 var buf bytes.Buffer
23 data := format
24 nextArg := 1 // arg numbers are 1-based
25 var verb formatVerb
26
27 %%{
28
29 action begin {
30 verb = formatVerb{
31 ArgNum: nextArg,
32 Prec: -1,
33 Width: -1,
34 }
35 ts = p
36 }
37
38 action emit {
39 buf.WriteByte(fc);
40 }
41
42 action finish_ok {
43 }
44
45 action finish_err {
46 return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
47 }
48
49 action err_char {
50 // We'll try to slurp a whole UTF-8 sequence here, to give the user
51 // better feedback.
52 r, _ := utf8.DecodeRuneInString(data[p:])
53 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
54 }
55
56 action flag_sharp {
57 verb.Sharp = true
58 }
59 action flag_zero {
60 verb.Zero = true
61 }
62 action flag_minus {
63 verb.Minus = true
64 }
65 action flag_plus {
66 verb.Plus = true
67 }
68 action flag_space {
69 verb.Space = true
70 }
71
72 action argidx_reset {
73 verb.ArgNum = 0
74 }
75 action argidx_num {
76 verb.ArgNum = (10 * verb.ArgNum) + (int(fc) - '0')
77 }
78
79 action has_width {
80 verb.HasWidth = true
81 }
82 action width_reset {
83 verb.Width = 0
84 }
85 action width_num {
86 verb.Width = (10 * verb.Width) + (int(fc) - '0')
87 }
88
89 action has_prec {
90 verb.HasPrec = true
91 }
92 action prec_reset {
93 verb.Prec = 0
94 }
95 action prec_num {
96 verb.Prec = (10 * verb.Prec) + (int(fc) - '0')
97 }
98
99 action mode {
100 verb.Mode = rune(fc)
101 te = p+1
102 verb.Raw = data[ts:te]
103 verb.Offset = ts
104
105 err := formatAppend(&verb, &buf, a)
106 if err != nil {
107 return buf.String(), err
108 }
109 nextArg = verb.ArgNum + 1
110 }
111
112 # a number that isn't zero and doesn't have a leading zero
113 num = [1-9] [0-9]*;
114
115 flags = (
116 '0' @flag_zero |
117 '#' @flag_sharp |
118 '-' @flag_minus |
119 '+' @flag_plus |
120 ' ' @flag_space
121 )*;
122
123 argidx = ((
124 '[' (num $argidx_num) ']'
125 ) >argidx_reset)?;
126
127 width = (
128 ( num $width_num ) >width_reset %has_width
129 )?;
130
131 precision = (
132 ('.' ( digit* $prec_num )) >prec_reset %has_prec
133 )?;
134
135 # We accept any letter here, but will be more picky in formatAppend
136 mode = ('a'..'z' | 'A'..'Z') @mode;
137
138 fmt_verb = (
139 '%' @begin
140 flags
141 width
142 precision
143 argidx
144 mode
145 );
146
147 main := (
148 [^%] @emit |
149 '%%' @emit |
150 fmt_verb
151 )* @/finish_err %/finish_ok $!err_char;
152
153 }%%
154
155 // Ragel state
156 p := 0 // "Pointer" into data
157 pe := len(data) // End-of-data "pointer"
158 cs := 0 // current state (will be initialized by ragel-generated code)
159 ts := 0
160 te := 0
161 eof := pe
162
163 // Keep Go compiler happy even if generated code doesn't use these
164 _ = ts
165 _ = te
166 _ = eof
167
168 %%{
169 write init;
170 write exec;
171 }%%
172
173 // If we fall out here without being in a final state then we've
174 // encountered something that the scanner can't match, which should
175 // be impossible (the scanner matches all bytes _somehow_) but we'll
176 // flag it anyway rather than just losing data from the end.
177 if cs < formatfsm_first_final {
178 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %i", p)
179 }
180
181 return buf.String(), nil
182}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go
new file mode 100644
index 0000000..6b31f26
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go
@@ -0,0 +1,107 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/convert"
8 "github.com/zclconf/go-cty/cty/function"
9)
10
11var EqualFunc = function.New(&function.Spec{
12 Params: []function.Parameter{
13 {
14 Name: "a",
15 Type: cty.DynamicPseudoType,
16 AllowUnknown: true,
17 AllowDynamicType: true,
18 AllowNull: true,
19 },
20 {
21 Name: "b",
22 Type: cty.DynamicPseudoType,
23 AllowUnknown: true,
24 AllowDynamicType: true,
25 AllowNull: true,
26 },
27 },
28 Type: function.StaticReturnType(cty.Bool),
29 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
30 return args[0].Equals(args[1]), nil
31 },
32})
33
34var NotEqualFunc = function.New(&function.Spec{
35 Params: []function.Parameter{
36 {
37 Name: "a",
38 Type: cty.DynamicPseudoType,
39 AllowUnknown: true,
40 AllowDynamicType: true,
41 AllowNull: true,
42 },
43 {
44 Name: "b",
45 Type: cty.DynamicPseudoType,
46 AllowUnknown: true,
47 AllowDynamicType: true,
48 AllowNull: true,
49 },
50 },
51 Type: function.StaticReturnType(cty.Bool),
52 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
53 return args[0].Equals(args[1]).Not(), nil
54 },
55})
56
57var CoalesceFunc = function.New(&function.Spec{
58 Params: []function.Parameter{},
59 VarParam: &function.Parameter{
60 Name: "vals",
61 Type: cty.DynamicPseudoType,
62 AllowUnknown: true,
63 AllowDynamicType: true,
64 AllowNull: true,
65 },
66 Type: func(args []cty.Value) (ret cty.Type, err error) {
67 argTypes := make([]cty.Type, len(args))
68 for i, val := range args {
69 argTypes[i] = val.Type()
70 }
71 retType, _ := convert.UnifyUnsafe(argTypes)
72 if retType == cty.NilType {
73 return cty.NilType, fmt.Errorf("all arguments must have the same type")
74 }
75 return retType, nil
76 },
77 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
78 for _, argVal := range args {
79 if !argVal.IsKnown() {
80 return cty.UnknownVal(retType), nil
81 }
82 if argVal.IsNull() {
83 continue
84 }
85
86 return convert.Convert(argVal, retType)
87 }
88 return cty.NilVal, fmt.Errorf("no non-null arguments")
89 },
90})
91
92// Equal determines whether the two given values are equal, returning a
93// bool value.
94func Equal(a cty.Value, b cty.Value) (cty.Value, error) {
95 return EqualFunc.Call([]cty.Value{a, b})
96}
97
98// NotEqual is the opposite of Equal.
99func NotEqual(a cty.Value, b cty.Value) (cty.Value, error) {
100 return NotEqualFunc.Call([]cty.Value{a, b})
101}
102
103// Coalesce returns the first of the given arguments that is not null. If
104// all arguments are null, an error is produced.
105func Coalesce(vals ...cty.Value) (cty.Value, error) {
106 return CoalesceFunc.Call(vals)
107}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go
new file mode 100644
index 0000000..07901c6
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go
@@ -0,0 +1,72 @@
1package stdlib
2
3import (
4 "github.com/zclconf/go-cty/cty"
5 "github.com/zclconf/go-cty/cty/function"
6 "github.com/zclconf/go-cty/cty/json"
7)
8
9var JSONEncodeFunc = function.New(&function.Spec{
10 Params: []function.Parameter{
11 {
12 Name: "val",
13 Type: cty.DynamicPseudoType,
14 AllowDynamicType: true,
15 },
16 },
17 Type: function.StaticReturnType(cty.String),
18 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
19 val := args[0]
20 if !val.IsWhollyKnown() {
21 // We can't serialize unknowns, so if the value is unknown or
22 // contains any _nested_ unknowns then our result must be
23 // unknown.
24 return cty.UnknownVal(retType), nil
25 }
26
27 buf, err := json.Marshal(val, val.Type())
28 if err != nil {
29 return cty.NilVal, err
30 }
31
32 return cty.StringVal(string(buf)), nil
33 },
34})
35
36var JSONDecodeFunc = function.New(&function.Spec{
37 Params: []function.Parameter{
38 {
39 Name: "str",
40 Type: cty.String,
41 },
42 },
43 Type: func(args []cty.Value) (cty.Type, error) {
44 str := args[0]
45 if !str.IsKnown() {
46 return cty.DynamicPseudoType, nil
47 }
48
49 buf := []byte(str.AsString())
50 return json.ImpliedType(buf)
51 },
52 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
53 buf := []byte(args[0].AsString())
54 return json.Unmarshal(buf, retType)
55 },
56})
57
58// JSONEncode returns a JSON serialization of the given value.
59func JSONEncode(val cty.Value) (cty.Value, error) {
60 return JSONEncodeFunc.Call([]cty.Value{val})
61}
62
63// JSONDecode parses the given JSON string and, if it is valid, returns the
64// value it represents.
65//
66// Note that applying JSONDecode to the result of JSONEncode may not produce
67// an identically-typed result, since JSON encoding is lossy for cty Types.
68// The resulting value will consist only of primitive types, object types, and
69// tuple types.
70func JSONDecode(str cty.Value) (cty.Value, error) {
71 return JSONDecodeFunc.Call([]cty.Value{str})
72}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
new file mode 100644
index 0000000..bd9b2e5
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
@@ -0,0 +1,428 @@
1package stdlib
2
3import (
4 "fmt"
5 "math/big"
6
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/function"
9)
10
11var AbsoluteFunc = function.New(&function.Spec{
12 Params: []function.Parameter{
13 {
14 Name: "num",
15 Type: cty.Number,
16 AllowDynamicType: true,
17 },
18 },
19 Type: function.StaticReturnType(cty.Number),
20 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
21 return args[0].Absolute(), nil
22 },
23})
24
25var AddFunc = function.New(&function.Spec{
26 Params: []function.Parameter{
27 {
28 Name: "a",
29 Type: cty.Number,
30 AllowDynamicType: true,
31 },
32 {
33 Name: "b",
34 Type: cty.Number,
35 AllowDynamicType: true,
36 },
37 },
38 Type: function.StaticReturnType(cty.Number),
39 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
40 // big.Float.Add can panic if the input values are opposing infinities,
41 // so we must catch that here in order to remain within
42 // the cty Function abstraction.
43 defer func() {
44 if r := recover(); r != nil {
45 if _, ok := r.(big.ErrNaN); ok {
46 ret = cty.NilVal
47 err = fmt.Errorf("can't compute sum of opposing infinities")
48 } else {
49 // not a panic we recognize
50 panic(r)
51 }
52 }
53 }()
54 return args[0].Add(args[1]), nil
55 },
56})
57
58var SubtractFunc = function.New(&function.Spec{
59 Params: []function.Parameter{
60 {
61 Name: "a",
62 Type: cty.Number,
63 AllowDynamicType: true,
64 },
65 {
66 Name: "b",
67 Type: cty.Number,
68 AllowDynamicType: true,
69 },
70 },
71 Type: function.StaticReturnType(cty.Number),
72 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
73 // big.Float.Sub can panic if the input values are infinities,
74 // so we must catch that here in order to remain within
75 // the cty Function abstraction.
76 defer func() {
77 if r := recover(); r != nil {
78 if _, ok := r.(big.ErrNaN); ok {
79 ret = cty.NilVal
80 err = fmt.Errorf("can't subtract infinity from itself")
81 } else {
82 // not a panic we recognize
83 panic(r)
84 }
85 }
86 }()
87 return args[0].Subtract(args[1]), nil
88 },
89})
90
91var MultiplyFunc = function.New(&function.Spec{
92 Params: []function.Parameter{
93 {
94 Name: "a",
95 Type: cty.Number,
96 AllowDynamicType: true,
97 },
98 {
99 Name: "b",
100 Type: cty.Number,
101 AllowDynamicType: true,
102 },
103 },
104 Type: function.StaticReturnType(cty.Number),
105 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
106 // big.Float.Mul can panic if the input values are both zero or both
107 // infinity, so we must catch that here in order to remain within
108 // the cty Function abstraction.
109 defer func() {
110 if r := recover(); r != nil {
111 if _, ok := r.(big.ErrNaN); ok {
112 ret = cty.NilVal
113 err = fmt.Errorf("can't multiply zero by infinity")
114 } else {
115 // not a panic we recognize
116 panic(r)
117 }
118 }
119 }()
120
121 return args[0].Multiply(args[1]), nil
122 },
123})
124
125var DivideFunc = function.New(&function.Spec{
126 Params: []function.Parameter{
127 {
128 Name: "a",
129 Type: cty.Number,
130 AllowDynamicType: true,
131 },
132 {
133 Name: "b",
134 Type: cty.Number,
135 AllowDynamicType: true,
136 },
137 },
138 Type: function.StaticReturnType(cty.Number),
139 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
140 // big.Float.Quo can panic if the input values are both zero or both
141 // infinity, so we must catch that here in order to remain within
142 // the cty Function abstraction.
143 defer func() {
144 if r := recover(); r != nil {
145 if _, ok := r.(big.ErrNaN); ok {
146 ret = cty.NilVal
147 err = fmt.Errorf("can't divide zero by zero or infinity by infinity")
148 } else {
149 // not a panic we recognize
150 panic(r)
151 }
152 }
153 }()
154
155 return args[0].Divide(args[1]), nil
156 },
157})
158
159var ModuloFunc = function.New(&function.Spec{
160 Params: []function.Parameter{
161 {
162 Name: "a",
163 Type: cty.Number,
164 AllowDynamicType: true,
165 },
166 {
167 Name: "b",
168 Type: cty.Number,
169 AllowDynamicType: true,
170 },
171 },
172 Type: function.StaticReturnType(cty.Number),
173 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
174 // big.Float.Mul can panic if the input values are both zero or both
175 // infinity, so we must catch that here in order to remain within
176 // the cty Function abstraction.
177 defer func() {
178 if r := recover(); r != nil {
179 if _, ok := r.(big.ErrNaN); ok {
180 ret = cty.NilVal
181 err = fmt.Errorf("can't use modulo with zero and infinity")
182 } else {
183 // not a panic we recognize
184 panic(r)
185 }
186 }
187 }()
188
189 return args[0].Modulo(args[1]), nil
190 },
191})
192
193var GreaterThanFunc = function.New(&function.Spec{
194 Params: []function.Parameter{
195 {
196 Name: "a",
197 Type: cty.Number,
198 AllowDynamicType: true,
199 },
200 {
201 Name: "b",
202 Type: cty.Number,
203 AllowDynamicType: true,
204 },
205 },
206 Type: function.StaticReturnType(cty.Bool),
207 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
208 return args[0].GreaterThan(args[1]), nil
209 },
210})
211
212var GreaterThanOrEqualToFunc = function.New(&function.Spec{
213 Params: []function.Parameter{
214 {
215 Name: "a",
216 Type: cty.Number,
217 AllowDynamicType: true,
218 },
219 {
220 Name: "b",
221 Type: cty.Number,
222 AllowDynamicType: true,
223 },
224 },
225 Type: function.StaticReturnType(cty.Bool),
226 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
227 return args[0].GreaterThanOrEqualTo(args[1]), nil
228 },
229})
230
231var LessThanFunc = function.New(&function.Spec{
232 Params: []function.Parameter{
233 {
234 Name: "a",
235 Type: cty.Number,
236 AllowDynamicType: true,
237 },
238 {
239 Name: "b",
240 Type: cty.Number,
241 AllowDynamicType: true,
242 },
243 },
244 Type: function.StaticReturnType(cty.Bool),
245 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
246 return args[0].LessThan(args[1]), nil
247 },
248})
249
250var LessThanOrEqualToFunc = function.New(&function.Spec{
251 Params: []function.Parameter{
252 {
253 Name: "a",
254 Type: cty.Number,
255 AllowDynamicType: true,
256 },
257 {
258 Name: "b",
259 Type: cty.Number,
260 AllowDynamicType: true,
261 },
262 },
263 Type: function.StaticReturnType(cty.Bool),
264 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
265 return args[0].LessThanOrEqualTo(args[1]), nil
266 },
267})
268
269var NegateFunc = function.New(&function.Spec{
270 Params: []function.Parameter{
271 {
272 Name: "num",
273 Type: cty.Number,
274 AllowDynamicType: true,
275 },
276 },
277 Type: function.StaticReturnType(cty.Number),
278 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
279 return args[0].Negate(), nil
280 },
281})
282
283var MinFunc = function.New(&function.Spec{
284 Params: []function.Parameter{},
285 VarParam: &function.Parameter{
286 Name: "numbers",
287 Type: cty.Number,
288 AllowDynamicType: true,
289 },
290 Type: function.StaticReturnType(cty.Number),
291 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
292 if len(args) == 0 {
293 return cty.NilVal, fmt.Errorf("must pass at least one number")
294 }
295
296 min := cty.PositiveInfinity
297 for _, num := range args {
298 if num.LessThan(min).True() {
299 min = num
300 }
301 }
302
303 return min, nil
304 },
305})
306
307var MaxFunc = function.New(&function.Spec{
308 Params: []function.Parameter{},
309 VarParam: &function.Parameter{
310 Name: "numbers",
311 Type: cty.Number,
312 AllowDynamicType: true,
313 },
314 Type: function.StaticReturnType(cty.Number),
315 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
316 if len(args) == 0 {
317 return cty.NilVal, fmt.Errorf("must pass at least one number")
318 }
319
320 max := cty.NegativeInfinity
321 for _, num := range args {
322 if num.GreaterThan(max).True() {
323 max = num
324 }
325 }
326
327 return max, nil
328 },
329})
330
331var IntFunc = function.New(&function.Spec{
332 Params: []function.Parameter{
333 {
334 Name: "num",
335 Type: cty.Number,
336 AllowDynamicType: true,
337 },
338 },
339 Type: function.StaticReturnType(cty.Number),
340 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
341 bf := args[0].AsBigFloat()
342 if bf.IsInt() {
343 return args[0], nil
344 }
345 bi, _ := bf.Int(nil)
346 bf = (&big.Float{}).SetInt(bi)
347 return cty.NumberVal(bf), nil
348 },
349})
350
351// Absolute returns the magnitude of the given number, without its sign.
352// That is, it turns negative values into positive values.
353func Absolute(num cty.Value) (cty.Value, error) {
354 return AbsoluteFunc.Call([]cty.Value{num})
355}
356
357// Add returns the sum of the two given numbers.
358func Add(a cty.Value, b cty.Value) (cty.Value, error) {
359 return AddFunc.Call([]cty.Value{a, b})
360}
361
362// Subtract returns the difference between the two given numbers.
363func Subtract(a cty.Value, b cty.Value) (cty.Value, error) {
364 return SubtractFunc.Call([]cty.Value{a, b})
365}
366
367// Multiply returns the product of the two given numbers.
368func Multiply(a cty.Value, b cty.Value) (cty.Value, error) {
369 return MultiplyFunc.Call([]cty.Value{a, b})
370}
371
372// Divide returns a divided by b, where both a and b are numbers.
373func Divide(a cty.Value, b cty.Value) (cty.Value, error) {
374 return DivideFunc.Call([]cty.Value{a, b})
375}
376
377// Negate returns the given number multipled by -1.
378func Negate(num cty.Value) (cty.Value, error) {
379 return NegateFunc.Call([]cty.Value{num})
380}
381
382// LessThan returns true if a is less than b.
383func LessThan(a cty.Value, b cty.Value) (cty.Value, error) {
384 return LessThanFunc.Call([]cty.Value{a, b})
385}
386
387// LessThanOrEqualTo returns true if a is less than b.
388func LessThanOrEqualTo(a cty.Value, b cty.Value) (cty.Value, error) {
389 return LessThanOrEqualToFunc.Call([]cty.Value{a, b})
390}
391
392// GreaterThan returns true if a is less than b.
393func GreaterThan(a cty.Value, b cty.Value) (cty.Value, error) {
394 return GreaterThanFunc.Call([]cty.Value{a, b})
395}
396
397// GreaterThanOrEqualTo returns true if a is less than b.
398func GreaterThanOrEqualTo(a cty.Value, b cty.Value) (cty.Value, error) {
399 return GreaterThanOrEqualToFunc.Call([]cty.Value{a, b})
400}
401
402// Modulo returns the remainder of a divided by b under integer division,
403// where both a and b are numbers.
404func Modulo(a cty.Value, b cty.Value) (cty.Value, error) {
405 return ModuloFunc.Call([]cty.Value{a, b})
406}
407
408// Min returns the minimum number from the given numbers.
409func Min(numbers ...cty.Value) (cty.Value, error) {
410 return MinFunc.Call(numbers)
411}
412
413// Max returns the maximum number from the given numbers.
414func Max(numbers ...cty.Value) (cty.Value, error) {
415 return MaxFunc.Call(numbers)
416}
417
418// Int removes the fractional component of the given number returning an
419// integer representing the whole number component, rounding towards zero.
420// For example, -1.5 becomes -1.
421//
422// If an infinity is passed to Int, an error is returned.
423func Int(num cty.Value) (cty.Value, error) {
424 if num == cty.PositiveInfinity || num == cty.NegativeInfinity {
425 return cty.NilVal, fmt.Errorf("can't truncate infinity to an integer")
426 }
427 return IntFunc.Call([]cty.Value{num})
428}
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
new file mode 100644
index 0000000..e2c77c5
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
@@ -0,0 +1,130 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/convert"
8 "github.com/zclconf/go-cty/cty/function"
9)
10
11var ConcatFunc = function.New(&function.Spec{
12 Params: []function.Parameter{},
13 VarParam: &function.Parameter{
14 Name: "seqs",
15 Type: cty.DynamicPseudoType,
16 },
17 Type: func(args []cty.Value) (ret cty.Type, err error) {
18 if len(args) == 0 {
19 return cty.NilType, fmt.Errorf("at least one argument is required")
20 }
21
22 if args[0].Type().IsListType() {
23 // Possibly we're going to return a list, if all of our other
24 // args are also lists and we can find a common element type.
25 tys := make([]cty.Type, len(args))
26 for i, val := range args {
27 ty := val.Type()
28 if !ty.IsListType() {
29 tys = nil
30 break
31 }
32 tys[i] = ty
33 }
34
35 if tys != nil {
36 commonType, _ := convert.UnifyUnsafe(tys)
37 if commonType != cty.NilType {
38 return commonType, nil
39 }
40 }
41 }
42
43 etys := make([]cty.Type, 0, len(args))
44 for i, val := range args {
45 ety := val.Type()
46 switch {
47 case ety.IsTupleType():
48 etys = append(etys, ety.TupleElementTypes()...)
49 case ety.IsListType():
50 if !val.IsKnown() {
51 // We need to know the list to count its elements to
52 // build our tuple type, so any concat of an unknown
53 // list can't be typed yet.
54 return cty.DynamicPseudoType, nil
55 }
56
57 l := val.LengthInt()
58 subEty := ety.ElementType()
59 for j := 0; j < l; j++ {
60 etys = append(etys, subEty)
61 }
62 default:
63 return cty.NilType, function.NewArgErrorf(
64 i, "all arguments must be lists or tuples; got %s",
65 ety.FriendlyName(),
66 )
67 }
68 }
69 return cty.Tuple(etys), nil
70 },
71 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
72 switch {
73 case retType.IsListType():
74 // If retType is a list type then we know that all of the
75 // given values will be lists and that they will either be of
76 // retType or of something we can convert to retType.
77 vals := make([]cty.Value, 0, len(args))
78 for i, list := range args {
79 list, err = convert.Convert(list, retType)
80 if err != nil {
81 // Conversion might fail because we used UnifyUnsafe
82 // to choose our return type.
83 return cty.NilVal, function.NewArgError(i, err)
84 }
85
86 it := list.ElementIterator()
87 for it.Next() {
88 _, v := it.Element()
89 vals = append(vals, v)
90 }
91 }
92 if len(vals) == 0 {
93 return cty.ListValEmpty(retType.ElementType()), nil
94 }
95
96 return cty.ListVal(vals), nil
97 case retType.IsTupleType():
98 // If retType is a tuple type then we could have a mixture of
99 // lists and tuples but we know they all have known values
100 // (because our params don't AllowUnknown) and we know that
101 // concatenating them all together will produce a tuple of
102 // retType because of the work we did in the Type function above.
103 vals := make([]cty.Value, 0, len(args))
104
105 for _, seq := range args {
106 // Both lists and tuples support ElementIterator, so this is easy.
107 it := seq.ElementIterator()
108 for it.Next() {
109 _, v := it.Element()
110 vals = append(vals, v)
111 }
112 }
113
114 return cty.TupleVal(vals), nil
115 default:
116 // should never happen if Type is working correctly above
117 panic("unsupported return type")
118 }
119 },
120})
121
122// Concat takes one or more sequences (lists or tuples) and returns the single
123// sequence that results from concatenating them together in order.
124//
125// If all of the given sequences are lists of the same element type then the
126// result is a list of that type. Otherwise, the result is a of a tuple type
127// constructed from the given sequence types.
128func Concat(seqs ...cty.Value) (cty.Value, error) {
129 return ConcatFunc.Call(seqs)
130}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go
new file mode 100644
index 0000000..100078f
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go
@@ -0,0 +1,195 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty/convert"
7
8 "github.com/zclconf/go-cty/cty"
9 "github.com/zclconf/go-cty/cty/function"
10)
11
12var SetHasElementFunc = function.New(&function.Spec{
13 Params: []function.Parameter{
14 {
15 Name: "set",
16 Type: cty.Set(cty.DynamicPseudoType),
17 AllowDynamicType: true,
18 },
19 {
20 Name: "elem",
21 Type: cty.DynamicPseudoType,
22 AllowDynamicType: true,
23 },
24 },
25 Type: function.StaticReturnType(cty.Bool),
26 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
27 return args[0].HasElement(args[1]), nil
28 },
29})
30
31var SetUnionFunc = function.New(&function.Spec{
32 Params: []function.Parameter{
33 {
34 Name: "first_set",
35 Type: cty.Set(cty.DynamicPseudoType),
36 AllowDynamicType: true,
37 },
38 },
39 VarParam: &function.Parameter{
40 Name: "other_sets",
41 Type: cty.Set(cty.DynamicPseudoType),
42 AllowDynamicType: true,
43 },
44 Type: setOperationReturnType,
45 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
46 return s1.Union(s2)
47 }),
48})
49
50var SetIntersectionFunc = function.New(&function.Spec{
51 Params: []function.Parameter{
52 {
53 Name: "first_set",
54 Type: cty.Set(cty.DynamicPseudoType),
55 AllowDynamicType: true,
56 },
57 },
58 VarParam: &function.Parameter{
59 Name: "other_sets",
60 Type: cty.Set(cty.DynamicPseudoType),
61 AllowDynamicType: true,
62 },
63 Type: setOperationReturnType,
64 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
65 return s1.Intersection(s2)
66 }),
67})
68
69var SetSubtractFunc = function.New(&function.Spec{
70 Params: []function.Parameter{
71 {
72 Name: "a",
73 Type: cty.Set(cty.DynamicPseudoType),
74 AllowDynamicType: true,
75 },
76 {
77 Name: "b",
78 Type: cty.Set(cty.DynamicPseudoType),
79 AllowDynamicType: true,
80 },
81 },
82 Type: setOperationReturnType,
83 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
84 return s1.Subtract(s2)
85 }),
86})
87
88var SetSymmetricDifferenceFunc = function.New(&function.Spec{
89 Params: []function.Parameter{
90 {
91 Name: "first_set",
92 Type: cty.Set(cty.DynamicPseudoType),
93 AllowDynamicType: true,
94 },
95 },
96 VarParam: &function.Parameter{
97 Name: "other_sets",
98 Type: cty.Set(cty.DynamicPseudoType),
99 AllowDynamicType: true,
100 },
101 Type: setOperationReturnType,
102 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
103 return s1.Subtract(s2)
104 }),
105})
106
107// SetHasElement determines whether the given set contains the given value as an
108// element.
109func SetHasElement(set cty.Value, elem cty.Value) (cty.Value, error) {
110 return SetHasElementFunc.Call([]cty.Value{set, elem})
111}
112
113// SetUnion returns a new set containing all of the elements from the given
114// sets, which must have element types that can all be converted to some
115// common type using the standard type unification rules. If conversion
116// is not possible, an error is returned.
117//
118// The union operation is performed after type conversion, which may result
119// in some previously-distinct values being conflated.
120//
121// At least one set must be provided.
122func SetUnion(sets ...cty.Value) (cty.Value, error) {
123 return SetUnionFunc.Call(sets)
124}
125
126// Intersection returns a new set containing the elements that exist
127// in all of the given sets, which must have element types that can all be
128// converted to some common type using the standard type unification rules.
129// If conversion is not possible, an error is returned.
130//
131// The intersection operation is performed after type conversion, which may
132// result in some previously-distinct values being conflated.
133//
134// At least one set must be provided.
135func SetIntersection(sets ...cty.Value) (cty.Value, error) {
136 return SetIntersectionFunc.Call(sets)
137}
138
139// SetSubtract returns a new set containing the elements from the
140// first set that are not present in the second set. The sets must have
141// element types that can both be converted to some common type using the
142// standard type unification rules. If conversion is not possible, an error
143// is returned.
144//
145// The subtract operation is performed after type conversion, which may
146// result in some previously-distinct values being conflated.
147func SetSubtract(a, b cty.Value) (cty.Value, error) {
148 return SetSubtractFunc.Call([]cty.Value{a, b})
149}
150
151// SetSymmetricDifference returns a new set containing elements that appear
152// in any of the given sets but not multiple. The sets must have
153// element types that can all be converted to some common type using the
154// standard type unification rules. If conversion is not possible, an error
155// is returned.
156//
157// The difference operation is performed after type conversion, which may
158// result in some previously-distinct values being conflated.
159func SetSymmetricDifference(sets ...cty.Value) (cty.Value, error) {
160 return SetSymmetricDifferenceFunc.Call(sets)
161}
162
163func setOperationReturnType(args []cty.Value) (ret cty.Type, err error) {
164 var etys []cty.Type
165 for _, arg := range args {
166 etys = append(etys, arg.Type().ElementType())
167 }
168 newEty, _ := convert.UnifyUnsafe(etys)
169 if newEty == cty.NilType {
170 return cty.NilType, fmt.Errorf("given sets must all have compatible element types")
171 }
172 return cty.Set(newEty), nil
173}
174
175func setOperationImpl(f func(s1, s2 cty.ValueSet) cty.ValueSet) function.ImplFunc {
176 return func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
177 first := args[0]
178 first, err = convert.Convert(first, retType)
179 if err != nil {
180 return cty.NilVal, function.NewArgError(0, err)
181 }
182
183 set := first.AsValueSet()
184 for i, arg := range args[1:] {
185 arg, err := convert.Convert(arg, retType)
186 if err != nil {
187 return cty.NilVal, function.NewArgError(i+1, err)
188 }
189
190 argSet := arg.AsValueSet()
191 set = f(set, argSet)
192 }
193 return cty.SetValFromValueSet(set), nil
194 }
195}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
new file mode 100644
index 0000000..d7c89fa
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
@@ -0,0 +1,234 @@
1package stdlib
2
3import (
4 "strings"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/function"
8 "github.com/zclconf/go-cty/cty/gocty"
9 "github.com/apparentlymart/go-textseg/textseg"
10)
11
12var UpperFunc = function.New(&function.Spec{
13 Params: []function.Parameter{
14 {
15 Name: "str",
16 Type: cty.String,
17 AllowDynamicType: true,
18 },
19 },
20 Type: function.StaticReturnType(cty.String),
21 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
22 in := args[0].AsString()
23 out := strings.ToUpper(in)
24 return cty.StringVal(out), nil
25 },
26})
27
28var LowerFunc = function.New(&function.Spec{
29 Params: []function.Parameter{
30 {
31 Name: "str",
32 Type: cty.String,
33 AllowDynamicType: true,
34 },
35 },
36 Type: function.StaticReturnType(cty.String),
37 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
38 in := args[0].AsString()
39 out := strings.ToLower(in)
40 return cty.StringVal(out), nil
41 },
42})
43
44var ReverseFunc = function.New(&function.Spec{
45 Params: []function.Parameter{
46 {
47 Name: "str",
48 Type: cty.String,
49 AllowDynamicType: true,
50 },
51 },
52 Type: function.StaticReturnType(cty.String),
53 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
54 in := []byte(args[0].AsString())
55 out := make([]byte, len(in))
56 pos := len(out)
57
58 inB := []byte(in)
59 for i := 0; i < len(in); {
60 d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
61 cluster := in[i : i+d]
62 pos -= len(cluster)
63 copy(out[pos:], cluster)
64 i += d
65 }
66
67 return cty.StringVal(string(out)), nil
68 },
69})
70
71var StrlenFunc = function.New(&function.Spec{
72 Params: []function.Parameter{
73 {
74 Name: "str",
75 Type: cty.String,
76 AllowDynamicType: true,
77 },
78 },
79 Type: function.StaticReturnType(cty.Number),
80 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
81 in := args[0].AsString()
82 l := 0
83
84 inB := []byte(in)
85 for i := 0; i < len(in); {
86 d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
87 l++
88 i += d
89 }
90
91 return cty.NumberIntVal(int64(l)), nil
92 },
93})
94
95var SubstrFunc = function.New(&function.Spec{
96 Params: []function.Parameter{
97 {
98 Name: "str",
99 Type: cty.String,
100 AllowDynamicType: true,
101 },
102 {
103 Name: "offset",
104 Type: cty.Number,
105 AllowDynamicType: true,
106 },
107 {
108 Name: "length",
109 Type: cty.Number,
110 AllowDynamicType: true,
111 },
112 },
113 Type: function.StaticReturnType(cty.String),
114 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
115 in := []byte(args[0].AsString())
116 var offset, length int
117
118 var err error
119 err = gocty.FromCtyValue(args[1], &offset)
120 if err != nil {
121 return cty.NilVal, err
122 }
123 err = gocty.FromCtyValue(args[2], &length)
124 if err != nil {
125 return cty.NilVal, err
126 }
127
128 if offset < 0 {
129 totalLenNum, err := Strlen(args[0])
130 if err != nil {
131 // should never happen
132 panic("Stdlen returned an error")
133 }
134
135 var totalLen int
136 err = gocty.FromCtyValue(totalLenNum, &totalLen)
137 if err != nil {
138 // should never happen
139 panic("Stdlen returned a non-int number")
140 }
141
142 offset += totalLen
143 }
144
145 sub := in
146 pos := 0
147 var i int
148
149 // First we'll seek forward to our offset
150 if offset > 0 {
151 for i = 0; i < len(sub); {
152 d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
153 i += d
154 pos++
155 if pos == offset {
156 break
157 }
158 if i >= len(in) {
159 return cty.StringVal(""), nil
160 }
161 }
162
163 sub = sub[i:]
164 }
165
166 if length < 0 {
167 // Taking the remainder of the string is a fast path since
168 // we can just return the rest of the buffer verbatim.
169 return cty.StringVal(string(sub)), nil
170 }
171
172 // Otherwise we need to start seeking forward again until we
173 // reach the length we want.
174 pos = 0
175 for i = 0; i < len(sub); {
176 d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
177 i += d
178 pos++
179 if pos == length {
180 break
181 }
182 }
183
184 sub = sub[:i]
185
186 return cty.StringVal(string(sub)), nil
187 },
188})
189
190// Upper is a Function that converts a given string to uppercase.
191func Upper(str cty.Value) (cty.Value, error) {
192 return UpperFunc.Call([]cty.Value{str})
193}
194
195// Lower is a Function that converts a given string to lowercase.
196func Lower(str cty.Value) (cty.Value, error) {
197 return LowerFunc.Call([]cty.Value{str})
198}
199
200// Reverse is a Function that reverses the order of the characters in the
201// given string.
202//
203// As usual, "character" for the sake of this function is a grapheme cluster,
204// so combining diacritics (for example) will be considered together as a
205// single character.
206func Reverse(str cty.Value) (cty.Value, error) {
207 return ReverseFunc.Call([]cty.Value{str})
208}
209
210// Strlen is a Function that returns the length of the given string in
211// characters.
212//
213// As usual, "character" for the sake of this function is a grapheme cluster,
214// so combining diacritics (for example) will be considered together as a
215// single character.
216func Strlen(str cty.Value) (cty.Value, error) {
217 return StrlenFunc.Call([]cty.Value{str})
218}
219
220// Substr is a Function that extracts a sequence of characters from another
221// string and creates a new string.
222//
223// As usual, "character" for the sake of this function is a grapheme cluster,
224// so combining diacritics (for example) will be considered together as a
225// single character.
226//
227// The "offset" index may be negative, in which case it is relative to the
228// end of the given string.
229//
230// The "length" may be -1, in which case the remainder of the string after
231// the given offset will be returned.
232func Substr(str cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) {
233 return SubstrFunc.Call([]cty.Value{str, offset, length})
234}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go b/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go
new file mode 100644
index 0000000..3495550
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go
@@ -0,0 +1,31 @@
1package function
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// Unpredictable wraps a given function such that it retains the same arguments
8// and type checking behavior but will return an unknown value when called.
9//
10// It is recommended that most functions be "pure", which is to say that they
11// will always produce the same value given particular input. However,
12// sometimes it is necessary to offer functions whose behavior depends on
13// some external state, such as reading a file or determining the current time.
14// In such cases, an unpredictable wrapper might be used to stand in for
15// the function during some sort of prior "checking" phase in order to delay
16// the actual effect until later.
17//
18// While Unpredictable can support a function that isn't pure in its
19// implementation, it still expects a function to be pure in its type checking
20// behavior, except for the special case of returning cty.DynamicPseudoType
21// if it is not yet able to predict its return value based on current argument
22// information.
23func Unpredictable(f Function) Function {
24 newSpec := *f.spec // shallow copy
25 newSpec.Impl = unpredictableImpl
26 return New(&newSpec)
27}
28
29func unpredictableImpl(args []cty.Value, retType cty.Type) (cty.Value, error) {
30 return cty.UnknownVal(retType), nil
31}
diff --git a/vendor/github.com/zclconf/go-cty/cty/gob.go b/vendor/github.com/zclconf/go-cty/cty/gob.go
new file mode 100644
index 0000000..3d73199
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/gob.go
@@ -0,0 +1,125 @@
1package cty
2
3import (
4 "bytes"
5 "encoding/gob"
6 "fmt"
7 "math/big"
8)
9
10// GobEncode is an implementation of the gob.GobEncoder interface, which
11// allows Values to be included in structures encoded with encoding/gob.
12//
13// Currently it is not possible to represent values of capsule types in gob,
14// because the types themselves cannot be represented.
15func (val Value) GobEncode() ([]byte, error) {
16 buf := &bytes.Buffer{}
17 enc := gob.NewEncoder(buf)
18
19 gv := gobValue{
20 Version: 0,
21 Ty: val.ty,
22 V: val.v,
23 }
24
25 err := enc.Encode(gv)
26 if err != nil {
27 return nil, fmt.Errorf("error encoding cty.Value: %s", err)
28 }
29
30 return buf.Bytes(), nil
31}
32
33// GobDecode is an implementation of the gob.GobDecoder interface, which
34// inverts the operation performed by GobEncode. See the documentation of
35// GobEncode for considerations when using cty.Value instances with gob.
36func (val *Value) GobDecode(buf []byte) error {
37 r := bytes.NewReader(buf)
38 dec := gob.NewDecoder(r)
39
40 var gv gobValue
41 err := dec.Decode(&gv)
42 if err != nil {
43 return fmt.Errorf("error decoding cty.Value: %s", err)
44 }
45 if gv.Version != 0 {
46 return fmt.Errorf("unsupported cty.Value encoding version %d; only 0 is supported", gv.Version)
47 }
48
49 // big.Float seems to, for some reason, lose its "pointerness" when we
50 // round-trip it, so we'll fix that here.
51 if bf, ok := gv.V.(big.Float); ok {
52 gv.V = &bf
53 }
54
55 val.ty = gv.Ty
56 val.v = gv.V
57
58 return nil
59}
60
61// GobEncode is an implementation of the gob.GobEncoder interface, which
62// allows Types to be included in structures encoded with encoding/gob.
63//
64// Currently it is not possible to represent capsule types in gob.
65func (t Type) GobEncode() ([]byte, error) {
66 buf := &bytes.Buffer{}
67 enc := gob.NewEncoder(buf)
68
69 gt := gobType{
70 Version: 0,
71 Impl: t.typeImpl,
72 }
73
74 err := enc.Encode(gt)
75 if err != nil {
76 return nil, fmt.Errorf("error encoding cty.Type: %s", err)
77 }
78
79 return buf.Bytes(), nil
80}
81
82// GobDecode is an implementatino of the gob.GobDecoder interface, which
83// reverses the encoding performed by GobEncode to allow types to be recovered
84// from gob buffers.
85func (t *Type) GobDecode(buf []byte) error {
86 r := bytes.NewReader(buf)
87 dec := gob.NewDecoder(r)
88
89 var gt gobType
90 err := dec.Decode(&gt)
91 if err != nil {
92 return fmt.Errorf("error decoding cty.Type: %s", err)
93 }
94 if gt.Version != 0 {
95 return fmt.Errorf("unsupported cty.Type encoding version %d; only 0 is supported", gt.Version)
96 }
97
98 t.typeImpl = gt.Impl
99
100 return nil
101}
102
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.
105func (t *capsuleType) GobEncode() ([]byte, error) {
106 return nil, fmt.Errorf("cannot gob-encode capsule type %q", t.FriendlyName())
107}
108
109func (t *capsuleType) GobDecode() ([]byte, error) {
110 return nil, fmt.Errorf("cannot gob-decode capsule type %q", t.FriendlyName())
111}
112
113type gobValue struct {
114 Version int
115 Ty Type
116 V interface{}
117}
118
119type gobType struct {
120 Version int
121 Impl typeImpl
122}
123
124type gobCapsuleTypeImpl struct {
125}
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go b/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go
new file mode 100644
index 0000000..a5177d2
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go
@@ -0,0 +1,7 @@
1// Package gocty deals with converting between cty Values and native go
2// values.
3//
4// It operates under a similar principle to the encoding/json and
5// encoding/xml packages in the standard library, using reflection to
6// populate native Go data structures from cty values and vice-versa.
7package gocty
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go b/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go
new file mode 100644
index 0000000..94ffd2f
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go
@@ -0,0 +1,43 @@
1package gocty
2
3import (
4 "math/big"
5 "reflect"
6
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/set"
9)
10
11var valueType = reflect.TypeOf(cty.Value{})
12var typeType = reflect.TypeOf(cty.Type{})
13
14var setType = reflect.TypeOf(set.Set{})
15
16var bigFloatType = reflect.TypeOf(big.Float{})
17var bigIntType = reflect.TypeOf(big.Int{})
18
19var emptyInterfaceType = reflect.TypeOf(interface{}(nil))
20
21var stringType = reflect.TypeOf("")
22
23// structTagIndices interrogates the fields of the given type (which must
24// be a struct type, or we'll panic) and returns a map from the cty
25// attribute names declared via struct tags to the indices of the
26// fields holding those tags.
27//
28// This function will panic if two fields within the struct are tagged with
29// the same cty attribute name.
30func structTagIndices(st reflect.Type) map[string]int {
31 ct := st.NumField()
32 ret := make(map[string]int, ct)
33
34 for i := 0; i < ct; i++ {
35 field := st.Field(i)
36 attrName := field.Tag.Get("cty")
37 if attrName != "" {
38 ret[attrName] = i
39 }
40 }
41
42 return ret
43}
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/in.go b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go
new file mode 100644
index 0000000..642501b
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go
@@ -0,0 +1,528 @@
1package gocty
2
3import (
4 "math/big"
5 "reflect"
6
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/set"
9)
10
11// ToCtyValue produces a cty.Value from a Go value. The result will conform
12// to the given type, or an error will be returned if this is not possible.
13//
14// The target type serves as a hint to resolve ambiguities in the mapping.
15// For example, the Go type set.Set tells us that the value is a set but
16// does not describe the set's element type. This also allows for convenient
17// conversions, such as populating a set from a slice rather than having to
18// first explicitly instantiate a set.Set.
19//
20// The audience of this function is assumed to be the developers of Go code
21// that is integrating with cty, and thus the error messages it returns are
22// presented from Go's perspective. These messages are thus not appropriate
23// for display to end-users. An error returned from ToCtyValue represents a
24// bug in the calling program, not user error.
25func ToCtyValue(val interface{}, ty cty.Type) (cty.Value, error) {
26 // 'path' starts off as empty but will grow for each level of recursive
27 // call we make, so by the time toCtyValue returns it is likely to have
28 // unused capacity on the end of it, depending on how deeply-recursive
29 // the given Type is.
30 path := make(cty.Path, 0)
31 return toCtyValue(reflect.ValueOf(val), ty, path)
32}
33
34func toCtyValue(val reflect.Value, ty cty.Type, path cty.Path) (cty.Value, error) {
35
36 switch ty {
37 case cty.Bool:
38 return toCtyBool(val, path)
39 case cty.Number:
40 return toCtyNumber(val, path)
41 case cty.String:
42 return toCtyString(val, path)
43 case cty.DynamicPseudoType:
44 return toCtyDynamic(val, path)
45 }
46
47 switch {
48 case ty.IsListType():
49 return toCtyList(val, ty.ElementType(), path)
50 case ty.IsMapType():
51 return toCtyMap(val, ty.ElementType(), path)
52 case ty.IsSetType():
53 return toCtySet(val, ty.ElementType(), path)
54 case ty.IsObjectType():
55 return toCtyObject(val, ty.AttributeTypes(), path)
56 case ty.IsTupleType():
57 return toCtyTuple(val, ty.TupleElementTypes(), path)
58 case ty.IsCapsuleType():
59 return toCtyCapsule(val, ty, path)
60 }
61
62 // We should never fall out here
63 return cty.NilVal, path.NewErrorf("unsupported target type %#v", ty)
64}
65
66func toCtyBool(val reflect.Value, path cty.Path) (cty.Value, error) {
67 if val = toCtyUnwrapPointer(val); !val.IsValid() {
68 return cty.NullVal(cty.Bool), nil
69 }
70
71 switch val.Kind() {
72
73 case reflect.Bool:
74 return cty.BoolVal(val.Bool()), nil
75
76 default:
77 return cty.NilVal, path.NewErrorf("can't convert Go %s to bool", val.Kind())
78
79 }
80
81}
82
83func toCtyNumber(val reflect.Value, path cty.Path) (cty.Value, error) {
84 if val = toCtyUnwrapPointer(val); !val.IsValid() {
85 return cty.NullVal(cty.Number), nil
86 }
87
88 switch val.Kind() {
89
90 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
91 return cty.NumberIntVal(val.Int()), nil
92
93 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
94 return cty.NumberUIntVal(val.Uint()), nil
95
96 case reflect.Float32, reflect.Float64:
97 return cty.NumberFloatVal(val.Float()), nil
98
99 case reflect.Struct:
100 if val.Type().AssignableTo(bigIntType) {
101 bigInt := val.Interface().(big.Int)
102 bigFloat := (&big.Float{}).SetInt(&bigInt)
103 val = reflect.ValueOf(*bigFloat)
104 }
105
106 if val.Type().AssignableTo(bigFloatType) {
107 bigFloat := val.Interface().(big.Float)
108 return cty.NumberVal(&bigFloat), nil
109 }
110
111 fallthrough
112 default:
113 return cty.NilVal, path.NewErrorf("can't convert Go %s to number", val.Kind())
114
115 }
116
117}
118
119func toCtyString(val reflect.Value, path cty.Path) (cty.Value, error) {
120 if val = toCtyUnwrapPointer(val); !val.IsValid() {
121 return cty.NullVal(cty.String), nil
122 }
123
124 switch val.Kind() {
125
126 case reflect.String:
127 return cty.StringVal(val.String()), nil
128
129 default:
130 return cty.NilVal, path.NewErrorf("can't convert Go %s to string", val.Kind())
131
132 }
133
134}
135
136func toCtyList(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
137 if val = toCtyUnwrapPointer(val); !val.IsValid() {
138 return cty.NullVal(cty.List(ety)), nil
139 }
140
141 switch val.Kind() {
142
143 case reflect.Slice:
144 if val.IsNil() {
145 return cty.NullVal(cty.List(ety)), nil
146 }
147 fallthrough
148 case reflect.Array:
149 if val.Len() == 0 {
150 return cty.ListValEmpty(ety), nil
151 }
152
153 // While we work on our elements we'll temporarily grow
154 // path to give us a place to put our index step.
155 path = append(path, cty.PathStep(nil))
156
157 vals := make([]cty.Value, val.Len())
158 for i := range vals {
159 var err error
160 path[len(path)-1] = cty.IndexStep{
161 Key: cty.NumberIntVal(int64(i)),
162 }
163 vals[i], err = toCtyValue(val.Index(i), ety, path)
164 if err != nil {
165 return cty.NilVal, err
166 }
167 }
168
169 // Discard our extra path segment, retaining it as extra capacity
170 // for future appending to the path.
171 path = path[:len(path)-1]
172
173 return cty.ListVal(vals), nil
174
175 default:
176 return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.List(ety))
177
178 }
179}
180
181func toCtyMap(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
182 if val = toCtyUnwrapPointer(val); !val.IsValid() {
183 return cty.NullVal(cty.Map(ety)), nil
184 }
185
186 switch val.Kind() {
187
188 case reflect.Map:
189 if val.IsNil() {
190 return cty.NullVal(cty.Map(ety)), nil
191 }
192
193 if val.Len() == 0 {
194 return cty.MapValEmpty(ety), nil
195 }
196
197 keyType := val.Type().Key()
198 if keyType.Kind() != reflect.String {
199 return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType)
200 }
201
202 // While we work on our elements we'll temporarily grow
203 // path to give us a place to put our index step.
204 path = append(path, cty.PathStep(nil))
205
206 vals := make(map[string]cty.Value, val.Len())
207 for _, kv := range val.MapKeys() {
208 k := kv.String()
209 var err error
210 path[len(path)-1] = cty.IndexStep{
211 Key: cty.StringVal(k),
212 }
213 vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), ety, path)
214 if err != nil {
215 return cty.NilVal, err
216 }
217 }
218
219 // Discard our extra path segment, retaining it as extra capacity
220 // for future appending to the path.
221 path = path[:len(path)-1]
222
223 return cty.MapVal(vals), nil
224
225 default:
226 return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Map(ety))
227
228 }
229}
230
231func toCtySet(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
232 if val = toCtyUnwrapPointer(val); !val.IsValid() {
233 return cty.NullVal(cty.Set(ety)), nil
234 }
235
236 var vals []cty.Value
237
238 switch val.Kind() {
239
240 case reflect.Slice:
241 if val.IsNil() {
242 return cty.NullVal(cty.Set(ety)), nil
243 }
244 fallthrough
245 case reflect.Array:
246 if val.Len() == 0 {
247 return cty.SetValEmpty(ety), nil
248 }
249
250 vals = make([]cty.Value, val.Len())
251 for i := range vals {
252 var err error
253 vals[i], err = toCtyValue(val.Index(i), ety, path)
254 if err != nil {
255 return cty.NilVal, err
256 }
257 }
258
259 case reflect.Struct:
260
261 if !val.Type().AssignableTo(setType) {
262 return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Type(), cty.Set(ety))
263 }
264
265 rawSet := val.Interface().(set.Set)
266 inVals := rawSet.Values()
267
268 if len(inVals) == 0 {
269 return cty.SetValEmpty(ety), nil
270 }
271
272 vals = make([]cty.Value, len(inVals))
273 for i := range inVals {
274 var err error
275 vals[i], err = toCtyValue(reflect.ValueOf(inVals[i]), ety, path)
276 if err != nil {
277 return cty.NilVal, err
278 }
279 }
280
281 default:
282 return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Set(ety))
283
284 }
285
286 return cty.SetVal(vals), nil
287}
288
289func toCtyObject(val reflect.Value, attrTypes map[string]cty.Type, path cty.Path) (cty.Value, error) {
290 if val = toCtyUnwrapPointer(val); !val.IsValid() {
291 return cty.NullVal(cty.Object(attrTypes)), nil
292 }
293
294 switch val.Kind() {
295
296 case reflect.Map:
297 if val.IsNil() {
298 return cty.NullVal(cty.Object(attrTypes)), nil
299 }
300
301 keyType := val.Type().Key()
302 if keyType.Kind() != reflect.String {
303 return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType)
304 }
305
306 if len(attrTypes) == 0 {
307 return cty.EmptyObjectVal, nil
308 }
309
310 // While we work on our elements we'll temporarily grow
311 // path to give us a place to put our GetAttr step.
312 path = append(path, cty.PathStep(nil))
313
314 haveKeys := make(map[string]struct{}, val.Len())
315 for _, kv := range val.MapKeys() {
316 haveKeys[kv.String()] = struct{}{}
317 }
318
319 vals := make(map[string]cty.Value, len(attrTypes))
320 for k, at := range attrTypes {
321 var err error
322 path[len(path)-1] = cty.GetAttrStep{
323 Name: k,
324 }
325
326 if _, have := haveKeys[k]; !have {
327 vals[k] = cty.NullVal(at)
328 continue
329 }
330
331 vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), at, path)
332 if err != nil {
333 return cty.NilVal, err
334 }
335 }
336
337 // Discard our extra path segment, retaining it as extra capacity
338 // for future appending to the path.
339 path = path[:len(path)-1]
340
341 return cty.ObjectVal(vals), nil
342
343 case reflect.Struct:
344 if len(attrTypes) == 0 {
345 return cty.EmptyObjectVal, nil
346 }
347
348 // While we work on our elements we'll temporarily grow
349 // path to give us a place to put our GetAttr step.
350 path = append(path, cty.PathStep(nil))
351
352 attrFields := structTagIndices(val.Type())
353
354 vals := make(map[string]cty.Value, len(attrTypes))
355 for k, at := range attrTypes {
356 path[len(path)-1] = cty.GetAttrStep{
357 Name: k,
358 }
359
360 if fieldIdx, have := attrFields[k]; have {
361 var err error
362 vals[k], err = toCtyValue(val.Field(fieldIdx), at, path)
363 if err != nil {
364 return cty.NilVal, err
365 }
366 } else {
367 vals[k] = cty.NullVal(at)
368 }
369 }
370
371 // Discard our extra path segment, retaining it as extra capacity
372 // for future appending to the path.
373 path = path[:len(path)-1]
374
375 return cty.ObjectVal(vals), nil
376
377 default:
378 return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Object(attrTypes))
379
380 }
381}
382
383func toCtyTuple(val reflect.Value, elemTypes []cty.Type, path cty.Path) (cty.Value, error) {
384 if val = toCtyUnwrapPointer(val); !val.IsValid() {
385 return cty.NullVal(cty.Tuple(elemTypes)), nil
386 }
387
388 switch val.Kind() {
389
390 case reflect.Slice:
391 if val.IsNil() {
392 return cty.NullVal(cty.Tuple(elemTypes)), nil
393 }
394
395 if val.Len() != len(elemTypes) {
396 return cty.NilVal, path.NewErrorf("wrong number of elements %d; need %d", val.Len(), len(elemTypes))
397 }
398
399 if len(elemTypes) == 0 {
400 return cty.EmptyTupleVal, nil
401 }
402
403 // While we work on our elements we'll temporarily grow
404 // path to give us a place to put our Index step.
405 path = append(path, cty.PathStep(nil))
406
407 vals := make([]cty.Value, len(elemTypes))
408 for i, ety := range elemTypes {
409 var err error
410
411 path[len(path)-1] = cty.IndexStep{
412 Key: cty.NumberIntVal(int64(i)),
413 }
414
415 vals[i], err = toCtyValue(val.Index(i), ety, path)
416 if err != nil {
417 return cty.NilVal, err
418 }
419 }
420
421 // Discard our extra path segment, retaining it as extra capacity
422 // for future appending to the path.
423 path = path[:len(path)-1]
424
425 return cty.TupleVal(vals), nil
426
427 case reflect.Struct:
428 fieldCount := val.Type().NumField()
429 if fieldCount != len(elemTypes) {
430 return cty.NilVal, path.NewErrorf("wrong number of struct fields %d; need %d", fieldCount, len(elemTypes))
431 }
432
433 if len(elemTypes) == 0 {
434 return cty.EmptyTupleVal, nil
435 }
436
437 // While we work on our elements we'll temporarily grow
438 // path to give us a place to put our Index step.
439 path = append(path, cty.PathStep(nil))
440
441 vals := make([]cty.Value, len(elemTypes))
442 for i, ety := range elemTypes {
443 var err error
444
445 path[len(path)-1] = cty.IndexStep{
446 Key: cty.NumberIntVal(int64(i)),
447 }
448
449 vals[i], err = toCtyValue(val.Field(i), ety, path)
450 if err != nil {
451 return cty.NilVal, err
452 }
453 }
454
455 // Discard our extra path segment, retaining it as extra capacity
456 // for future appending to the path.
457 path = path[:len(path)-1]
458
459 return cty.TupleVal(vals), nil
460
461 default:
462 return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Tuple(elemTypes))
463
464 }
465}
466
467func toCtyCapsule(val reflect.Value, capsuleType cty.Type, path cty.Path) (cty.Value, error) {
468 if val = toCtyUnwrapPointer(val); !val.IsValid() {
469 return cty.NullVal(capsuleType), nil
470 }
471
472 if val.Kind() != reflect.Ptr {
473 if !val.CanAddr() {
474 return cty.NilVal, path.NewErrorf("source value for capsule %#v must be addressable", capsuleType)
475 }
476
477 val = val.Addr()
478 }
479
480 if !val.Type().Elem().AssignableTo(capsuleType.EncapsulatedType()) {
481 return cty.NilVal, path.NewErrorf("value of type %T not compatible with capsule %#v", val.Interface(), capsuleType)
482 }
483
484 return cty.CapsuleVal(capsuleType, val.Interface()), nil
485}
486
487func toCtyDynamic(val reflect.Value, path cty.Path) (cty.Value, error) {
488 if val = toCtyUnwrapPointer(val); !val.IsValid() {
489 return cty.NullVal(cty.DynamicPseudoType), nil
490 }
491
492 switch val.Kind() {
493
494 case reflect.Struct:
495 if !val.Type().AssignableTo(valueType) {
496 return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Type())
497 }
498
499 return val.Interface().(cty.Value), nil
500
501 default:
502 return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Kind())
503
504 }
505
506}
507
508// toCtyUnwrapPointer is a helper for dealing with Go pointers. It has three
509// possible outcomes:
510//
511// - Given value isn't a pointer, so it's just returned as-is.
512// - Given value is a non-nil pointer, in which case it is dereferenced
513// and the result returned.
514// - Given value is a nil pointer, in which case an invalid value is returned.
515//
516// For nested pointer types, like **int, they are all dereferenced in turn
517// until a non-pointer value is found, or until a nil pointer is encountered.
518func toCtyUnwrapPointer(val reflect.Value) reflect.Value {
519 for val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
520 if val.IsNil() {
521 return reflect.Value{}
522 }
523
524 val = val.Elem()
525 }
526
527 return val
528}
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/out.go b/vendor/github.com/zclconf/go-cty/cty/gocty/out.go
new file mode 100644
index 0000000..99b65a7
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/gocty/out.go
@@ -0,0 +1,705 @@
1package gocty
2
3import (
4 "math/big"
5 "reflect"
6
7 "math"
8
9 "github.com/zclconf/go-cty/cty"
10)
11
12// FromCtyValue assigns a cty.Value to a reflect.Value, which must be a pointer,
13// using a fixed set of conversion rules.
14//
15// This function considers its audience to be the creator of the cty Value
16// given, and thus the error messages it generates are (unlike with ToCtyValue)
17// presented in cty terminology that is generally appropriate to return to
18// end-users in applications where cty data structures are built from
19// user-provided configuration. In particular this means that if incorrect
20// target types are provided by the calling application the resulting error
21// messages are likely to be confusing, since we assume that the given target
22// type is correct and the cty.Value is where the error lies.
23//
24// If an error is returned, the target data structure may have been partially
25// populated, but the degree to which this is true is an implementation
26// detail that the calling application should not rely on.
27//
28// The function will panic if given a non-pointer as the Go value target,
29// since that is considered to be a bug in the calling program.
30func FromCtyValue(val cty.Value, target interface{}) error {
31 tVal := reflect.ValueOf(target)
32 if tVal.Kind() != reflect.Ptr {
33 panic("target value is not a pointer")
34 }
35 if tVal.IsNil() {
36 panic("target value is nil pointer")
37 }
38
39 // 'path' starts off as empty but will grow for each level of recursive
40 // call we make, so by the time fromCtyValue returns it is likely to have
41 // unused capacity on the end of it, depending on how deeply-recursive
42 // the given cty.Value is.
43 path := make(cty.Path, 0)
44 return fromCtyValue(val, tVal, path)
45}
46
47func fromCtyValue(val cty.Value, target reflect.Value, path cty.Path) error {
48 ty := val.Type()
49
50 deepTarget := fromCtyPopulatePtr(target, false)
51
52 // If we're decoding into a cty.Value then we just pass through the
53 // value as-is, to enable partial decoding. This is the only situation
54 // where unknown values are permitted.
55 if deepTarget.Kind() == reflect.Struct && deepTarget.Type().AssignableTo(valueType) {
56 deepTarget.Set(reflect.ValueOf(val))
57 return nil
58 }
59
60 // Lists and maps can be nil without indirection, but everything else
61 // requires a pointer and we set it immediately to nil.
62 // We also make an exception for capsule types because we want to handle
63 // pointers specially for these.
64 // (fromCtyList and fromCtyMap must therefore deal with val.IsNull, while
65 // other types can assume no nulls after this point.)
66 if val.IsNull() && !val.Type().IsListType() && !val.Type().IsMapType() && !val.Type().IsCapsuleType() {
67 target = fromCtyPopulatePtr(target, true)
68 if target.Kind() != reflect.Ptr {
69 return path.NewErrorf("null value is not allowed")
70 }
71
72 target.Set(reflect.Zero(target.Type()))
73 return nil
74 }
75
76 target = deepTarget
77
78 if !val.IsKnown() {
79 return path.NewErrorf("value must be known")
80 }
81
82 switch ty {
83 case cty.Bool:
84 return fromCtyBool(val, target, path)
85 case cty.Number:
86 return fromCtyNumber(val, target, path)
87 case cty.String:
88 return fromCtyString(val, target, path)
89 }
90
91 switch {
92 case ty.IsListType():
93 return fromCtyList(val, target, path)
94 case ty.IsMapType():
95 return fromCtyMap(val, target, path)
96 case ty.IsSetType():
97 return fromCtySet(val, target, path)
98 case ty.IsObjectType():
99 return fromCtyObject(val, target, path)
100 case ty.IsTupleType():
101 return fromCtyTuple(val, target, path)
102 case ty.IsCapsuleType():
103 return fromCtyCapsule(val, target, path)
104 }
105
106 // We should never fall out here; reaching here indicates a bug in this
107 // function.
108 return path.NewErrorf("unsupported source type %#v", ty)
109}
110
111func fromCtyBool(val cty.Value, target reflect.Value, path cty.Path) error {
112 switch target.Kind() {
113
114 case reflect.Bool:
115 if val.True() {
116 target.Set(reflect.ValueOf(true))
117 } else {
118 target.Set(reflect.ValueOf(false))
119 }
120 return nil
121
122 default:
123 return likelyRequiredTypesError(path, target)
124
125 }
126}
127
128func fromCtyNumber(val cty.Value, target reflect.Value, path cty.Path) error {
129 bf := val.AsBigFloat()
130
131 switch target.Kind() {
132
133 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
134 return fromCtyNumberInt(bf, target, path)
135
136 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
137 return fromCtyNumberUInt(bf, target, path)
138
139 case reflect.Float32, reflect.Float64:
140 return fromCtyNumberFloat(bf, target, path)
141
142 case reflect.Struct:
143 return fromCtyNumberBig(bf, target, path)
144
145 default:
146 return likelyRequiredTypesError(path, target)
147
148 }
149}
150
151func fromCtyNumberInt(bf *big.Float, target reflect.Value, path cty.Path) error {
152 // Doing this with switch rather than << arithmetic because << with
153 // result >32-bits is not portable to 32-bit systems.
154 var min int64
155 var max int64
156 switch target.Type().Bits() {
157 case 8:
158 min = math.MinInt8
159 max = math.MaxInt8
160 case 16:
161 min = math.MinInt16
162 max = math.MaxInt16
163 case 32:
164 min = math.MinInt32
165 max = math.MaxInt32
166 case 64:
167 min = math.MinInt64
168 max = math.MaxInt64
169 default:
170 panic("weird number of bits in target int")
171 }
172
173 iv, accuracy := bf.Int64()
174 if accuracy != big.Exact || iv < min || iv > max {
175 return path.NewErrorf("value must be a whole number, between %d and %d", min, max)
176 }
177
178 target.Set(reflect.ValueOf(iv).Convert(target.Type()))
179
180 return nil
181}
182
183func fromCtyNumberUInt(bf *big.Float, target reflect.Value, path cty.Path) error {
184 // Doing this with switch rather than << arithmetic because << with
185 // result >32-bits is not portable to 32-bit systems.
186 var max uint64
187 switch target.Type().Bits() {
188 case 8:
189 max = math.MaxUint8
190 case 16:
191 max = math.MaxUint16
192 case 32:
193 max = math.MaxUint32
194 case 64:
195 max = math.MaxUint64
196 default:
197 panic("weird number of bits in target uint")
198 }
199
200 iv, accuracy := bf.Uint64()
201 if accuracy != big.Exact || iv > max {
202 return path.NewErrorf("value must be a whole number, between 0 and %d inclusive", max)
203 }
204
205 target.Set(reflect.ValueOf(iv).Convert(target.Type()))
206
207 return nil
208}
209
210func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) error {
211 switch target.Kind() {
212 case reflect.Float32:
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()
225 if accuracy != big.Exact {
226 // We allow the precision to be truncated as part of our conversion,
227 // but we don't want to silently introduce infinities.
228 if math.IsInf(fv, 0) {
229 return path.NewErrorf("value must be between %f and %f inclusive", -math.MaxFloat64, math.MaxFloat64)
230 }
231 }
232 target.Set(reflect.ValueOf(fv))
233 return nil
234 default:
235 panic("unsupported kind of float")
236 }
237}
238
239func fromCtyNumberBig(bf *big.Float, target reflect.Value, path cty.Path) error {
240 switch {
241
242 case bigFloatType.AssignableTo(target.Type()):
243 // Easy!
244 target.Set(reflect.ValueOf(bf).Elem())
245 return nil
246
247 case bigIntType.AssignableTo(target.Type()):
248 bi, accuracy := bf.Int(nil)
249 if accuracy != big.Exact {
250 return path.NewErrorf("value must be a whole number")
251 }
252 target.Set(reflect.ValueOf(bi).Elem())
253 return nil
254
255 default:
256 return likelyRequiredTypesError(path, target)
257 }
258}
259
260func fromCtyString(val cty.Value, target reflect.Value, path cty.Path) error {
261 switch target.Kind() {
262
263 case reflect.String:
264 target.Set(reflect.ValueOf(val.AsString()))
265 return nil
266
267 default:
268 return likelyRequiredTypesError(path, target)
269
270 }
271}
272
273func fromCtyList(val cty.Value, target reflect.Value, path cty.Path) error {
274 switch target.Kind() {
275
276 case reflect.Slice:
277 if val.IsNull() {
278 target.Set(reflect.Zero(target.Type()))
279 return nil
280 }
281
282 length := val.LengthInt()
283 tv := reflect.MakeSlice(target.Type(), length, length)
284
285 path = append(path, nil)
286
287 i := 0
288 var err error
289 val.ForEachElement(func(key cty.Value, val cty.Value) bool {
290 path[len(path)-1] = cty.IndexStep{
291 Key: cty.NumberIntVal(int64(i)),
292 }
293
294 targetElem := tv.Index(i)
295 err = fromCtyValue(val, targetElem, path)
296 if err != nil {
297 return true
298 }
299
300 i++
301 return false
302 })
303 if err != nil {
304 return err
305 }
306
307 path = path[:len(path)-1]
308
309 target.Set(tv)
310 return nil
311
312 case reflect.Array:
313 if val.IsNull() {
314 return path.NewErrorf("null value is not allowed")
315 }
316
317 length := val.LengthInt()
318 if length != target.Len() {
319 return path.NewErrorf("must be a list of length %d", target.Len())
320 }
321
322 path = append(path, nil)
323
324 i := 0
325 var err error
326 val.ForEachElement(func(key cty.Value, val cty.Value) bool {
327 path[len(path)-1] = cty.IndexStep{
328 Key: cty.NumberIntVal(int64(i)),
329 }
330
331 targetElem := target.Index(i)
332 err = fromCtyValue(val, targetElem, path)
333 if err != nil {
334 return true
335 }
336
337 i++
338 return false
339 })
340 if err != nil {
341 return err
342 }
343
344 path = path[:len(path)-1]
345
346 return nil
347
348 default:
349 return likelyRequiredTypesError(path, target)
350
351 }
352}
353
354func fromCtyMap(val cty.Value, target reflect.Value, path cty.Path) error {
355
356 switch target.Kind() {
357
358 case reflect.Map:
359 if val.IsNull() {
360 target.Set(reflect.Zero(target.Type()))
361 return nil
362 }
363
364 tv := reflect.MakeMap(target.Type())
365 et := target.Type().Elem()
366
367 path = append(path, nil)
368
369 var err error
370 val.ForEachElement(func(key cty.Value, val cty.Value) bool {
371 path[len(path)-1] = cty.IndexStep{
372 Key: key,
373 }
374
375 ks := key.AsString()
376
377 targetElem := reflect.New(et)
378 err = fromCtyValue(val, targetElem, path)
379
380 tv.SetMapIndex(reflect.ValueOf(ks), targetElem.Elem())
381
382 return err != nil
383 })
384 if err != nil {
385 return err
386 }
387
388 path = path[:len(path)-1]
389
390 target.Set(tv)
391 return nil
392
393 default:
394 return likelyRequiredTypesError(path, target)
395
396 }
397}
398
399func fromCtySet(val cty.Value, target reflect.Value, path cty.Path) error {
400 switch target.Kind() {
401
402 case reflect.Slice:
403 if val.IsNull() {
404 target.Set(reflect.Zero(target.Type()))
405 return nil
406 }
407
408 length := val.LengthInt()
409 tv := reflect.MakeSlice(target.Type(), length, length)
410
411 i := 0
412 var err error
413 val.ForEachElement(func(key cty.Value, val cty.Value) bool {
414 targetElem := tv.Index(i)
415 err = fromCtyValue(val, targetElem, path)
416 if err != nil {
417 return true
418 }
419
420 i++
421 return false
422 })
423 if err != nil {
424 return err
425 }
426
427 target.Set(tv)
428 return nil
429
430 case reflect.Array:
431 if val.IsNull() {
432 return path.NewErrorf("null value is not allowed")
433 }
434
435 length := val.LengthInt()
436 if length != target.Len() {
437 return path.NewErrorf("must be a set of length %d", target.Len())
438 }
439
440 i := 0
441 var err error
442 val.ForEachElement(func(key cty.Value, val cty.Value) bool {
443 targetElem := target.Index(i)
444 err = fromCtyValue(val, targetElem, path)
445 if err != nil {
446 return true
447 }
448
449 i++
450 return false
451 })
452 if err != nil {
453 return err
454 }
455
456 return nil
457
458 // TODO: decode into set.Set instance
459
460 default:
461 return likelyRequiredTypesError(path, target)
462
463 }
464}
465
466func fromCtyObject(val cty.Value, target reflect.Value, path cty.Path) error {
467
468 switch target.Kind() {
469
470 case reflect.Struct:
471
472 attrTypes := val.Type().AttributeTypes()
473 targetFields := structTagIndices(target.Type())
474
475 path = append(path, nil)
476
477 for k, i := range targetFields {
478 if _, exists := attrTypes[k]; !exists {
479 // If the field in question isn't able to represent nil,
480 // that's an error.
481 fk := target.Field(i).Kind()
482 switch fk {
483 case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface:
484 // okay
485 default:
486 return path.NewErrorf("missing required attribute %q", k)
487 }
488 }
489 }
490
491 for k := range attrTypes {
492 path[len(path)-1] = cty.GetAttrStep{
493 Name: k,
494 }
495
496 fieldIdx, exists := targetFields[k]
497 if !exists {
498 return path.NewErrorf("unsupported attribute %q", k)
499 }
500
501 ev := val.GetAttr(k)
502
503 targetField := target.Field(fieldIdx)
504 err := fromCtyValue(ev, targetField, path)
505 if err != nil {
506 return err
507 }
508 }
509
510 path = path[:len(path)-1]
511
512 return nil
513
514 default:
515 return likelyRequiredTypesError(path, target)
516
517 }
518}
519
520func fromCtyTuple(val cty.Value, target reflect.Value, path cty.Path) error {
521
522 switch target.Kind() {
523
524 case reflect.Struct:
525
526 elemTypes := val.Type().TupleElementTypes()
527 fieldCount := target.Type().NumField()
528
529 if fieldCount != len(elemTypes) {
530 return path.NewErrorf("a tuple of %d elements is required", fieldCount)
531 }
532
533 path = append(path, nil)
534
535 for i := range elemTypes {
536 path[len(path)-1] = cty.IndexStep{
537 Key: cty.NumberIntVal(int64(i)),
538 }
539
540 ev := val.Index(cty.NumberIntVal(int64(i)))
541
542 targetField := target.Field(i)
543 err := fromCtyValue(ev, targetField, path)
544 if err != nil {
545 return err
546 }
547 }
548
549 path = path[:len(path)-1]
550
551 return nil
552
553 default:
554 return likelyRequiredTypesError(path, target)
555
556 }
557}
558
559func fromCtyCapsule(val cty.Value, target reflect.Value, path cty.Path) error {
560
561 if target.Kind() == reflect.Ptr {
562 // Walk through indirection until we get to the last pointer,
563 // which we might set to null below.
564 target = fromCtyPopulatePtr(target, true)
565
566 if val.IsNull() {
567 target.Set(reflect.Zero(target.Type()))
568 return nil
569 }
570
571 // Since a capsule contains a pointer to an object, we'll preserve
572 // that pointer on the way out and thus allow the caller to recover
573 // the original object, rather than a copy of it.
574
575 eType := val.Type().EncapsulatedType()
576
577 if !eType.AssignableTo(target.Elem().Type()) {
578 // Our interface contract promises that we won't expose Go
579 // implementation details in error messages, so we need to keep
580 // this vague. This can only arise if a calling application has
581 // more than one capsule type in play and a user mixes them up.
582 return path.NewErrorf("incorrect type %s", val.Type().FriendlyName())
583 }
584
585 target.Set(reflect.ValueOf(val.EncapsulatedValue()))
586
587 return nil
588 } else {
589 if val.IsNull() {
590 return path.NewErrorf("null value is not allowed")
591 }
592
593 // If our target isn't a pointer then we will attempt to copy
594 // the encapsulated value into it.
595
596 eType := val.Type().EncapsulatedType()
597
598 if !eType.AssignableTo(target.Type()) {
599 // Our interface contract promises that we won't expose Go
600 // implementation details in error messages, so we need to keep
601 // this vague. This can only arise if a calling application has
602 // more than one capsule type in play and a user mixes them up.
603 return path.NewErrorf("incorrect type %s", val.Type().FriendlyName())
604 }
605
606 // We know that EncapsulatedValue is always a pointer, so we
607 // can safely call .Elem on its reflect.Value.
608 target.Set(reflect.ValueOf(val.EncapsulatedValue()).Elem())
609
610 return nil
611 }
612
613}
614
615// fromCtyPopulatePtr recognizes when target is a pointer type and allocates
616// a value to assign to that pointer, which it returns.
617//
618// If the given value has multiple levels of indirection, like **int, these
619// will be processed in turn so that the return value is guaranteed to be
620// a non-pointer.
621//
622// As an exception, if decodingNull is true then the returned value will be
623// the final level of pointer, if any, so that the caller can assign it
624// as nil to represent a null value. If the given target value is not a pointer
625// at all then the returned value will be just the given target, so the caller
626// must test if the returned value is a pointer before trying to assign nil
627// to it.
628func fromCtyPopulatePtr(target reflect.Value, decodingNull bool) reflect.Value {
629 for {
630 if target.Kind() == reflect.Interface && !target.IsNil() {
631 e := target.Elem()
632 if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
633 target = e
634 }
635 }
636
637 if target.Kind() != reflect.Ptr {
638 break
639 }
640
641 // Stop early if we're decodingNull and we've found our last indirection
642 if target.Elem().Kind() != reflect.Ptr && decodingNull && target.CanSet() {
643 break
644 }
645
646 if target.IsNil() {
647 target.Set(reflect.New(target.Type().Elem()))
648 }
649
650 target = target.Elem()
651 }
652 return target
653}
654
655// likelyRequiredTypesError returns an error that states which types are
656// acceptable by making some assumptions about what types we support for
657// each target Go kind. It's not a precise science but it allows us to return
658// an error message that is cty-user-oriented rather than Go-oriented.
659//
660// Generally these error messages should be a matter of last resort, since
661// the calling application should be validating user-provided value types
662// before decoding anyway.
663func likelyRequiredTypesError(path cty.Path, target reflect.Value) error {
664 switch target.Kind() {
665
666 case reflect.Bool:
667 return path.NewErrorf("bool value is required")
668
669 case reflect.String:
670 return path.NewErrorf("string value is required")
671
672 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
673 fallthrough
674 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
675 fallthrough
676 case reflect.Float32, reflect.Float64:
677 return path.NewErrorf("number value is required")
678
679 case reflect.Slice, reflect.Array:
680 return path.NewErrorf("list or set value is required")
681
682 case reflect.Map:
683 return path.NewErrorf("map or object value is required")
684
685 case reflect.Struct:
686 switch {
687
688 case target.Type().AssignableTo(bigFloatType) || target.Type().AssignableTo(bigIntType):
689 return path.NewErrorf("number value is required")
690
691 case target.Type().AssignableTo(setType):
692 return path.NewErrorf("set or list value is required")
693
694 default:
695 return path.NewErrorf("object or tuple value is required")
696
697 }
698
699 default:
700 // We should avoid getting into this path, since this error
701 // message is rather useless.
702 return path.NewErrorf("incorrect type")
703
704 }
705}
diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go b/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go
new file mode 100644
index 0000000..ce4c8f1
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go
@@ -0,0 +1,108 @@
1package gocty
2
3import (
4 "reflect"
5
6 "github.com/zclconf/go-cty/cty"
7)
8
9// ImpliedType takes an arbitrary Go value (as an interface{}) and attempts
10// to find a suitable cty.Type instance that could be used for a conversion
11// with ToCtyValue.
12//
13// This allows -- for simple situations at least -- types to be defined just
14// once in Go and the cty types derived from the Go types, but in the process
15// it makes some assumptions that may be undesirable so applications are
16// encouraged to build their cty types directly if exacting control is
17// required.
18//
19// Not all Go types can be represented as cty types, so an error may be
20// returned which is usually considered to be a bug in the calling program.
21// In particular, ImpliedType will never use capsule types in its returned
22// type, because it cannot know the capsule types supported by the calling
23// program.
24func ImpliedType(gv interface{}) (cty.Type, error) {
25 rt := reflect.TypeOf(gv)
26 var path cty.Path
27 return impliedType(rt, path)
28}
29
30func impliedType(rt reflect.Type, path cty.Path) (cty.Type, error) {
31 switch rt.Kind() {
32
33 case reflect.Ptr:
34 return impliedType(rt.Elem(), path)
35
36 // Primitive types
37 case reflect.Bool:
38 return cty.Bool, nil
39 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
40 return cty.Number, nil
41 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
42 return cty.Number, nil
43 case reflect.Float32, reflect.Float64:
44 return cty.Number, nil
45 case reflect.String:
46 return cty.String, nil
47
48 // Collection types
49 case reflect.Slice:
50 path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.Number)})
51 ety, err := impliedType(rt.Elem(), path)
52 if err != nil {
53 return cty.NilType, err
54 }
55 return cty.List(ety), nil
56 case reflect.Map:
57 if !stringType.AssignableTo(rt.Key()) {
58 return cty.NilType, path.NewErrorf("no cty.Type for %s (must have string keys)", rt)
59 }
60 path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.String)})
61 ety, err := impliedType(rt.Elem(), path)
62 if err != nil {
63 return cty.NilType, err
64 }
65 return cty.Map(ety), nil
66
67 // Structural types
68 case reflect.Struct:
69 return impliedStructType(rt, path)
70
71 default:
72 return cty.NilType, path.NewErrorf("no cty.Type for %s", rt)
73 }
74}
75
76func impliedStructType(rt reflect.Type, path cty.Path) (cty.Type, error) {
77 if valueType.AssignableTo(rt) {
78 // Special case: cty.Value represents cty.DynamicPseudoType, for
79 // type conformance checking.
80 return cty.DynamicPseudoType, nil
81 }
82
83 fieldIdxs := structTagIndices(rt)
84 if len(fieldIdxs) == 0 {
85 return cty.NilType, path.NewErrorf("no cty.Type for %s (no cty field tags)", rt)
86 }
87
88 atys := make(map[string]cty.Type, len(fieldIdxs))
89
90 {
91 // Temporary extension of path for attributes
92 path := append(path, nil)
93
94 for k, fi := range fieldIdxs {
95 path[len(path)-1] = cty.GetAttrStep{Name: k}
96
97 ft := rt.Field(fi).Type
98 aty, err := impliedType(ft, path)
99 if err != nil {
100 return cty.NilType, err
101 }
102
103 atys[k] = aty
104 }
105 }
106
107 return cty.Object(atys), nil
108}
diff --git a/vendor/github.com/zclconf/go-cty/cty/helper.go b/vendor/github.com/zclconf/go-cty/cty/helper.go
new file mode 100644
index 0000000..1b88e9f
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/helper.go
@@ -0,0 +1,99 @@
1package cty
2
3import (
4 "fmt"
5)
6
7// anyUnknown is a helper to easily check if a set of values contains any
8// unknowns, for operations that short-circuit to return unknown in that case.
9func anyUnknown(values ...Value) bool {
10 for _, val := range values {
11 if val.v == unknown {
12 return true
13 }
14 }
15 return false
16}
17
18// typeCheck tests whether all of the given values belong to the given type.
19// If the given types are a mixture of the given type and the dynamic
20// pseudo-type then a short-circuit dynamic value is returned. If the given
21// values are all of the correct type but at least one is unknown then
22// a short-circuit unknown value is returned. If any other types appear then
23// an error is returned. Otherwise (finally!) the result is nil, nil.
24func typeCheck(required Type, ret Type, values ...Value) (shortCircuit *Value, err error) {
25 hasDynamic := false
26 hasUnknown := false
27
28 for i, val := range values {
29 if val.ty == DynamicPseudoType {
30 hasDynamic = true
31 continue
32 }
33
34 if !val.Type().Equals(required) {
35 return nil, fmt.Errorf(
36 "type mismatch: want %s but value %d is %s",
37 required.FriendlyName(),
38 i, val.ty.FriendlyName(),
39 )
40 }
41
42 if val.v == unknown {
43 hasUnknown = true
44 }
45 }
46
47 if hasDynamic {
48 return &DynamicVal, nil
49 }
50
51 if hasUnknown {
52 ret := UnknownVal(ret)
53 return &ret, nil
54 }
55
56 return nil, nil
57}
58
59// mustTypeCheck is a wrapper around typeCheck that immediately panics if
60// any error is returned.
61func mustTypeCheck(required Type, ret Type, values ...Value) *Value {
62 shortCircuit, err := typeCheck(required, ret, values...)
63 if err != nil {
64 panic(err)
65 }
66 return shortCircuit
67}
68
69// shortCircuitForceType takes the return value from mustTypeCheck and
70// replaces it with an unknown of the given type if the original value was
71// DynamicVal.
72//
73// This is useful for operations that are specified to always return a
74// particular type, since then a dynamic result can safely be "upgrade" to
75// a strongly-typed unknown, which then allows subsequent operations to
76// be actually type-checked.
77//
78// It is safe to use this only if the operation in question is defined as
79// returning either a value of the given type or panicking, since we know
80// then that subsequent operations won't run if the operation panics.
81//
82// If the given short-circuit value is *not* DynamicVal then it must be
83// of the given type, or this function will panic.
84func forceShortCircuitType(shortCircuit *Value, ty Type) *Value {
85 if shortCircuit == nil {
86 return nil
87 }
88
89 if shortCircuit.ty == DynamicPseudoType {
90 ret := UnknownVal(ty)
91 return &ret
92 }
93
94 if !shortCircuit.ty.Equals(ty) {
95 panic("forceShortCircuitType got value of wrong type")
96 }
97
98 return shortCircuit
99}
diff --git a/vendor/github.com/zclconf/go-cty/cty/json.go b/vendor/github.com/zclconf/go-cty/cty/json.go
new file mode 100644
index 0000000..c421a62
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json.go
@@ -0,0 +1,176 @@
1package cty
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7)
8
9// MarshalJSON is an implementation of json.Marshaler that allows Type
10// instances to be serialized as JSON.
11//
12// All standard types can be serialized, but capsule types cannot since there
13// is no way to automatically recover the original pointer and capsule types
14// compare by equality.
15func (t Type) MarshalJSON() ([]byte, error) {
16 switch impl := t.typeImpl.(type) {
17 case primitiveType:
18 switch impl.Kind {
19 case primitiveTypeBool:
20 return []byte{'"', 'b', 'o', 'o', 'l', '"'}, nil
21 case primitiveTypeNumber:
22 return []byte{'"', 'n', 'u', 'm', 'b', 'e', 'r', '"'}, nil
23 case primitiveTypeString:
24 return []byte{'"', 's', 't', 'r', 'i', 'n', 'g', '"'}, nil
25 default:
26 panic("unknown primitive type kind")
27 }
28 case typeList, typeMap, typeSet:
29 buf := &bytes.Buffer{}
30 etyJSON, err := t.ElementType().MarshalJSON()
31 if err != nil {
32 return nil, err
33 }
34 buf.WriteRune('[')
35 switch impl.(type) {
36 case typeList:
37 buf.WriteString(`"list"`)
38 case typeMap:
39 buf.WriteString(`"map"`)
40 case typeSet:
41 buf.WriteString(`"set"`)
42 }
43 buf.WriteRune(',')
44 buf.Write(etyJSON)
45 buf.WriteRune(']')
46 return buf.Bytes(), nil
47 case typeObject:
48 buf := &bytes.Buffer{}
49 atysJSON, err := json.Marshal(t.AttributeTypes())
50 if err != nil {
51 return nil, err
52 }
53 buf.WriteString(`["object",`)
54 buf.Write(atysJSON)
55 buf.WriteRune(']')
56 return buf.Bytes(), nil
57 case typeTuple:
58 buf := &bytes.Buffer{}
59 etysJSON, err := json.Marshal(t.TupleElementTypes())
60 if err != nil {
61 return nil, err
62 }
63 buf.WriteString(`["tuple",`)
64 buf.Write(etysJSON)
65 buf.WriteRune(']')
66 return buf.Bytes(), nil
67 case pseudoTypeDynamic:
68 return []byte{'"', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '"'}, nil
69 case *capsuleType:
70 return nil, fmt.Errorf("type not allowed: %s", t.FriendlyName())
71 default:
72 // should never happen
73 panic("unknown type implementation")
74 }
75}
76
77// UnmarshalJSON is the opposite of MarshalJSON. See the documentation of
78// MarshalJSON for information on the limitations of JSON serialization of
79// types.
80func (t *Type) UnmarshalJSON(buf []byte) error {
81 r := bytes.NewReader(buf)
82 dec := json.NewDecoder(r)
83
84 tok, err := dec.Token()
85 if err != nil {
86 return err
87 }
88
89 switch v := tok.(type) {
90 case string:
91 switch v {
92 case "bool":
93 *t = Bool
94 case "number":
95 *t = Number
96 case "string":
97 *t = String
98 case "dynamic":
99 *t = DynamicPseudoType
100 default:
101 return fmt.Errorf("invalid primitive type name %q", v)
102 }
103
104 if dec.More() {
105 return fmt.Errorf("extraneous data after type description")
106 }
107 return nil
108 case json.Delim:
109 if rune(v) != '[' {
110 return fmt.Errorf("invalid complex type description")
111 }
112
113 tok, err = dec.Token()
114 if err != nil {
115 return err
116 }
117
118 kind, ok := tok.(string)
119 if !ok {
120 return fmt.Errorf("invalid complex type kind name")
121 }
122
123 switch kind {
124 case "list":
125 var ety Type
126 err = dec.Decode(&ety)
127 if err != nil {
128 return err
129 }
130 *t = List(ety)
131 case "map":
132 var ety Type
133 err = dec.Decode(&ety)
134 if err != nil {
135 return err
136 }
137 *t = Map(ety)
138 case "set":
139 var ety Type
140 err = dec.Decode(&ety)
141 if err != nil {
142 return err
143 }
144 *t = Set(ety)
145 case "object":
146 var atys map[string]Type
147 err = dec.Decode(&atys)
148 if err != nil {
149 return err
150 }
151 *t = Object(atys)
152 case "tuple":
153 var etys []Type
154 err = dec.Decode(&etys)
155 if err != nil {
156 return err
157 }
158 *t = Tuple(etys)
159 default:
160 return fmt.Errorf("invalid complex type kind name")
161 }
162
163 tok, err = dec.Token()
164 if err != nil {
165 return err
166 }
167 if delim, ok := tok.(json.Delim); !ok || rune(delim) != ']' || dec.More() {
168 return fmt.Errorf("unexpected extra data in type description")
169 }
170
171 return nil
172
173 default:
174 return fmt.Errorf("invalid type description")
175 }
176}
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/doc.go b/vendor/github.com/zclconf/go-cty/cty/json/doc.go
new file mode 100644
index 0000000..8916513
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json/doc.go
@@ -0,0 +1,11 @@
1// Package json provides functions for serializing cty types and values in
2// JSON format, and for decoding them again.
3//
4// Since the cty type system is a superset of the JSON type system,
5// round-tripping through JSON is lossy unless type information is provided
6// both at encoding time and decoding time. Callers of this package are
7// therefore suggested to define their expected structure as a cty.Type
8// and pass it in consistently both when encoding and when decoding, though
9// default (type-lossy) behavior is provided for situations where the precise
10// representation of the data is not significant.
11package json
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/marshal.go b/vendor/github.com/zclconf/go-cty/cty/json/marshal.go
new file mode 100644
index 0000000..f7bea1a
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json/marshal.go
@@ -0,0 +1,189 @@
1package json
2
3import (
4 "bytes"
5 "encoding/json"
6 "sort"
7
8 "github.com/zclconf/go-cty/cty"
9)
10
11func marshal(val cty.Value, t cty.Type, path cty.Path, b *bytes.Buffer) error {
12 // If we're going to decode as DynamicPseudoType then we need to save
13 // dynamic type information to recover the real type.
14 if t == cty.DynamicPseudoType && val.Type() != cty.DynamicPseudoType {
15 return marshalDynamic(val, path, b)
16 }
17
18 if val.IsNull() {
19 b.WriteString("null")
20 return nil
21 }
22
23 if !val.IsKnown() {
24 return path.NewErrorf("value is not known")
25 }
26
27 // The caller should've guaranteed that the given val is conformant with
28 // the given type t, so we'll proceed under that assumption here.
29
30 switch {
31 case t.IsPrimitiveType():
32 switch t {
33 case cty.String:
34 json, err := json.Marshal(val.AsString())
35 if err != nil {
36 return path.NewErrorf("failed to serialize value: %s", err)
37 }
38 b.Write(json)
39 return nil
40 case cty.Number:
41 if val.RawEquals(cty.PositiveInfinity) || val.RawEquals(cty.NegativeInfinity) {
42 return path.NewErrorf("cannot serialize infinity as JSON")
43 }
44 b.WriteString(val.AsBigFloat().Text('f', -1))
45 return nil
46 case cty.Bool:
47 if val.True() {
48 b.WriteString("true")
49 } else {
50 b.WriteString("false")
51 }
52 return nil
53 default:
54 panic("unsupported primitive type")
55 }
56 case t.IsListType(), t.IsSetType():
57 b.WriteRune('[')
58 first := true
59 ety := t.ElementType()
60 it := val.ElementIterator()
61 path := append(path, nil) // local override of 'path' with extra element
62 for it.Next() {
63 if !first {
64 b.WriteRune(',')
65 }
66 ek, ev := it.Element()
67 path[len(path)-1] = cty.IndexStep{
68 Key: ek,
69 }
70 err := marshal(ev, ety, path, b)
71 if err != nil {
72 return err
73 }
74 first = false
75 }
76 b.WriteRune(']')
77 return nil
78 case t.IsMapType():
79 b.WriteRune('{')
80 first := true
81 ety := t.ElementType()
82 it := val.ElementIterator()
83 path := append(path, nil) // local override of 'path' with extra element
84 for it.Next() {
85 if !first {
86 b.WriteRune(',')
87 }
88 ek, ev := it.Element()
89 path[len(path)-1] = cty.IndexStep{
90 Key: ek,
91 }
92 var err error
93 err = marshal(ek, ek.Type(), path, b)
94 if err != nil {
95 return err
96 }
97 b.WriteRune(':')
98 err = marshal(ev, ety, path, b)
99 if err != nil {
100 return err
101 }
102 first = false
103 }
104 b.WriteRune('}')
105 return nil
106 case t.IsTupleType():
107 b.WriteRune('[')
108 etys := t.TupleElementTypes()
109 it := val.ElementIterator()
110 path := append(path, nil) // local override of 'path' with extra element
111 i := 0
112 for it.Next() {
113 if i > 0 {
114 b.WriteRune(',')
115 }
116 ety := etys[i]
117 ek, ev := it.Element()
118 path[len(path)-1] = cty.IndexStep{
119 Key: ek,
120 }
121 err := marshal(ev, ety, path, b)
122 if err != nil {
123 return err
124 }
125 i++
126 }
127 b.WriteRune(']')
128 return nil
129 case t.IsObjectType():
130 b.WriteRune('{')
131 atys := t.AttributeTypes()
132 path := append(path, nil) // local override of 'path' with extra element
133
134 names := make([]string, 0, len(atys))
135 for k := range atys {
136 names = append(names, k)
137 }
138 sort.Strings(names)
139
140 for i, k := range names {
141 aty := atys[k]
142 if i > 0 {
143 b.WriteRune(',')
144 }
145 av := val.GetAttr(k)
146 path[len(path)-1] = cty.GetAttrStep{
147 Name: k,
148 }
149 var err error
150 err = marshal(cty.StringVal(k), cty.String, path, b)
151 if err != nil {
152 return err
153 }
154 b.WriteRune(':')
155 err = marshal(av, aty, path, b)
156 if err != nil {
157 return err
158 }
159 }
160 b.WriteRune('}')
161 return nil
162 case t.IsCapsuleType():
163 rawVal := val.EncapsulatedValue()
164 jsonVal, err := json.Marshal(rawVal)
165 if err != nil {
166 return path.NewError(err)
167 }
168 b.Write(jsonVal)
169 return nil
170 default:
171 // should never happen
172 return path.NewErrorf("cannot JSON-serialize %s", t.FriendlyName())
173 }
174}
175
176// marshalDynamic adds an extra wrapping object containing dynamic type
177// information for the given value.
178func marshalDynamic(val cty.Value, path cty.Path, b *bytes.Buffer) error {
179 typeJSON, err := MarshalType(val.Type())
180 if err != nil {
181 return path.NewErrorf("failed to serialize type: %s", err)
182 }
183 b.WriteString(`{"value":`)
184 marshal(val, val.Type(), path, b)
185 b.WriteString(`,"type":`)
186 b.Write(typeJSON)
187 b.WriteRune('}')
188 return nil
189}
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/simple.go b/vendor/github.com/zclconf/go-cty/cty/json/simple.go
new file mode 100644
index 0000000..507c9cc
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json/simple.go
@@ -0,0 +1,41 @@
1package json
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// SimpleJSONValue is a wrapper around cty.Value that adds implementations of
8// json.Marshaler and json.Unmarshaler for simple-but-type-lossy automatic
9// encoding and decoding of values.
10//
11// The couplet Marshal and Unmarshal both take extra type information to
12// inform the encoding and decoding process so that all of the cty types
13// can be represented even though JSON's type system is a subset.
14//
15// SimpleJSONValue instead takes the approach of discarding the value's type
16// information and then deriving a new type from the stored structure when
17// decoding. This results in the same data being returned but not necessarily
18// with exactly the same type.
19//
20// For information on how types are inferred when decoding, see the
21// documentation of the function ImpliedType.
22type SimpleJSONValue struct {
23 cty.Value
24}
25
26// MarshalJSON is an implementation of json.Marshaler. See the documentation
27// of SimpleJSONValue for more information.
28func (v SimpleJSONValue) MarshalJSON() ([]byte, error) {
29 return Marshal(v.Value, v.Type())
30}
31
32// UnmarshalJSON is an implementation of json.Unmarshaler. See the
33// documentation of SimpleJSONValue for more information.
34func (v *SimpleJSONValue) UnmarshalJSON(buf []byte) error {
35 t, err := ImpliedType(buf)
36 if err != nil {
37 return err
38 }
39 v.Value, err = Unmarshal(buf, t)
40 return err
41}
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/type.go b/vendor/github.com/zclconf/go-cty/cty/json/type.go
new file mode 100644
index 0000000..9131c6c
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json/type.go
@@ -0,0 +1,23 @@
1package json
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// MarshalType returns a JSON serialization of the given type.
8//
9// This is just a thin wrapper around t.MarshalJSON, for symmetry with
10// UnmarshalType.
11func MarshalType(t cty.Type) ([]byte, error) {
12 return t.MarshalJSON()
13}
14
15// UnmarshalType decodes a JSON serialization of the given type as produced
16// by either Type.MarshalJSON or MarshalType.
17//
18// This is a convenience wrapper around Type.UnmarshalJSON.
19func UnmarshalType(buf []byte) (cty.Type, error) {
20 var t cty.Type
21 err := t.UnmarshalJSON(buf)
22 return t, err
23}
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
new file mode 100644
index 0000000..1a97306
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go
@@ -0,0 +1,171 @@
1package json
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7
8 "github.com/zclconf/go-cty/cty"
9)
10
11// ImpliedType returns the cty Type implied by the structure of the given
12// JSON-compliant buffer. This function implements the default type mapping
13// behavior used when decoding arbitrary JSON without explicit cty Type
14// information.
15//
16// The rules are as follows:
17//
18// JSON strings, numbers and bools map to their equivalent primitive type in
19// cty.
20//
21// JSON objects map to cty object types, with the attributes defined by the
22// object keys and the types of their values.
23//
24// JSON arrays map to cty tuple types, with the elements defined by the
25// types of the array members.
26//
27// Any nulls are typed as DynamicPseudoType, so callers of this function
28// must be prepared to deal with this. Callers that do not wish to deal with
29// dynamic typing should not use this function and should instead describe
30// their required types explicitly with a cty.Type instance when decoding.
31//
32// Any JSON syntax errors will be returned as an error, and the type will
33// be the invalid value cty.NilType.
34func ImpliedType(buf []byte) (cty.Type, error) {
35 r := bytes.NewReader(buf)
36 dec := json.NewDecoder(r)
37 dec.UseNumber()
38
39 ty, err := impliedType(dec)
40 if err != nil {
41 return cty.NilType, err
42 }
43
44 if dec.More() {
45 return cty.NilType, fmt.Errorf("extraneous data after JSON object")
46 }
47
48 return ty, nil
49}
50
51func impliedType(dec *json.Decoder) (cty.Type, error) {
52 tok, err := dec.Token()
53 if err != nil {
54 return cty.NilType, err
55 }
56
57 return impliedTypeForTok(tok, dec)
58}
59
60func impliedTypeForTok(tok json.Token, dec *json.Decoder) (cty.Type, error) {
61 if tok == nil {
62 return cty.DynamicPseudoType, nil
63 }
64
65 switch ttok := tok.(type) {
66 case bool:
67 return cty.Bool, nil
68
69 case json.Number:
70 return cty.Number, nil
71
72 case string:
73 return cty.String, nil
74
75 case json.Delim:
76
77 switch rune(ttok) {
78 case '{':
79 return impliedObjectType(dec)
80 case '[':
81 return impliedTupleType(dec)
82 default:
83 return cty.NilType, fmt.Errorf("unexpected token %q", ttok)
84 }
85
86 default:
87 return cty.NilType, fmt.Errorf("unsupported JSON token %#v", tok)
88 }
89}
90
91func impliedObjectType(dec *json.Decoder) (cty.Type, error) {
92 // By the time we get in here, we've already consumed the { delimiter
93 // and so our next token should be the first object key.
94
95 var atys map[string]cty.Type
96
97 for {
98 // Read the object key first
99 tok, err := dec.Token()
100 if err != nil {
101 return cty.NilType, err
102 }
103
104 if ttok, ok := tok.(json.Delim); ok {
105 if rune(ttok) != '}' {
106 return cty.NilType, fmt.Errorf("unexpected delimiter %q", ttok)
107 }
108 break
109 }
110
111 key, ok := tok.(string)
112 if !ok {
113 return cty.NilType, fmt.Errorf("expected string but found %T", tok)
114 }
115
116 // Now read the value
117 tok, err = dec.Token()
118 if err != nil {
119 return cty.NilType, err
120 }
121
122 aty, err := impliedTypeForTok(tok, dec)
123 if err != nil {
124 return cty.NilType, err
125 }
126
127 if atys == nil {
128 atys = make(map[string]cty.Type)
129 }
130 atys[key] = aty
131 }
132
133 if len(atys) == 0 {
134 return cty.EmptyObject, nil
135 }
136
137 return cty.Object(atys), nil
138}
139
140func impliedTupleType(dec *json.Decoder) (cty.Type, error) {
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.
143
144 var etys []cty.Type
145
146 for {
147 tok, err := dec.Token()
148 if err != nil {
149 return cty.NilType, err
150 }
151
152 if ttok, ok := tok.(json.Delim); ok {
153 if rune(ttok) != ']' {
154 return cty.NilType, fmt.Errorf("unexpected delimiter %q", ttok)
155 }
156 break
157 }
158
159 ety, err := impliedTypeForTok(tok, dec)
160 if err != nil {
161 return cty.NilType, err
162 }
163 etys = append(etys, ety)
164 }
165
166 if len(etys) == 0 {
167 return cty.EmptyTuple, nil
168 }
169
170 return cty.Tuple(etys), nil
171}
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go b/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
new file mode 100644
index 0000000..155f0b8
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
@@ -0,0 +1,459 @@
1package json
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "reflect"
8
9 "github.com/zclconf/go-cty/cty"
10 "github.com/zclconf/go-cty/cty/convert"
11)
12
13func unmarshal(buf []byte, t cty.Type, path cty.Path) (cty.Value, error) {
14 dec := bufDecoder(buf)
15
16 tok, err := dec.Token()
17 if err != nil {
18 return cty.NilVal, path.NewError(err)
19 }
20
21 if tok == nil {
22 return cty.NullVal(t), nil
23 }
24
25 if t == cty.DynamicPseudoType {
26 return unmarshalDynamic(buf, path)
27 }
28
29 switch {
30 case t.IsPrimitiveType():
31 val, err := unmarshalPrimitive(tok, t, path)
32 if err != nil {
33 return cty.NilVal, err
34 }
35 return val, nil
36 case t.IsListType():
37 return unmarshalList(buf, t.ElementType(), path)
38 case t.IsSetType():
39 return unmarshalSet(buf, t.ElementType(), path)
40 case t.IsMapType():
41 return unmarshalMap(buf, t.ElementType(), path)
42 case t.IsTupleType():
43 return unmarshalTuple(buf, t.TupleElementTypes(), path)
44 case t.IsObjectType():
45 return unmarshalObject(buf, t.AttributeTypes(), path)
46 case t.IsCapsuleType():
47 return unmarshalCapsule(buf, t, path)
48 default:
49 return cty.NilVal, path.NewErrorf("unsupported type %s", t.FriendlyName())
50 }
51}
52
53func unmarshalPrimitive(tok json.Token, t cty.Type, path cty.Path) (cty.Value, error) {
54
55 switch t {
56 case cty.Bool:
57 switch v := tok.(type) {
58 case bool:
59 return cty.BoolVal(v), nil
60 case string:
61 val, err := convert.Convert(cty.StringVal(v), t)
62 if err != nil {
63 return cty.NilVal, path.NewError(err)
64 }
65 return val, nil
66 default:
67 return cty.NilVal, path.NewErrorf("bool is required")
68 }
69 case cty.Number:
70 if v, ok := tok.(json.Number); ok {
71 tok = string(v)
72 }
73 switch v := tok.(type) {
74 case string:
75 val, err := convert.Convert(cty.StringVal(v), t)
76 if err != nil {
77 return cty.NilVal, path.NewError(err)
78 }
79 return val, nil
80 default:
81 return cty.NilVal, path.NewErrorf("number is required")
82 }
83 case cty.String:
84 switch v := tok.(type) {
85 case string:
86 return cty.StringVal(v), nil
87 case json.Number:
88 return cty.StringVal(string(v)), nil
89 case bool:
90 val, err := convert.Convert(cty.BoolVal(v), t)
91 if err != nil {
92 return cty.NilVal, path.NewError(err)
93 }
94 return val, nil
95 default:
96 return cty.NilVal, path.NewErrorf("string is required")
97 }
98 default:
99 // should never happen
100 panic("unsupported primitive type")
101 }
102}
103
104func unmarshalList(buf []byte, ety cty.Type, path cty.Path) (cty.Value, error) {
105 dec := bufDecoder(buf)
106 if err := requireDelim(dec, '['); err != nil {
107 return cty.NilVal, path.NewError(err)
108 }
109
110 var vals []cty.Value
111
112 {
113 path := append(path, nil)
114 var idx int64
115
116 for dec.More() {
117 path[len(path)-1] = cty.IndexStep{
118 Key: cty.NumberIntVal(idx),
119 }
120 idx++
121
122 rawVal, err := readRawValue(dec)
123 if err != nil {
124 return cty.NilVal, path.NewErrorf("failed to read list value: %s", err)
125 }
126
127 el, err := unmarshal(rawVal, ety, path)
128 if err != nil {
129 return cty.NilVal, err
130 }
131
132 vals = append(vals, el)
133 }
134 }
135
136 if err := requireDelim(dec, ']'); err != nil {
137 return cty.NilVal, path.NewError(err)
138 }
139
140 if len(vals) == 0 {
141 return cty.ListValEmpty(ety), nil
142 }
143
144 return cty.ListVal(vals), nil
145}
146
147func unmarshalSet(buf []byte, ety cty.Type, path cty.Path) (cty.Value, error) {
148 dec := bufDecoder(buf)
149 if err := requireDelim(dec, '['); err != nil {
150 return cty.NilVal, path.NewError(err)
151 }
152
153 var vals []cty.Value
154
155 {
156 path := append(path, nil)
157
158 for dec.More() {
159 path[len(path)-1] = cty.IndexStep{
160 Key: cty.UnknownVal(ety),
161 }
162
163 rawVal, err := readRawValue(dec)
164 if err != nil {
165 return cty.NilVal, path.NewErrorf("failed to read set value: %s", err)
166 }
167
168 el, err := unmarshal(rawVal, ety, path)
169 if err != nil {
170 return cty.NilVal, err
171 }
172
173 vals = append(vals, el)
174 }
175 }
176
177 if err := requireDelim(dec, ']'); err != nil {
178 return cty.NilVal, path.NewError(err)
179 }
180
181 if len(vals) == 0 {
182 return cty.SetValEmpty(ety), nil
183 }
184
185 return cty.SetVal(vals), nil
186}
187
188func unmarshalMap(buf []byte, ety cty.Type, path cty.Path) (cty.Value, error) {
189 dec := bufDecoder(buf)
190 if err := requireDelim(dec, '{'); err != nil {
191 return cty.NilVal, path.NewError(err)
192 }
193
194 vals := make(map[string]cty.Value)
195
196 {
197 path := append(path, nil)
198
199 for dec.More() {
200 path[len(path)-1] = cty.IndexStep{
201 Key: cty.UnknownVal(cty.String),
202 }
203
204 var err error
205
206 k, err := requireObjectKey(dec)
207 if err != nil {
208 return cty.NilVal, path.NewErrorf("failed to read map key: %s", err)
209 }
210
211 path[len(path)-1] = cty.IndexStep{
212 Key: cty.StringVal(k),
213 }
214
215 rawVal, err := readRawValue(dec)
216 if err != nil {
217 return cty.NilVal, path.NewErrorf("failed to read map value: %s", err)
218 }
219
220 el, err := unmarshal(rawVal, ety, path)
221 if err != nil {
222 return cty.NilVal, err
223 }
224
225 vals[k] = el
226 }
227 }
228
229 if err := requireDelim(dec, '}'); err != nil {
230 return cty.NilVal, path.NewError(err)
231 }
232
233 if len(vals) == 0 {
234 return cty.MapValEmpty(ety), nil
235 }
236
237 return cty.MapVal(vals), nil
238}
239
240func unmarshalTuple(buf []byte, etys []cty.Type, path cty.Path) (cty.Value, error) {
241 dec := bufDecoder(buf)
242 if err := requireDelim(dec, '['); err != nil {
243 return cty.NilVal, path.NewError(err)
244 }
245
246 var vals []cty.Value
247
248 {
249 path := append(path, nil)
250 var idx int
251
252 for dec.More() {
253 if idx >= len(etys) {
254 return cty.NilVal, path[:len(path)-1].NewErrorf("too many tuple elements (need %d)", len(etys))
255 }
256
257 path[len(path)-1] = cty.IndexStep{
258 Key: cty.NumberIntVal(int64(idx)),
259 }
260 ety := etys[idx]
261 idx++
262
263 rawVal, err := readRawValue(dec)
264 if err != nil {
265 return cty.NilVal, path.NewErrorf("failed to read tuple value: %s", err)
266 }
267
268 el, err := unmarshal(rawVal, ety, path)
269 if err != nil {
270 return cty.NilVal, err
271 }
272
273 vals = append(vals, el)
274 }
275 }
276
277 if err := requireDelim(dec, ']'); err != nil {
278 return cty.NilVal, path.NewError(err)
279 }
280
281 if len(vals) != len(etys) {
282 return cty.NilVal, path[:len(path)-1].NewErrorf("not enough tuple elements (need %d)", len(etys))
283 }
284
285 if len(vals) == 0 {
286 return cty.EmptyTupleVal, nil
287 }
288
289 return cty.TupleVal(vals), nil
290}
291
292func unmarshalObject(buf []byte, atys map[string]cty.Type, path cty.Path) (cty.Value, error) {
293 dec := bufDecoder(buf)
294 if err := requireDelim(dec, '{'); err != nil {
295 return cty.NilVal, path.NewError(err)
296 }
297
298 vals := make(map[string]cty.Value)
299
300 {
301 objPath := path // some errors report from the object's perspective
302 path := append(path, nil) // path to a specific attribute
303
304 for dec.More() {
305
306 var err error
307
308 k, err := requireObjectKey(dec)
309 if err != nil {
310 return cty.NilVal, path.NewErrorf("failed to read object key: %s", err)
311 }
312
313 aty, ok := atys[k]
314 if !ok {
315 return cty.NilVal, objPath.NewErrorf("unsupported attribute %q", k)
316 }
317
318 path[len(path)-1] = cty.GetAttrStep{
319 Name: k,
320 }
321
322 rawVal, err := readRawValue(dec)
323 if err != nil {
324 return cty.NilVal, path.NewErrorf("failed to read object value: %s", err)
325 }
326
327 el, err := unmarshal(rawVal, aty, path)
328 if err != nil {
329 return cty.NilVal, err
330 }
331
332 vals[k] = el
333 }
334 }
335
336 if err := requireDelim(dec, '}'); err != nil {
337 return cty.NilVal, path.NewError(err)
338 }
339
340 // Make sure we have a value for every attribute
341 for k, aty := range atys {
342 if _, exists := vals[k]; !exists {
343 vals[k] = cty.NullVal(aty)
344 }
345 }
346
347 if len(vals) == 0 {
348 return cty.EmptyObjectVal, nil
349 }
350
351 return cty.ObjectVal(vals), nil
352}
353
354func unmarshalCapsule(buf []byte, t cty.Type, path cty.Path) (cty.Value, error) {
355 rawType := t.EncapsulatedType()
356 ptrPtr := reflect.New(reflect.PtrTo(rawType))
357 ptrPtr.Elem().Set(reflect.New(rawType))
358 ptr := ptrPtr.Elem().Interface()
359 err := json.Unmarshal(buf, ptr)
360 if err != nil {
361 return cty.NilVal, path.NewError(err)
362 }
363
364 return cty.CapsuleVal(t, ptr), nil
365}
366
367func unmarshalDynamic(buf []byte, path cty.Path) (cty.Value, error) {
368 dec := bufDecoder(buf)
369 if err := requireDelim(dec, '{'); err != nil {
370 return cty.NilVal, path.NewError(err)
371 }
372
373 var t cty.Type
374 var valBody []byte // defer actual decoding until we know the type
375
376 for dec.More() {
377 var err error
378
379 key, err := requireObjectKey(dec)
380 if err != nil {
381 return cty.NilVal, path.NewErrorf("failed to read dynamic type descriptor key: %s", err)
382 }
383
384 rawVal, err := readRawValue(dec)
385 if err != nil {
386 return cty.NilVal, path.NewErrorf("failed to read dynamic type descriptor value: %s", err)
387 }
388
389 switch key {
390 case "type":
391 err := json.Unmarshal(rawVal, &t)
392 if err != nil {
393 return cty.NilVal, path.NewErrorf("failed to decode type for dynamic value: %s", err)
394 }
395 case "value":
396 valBody = rawVal
397 default:
398 return cty.NilVal, path.NewErrorf("invalid key %q in dynamically-typed value", key)
399 }
400
401 }
402
403 if err := requireDelim(dec, '}'); err != nil {
404 return cty.NilVal, path.NewError(err)
405 }
406
407 if t == cty.NilType {
408 return cty.NilVal, path.NewErrorf("missing type in dynamically-typed value")
409 }
410 if valBody == nil {
411 return cty.NilVal, path.NewErrorf("missing value in dynamically-typed value")
412 }
413
414 val, err := Unmarshal([]byte(valBody), t)
415 if err != nil {
416 return cty.NilVal, path.NewError(err)
417 }
418 return val, nil
419}
420
421func requireDelim(dec *json.Decoder, d rune) error {
422 tok, err := dec.Token()
423 if err != nil {
424 return err
425 }
426
427 if tok != json.Delim(d) {
428 return fmt.Errorf("missing expected %c", d)
429 }
430
431 return nil
432}
433
434func requireObjectKey(dec *json.Decoder) (string, error) {
435 tok, err := dec.Token()
436 if err != nil {
437 return "", err
438 }
439 if s, ok := tok.(string); ok {
440 return s, nil
441 }
442 return "", fmt.Errorf("missing expected object key")
443}
444
445func readRawValue(dec *json.Decoder) ([]byte, error) {
446 var rawVal json.RawMessage
447 err := dec.Decode(&rawVal)
448 if err != nil {
449 return nil, err
450 }
451 return []byte(rawVal), nil
452}
453
454func bufDecoder(buf []byte) *json.Decoder {
455 r := bytes.NewReader(buf)
456 dec := json.NewDecoder(r)
457 dec.UseNumber()
458 return dec
459}
diff --git a/vendor/github.com/zclconf/go-cty/cty/json/value.go b/vendor/github.com/zclconf/go-cty/cty/json/value.go
new file mode 100644
index 0000000..f2f7dd5
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/json/value.go
@@ -0,0 +1,65 @@
1package json
2
3import (
4 "bytes"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/convert"
8)
9
10// Marshal produces a JSON representation of the given value that can later
11// be decoded into a value of the given type.
12//
13// A type is specified separately to allow for the given type to include
14// cty.DynamicPseudoType to represent situations where any type is permitted
15// and so type information must be included to allow recovery of the stored
16// structure when decoding.
17//
18// The given type will also be used to attempt automatic conversions of any
19// non-conformant types in the given value, although this will not always
20// be possible. If the value cannot be made to be conformant then an error is
21// returned, which may be a cty.PathError.
22//
23// Capsule-typed values can be marshalled, but with some caveats. Since
24// capsule values are compared by pointer equality, it is impossible to recover
25// a value that will compare equal to the original value. Additionally,
26// it's not possible to JSON-serialize the capsule type itself, so it's not
27// valid to use capsule types within parts of the value that are conformed to
28// cty.DynamicPseudoType. Otherwise, a capsule value can be used as long as
29// the encapsulated type itself is serializable with the Marshal function
30// in encoding/json.
31func Marshal(val cty.Value, t cty.Type) ([]byte, error) {
32 errs := val.Type().TestConformance(t)
33 if errs != nil {
34 // Attempt a conversion
35 var err error
36 val, err = convert.Convert(val, t)
37 if err != nil {
38 return nil, err
39 }
40 }
41
42 // From this point onward, val can be assumed to be conforming to t.
43
44 buf := &bytes.Buffer{}
45 var path cty.Path
46 err := marshal(val, t, path, buf)
47
48 if err != nil {
49 return nil, err
50 }
51
52 return buf.Bytes(), nil
53}
54
55// Unmarshal decodes a JSON representation of the given value into a cty Value
56// conforming to the given type.
57//
58// While decoding, type conversions will be done where possible to make
59// the result conformant even if the types given in JSON are not exactly
60// correct. If conversion isn't possible then an error is returned, which
61// may be a cty.PathError.
62func Unmarshal(buf []byte, t cty.Type) (cty.Value, error) {
63 var path cty.Path
64 return unmarshal(buf, t, path)
65}
diff --git a/vendor/github.com/zclconf/go-cty/cty/list_type.go b/vendor/github.com/zclconf/go-cty/cty/list_type.go
new file mode 100644
index 0000000..eadc865
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/list_type.go
@@ -0,0 +1,68 @@
1package cty
2
3import (
4 "fmt"
5)
6
7// TypeList instances represent specific list types. Each distinct ElementType
8// creates a distinct, non-equal list type.
9type typeList struct {
10 typeImplSigil
11 ElementTypeT Type
12}
13
14// List creates a map type with the given element Type.
15//
16// List types are CollectionType implementations.
17func List(elem Type) Type {
18 return Type{
19 typeList{
20 ElementTypeT: elem,
21 },
22 }
23}
24
25// Equals returns true if the other Type is a list whose element type is
26// equal to that of the receiver.
27func (t typeList) Equals(other Type) bool {
28 ot, isList := other.typeImpl.(typeList)
29 if !isList {
30 return false
31 }
32
33 return t.ElementTypeT.Equals(ot.ElementTypeT)
34}
35
36func (t typeList) FriendlyName() string {
37 return "list of " + t.ElementTypeT.FriendlyName()
38}
39
40func (t typeList) ElementType() Type {
41 return t.ElementTypeT
42}
43
44func (t typeList) GoString() string {
45 return fmt.Sprintf("cty.List(%#v)", t.ElementTypeT)
46}
47
48// IsListType returns true if the given type is a list type, regardless of its
49// element type.
50func (t Type) IsListType() bool {
51 _, ok := t.typeImpl.(typeList)
52 return ok
53}
54
55// ListElementType is a convenience method that checks if the given type is
56// a list type, returning a pointer to its element type if so and nil
57// otherwise. This is intended to allow convenient conditional branches,
58// like so:
59//
60// if et := t.ListElementType(); et != nil {
61// // Do something with *et
62// }
63func (t Type) ListElementType() *Type {
64 if lt, ok := t.typeImpl.(typeList); ok {
65 return &lt.ElementTypeT
66 }
67 return nil
68}
diff --git a/vendor/github.com/zclconf/go-cty/cty/map_type.go b/vendor/github.com/zclconf/go-cty/cty/map_type.go
new file mode 100644
index 0000000..ae9abae
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/map_type.go
@@ -0,0 +1,68 @@
1package cty
2
3import (
4 "fmt"
5)
6
7// TypeList instances represent specific list types. Each distinct ElementType
8// creates a distinct, non-equal list type.
9type typeMap struct {
10 typeImplSigil
11 ElementTypeT Type
12}
13
14// Map creates a map type with the given element Type.
15//
16// Map types are CollectionType implementations.
17func Map(elem Type) Type {
18 return Type{
19 typeMap{
20 ElementTypeT: elem,
21 },
22 }
23}
24
25// Equals returns true if the other Type is a map whose element type is
26// equal to that of the receiver.
27func (t typeMap) Equals(other Type) bool {
28 ot, isMap := other.typeImpl.(typeMap)
29 if !isMap {
30 return false
31 }
32
33 return t.ElementTypeT.Equals(ot.ElementTypeT)
34}
35
36func (t typeMap) FriendlyName() string {
37 return "map of " + t.ElementTypeT.FriendlyName()
38}
39
40func (t typeMap) ElementType() Type {
41 return t.ElementTypeT
42}
43
44func (t typeMap) GoString() string {
45 return fmt.Sprintf("cty.Map(%#v)", t.ElementTypeT)
46}
47
48// IsMapType returns true if the given type is a list type, regardless of its
49// element type.
50func (t Type) IsMapType() bool {
51 _, ok := t.typeImpl.(typeMap)
52 return ok
53}
54
55// MapElementType is a convenience method that checks if the given type is
56// a map type, returning a pointer to its element type if so and nil
57// otherwise. This is intended to allow convenient conditional branches,
58// like so:
59//
60// if et := t.MapElementType(); et != nil {
61// // Do something with *et
62// }
63func (t Type) MapElementType() *Type {
64 if lt, ok := t.typeImpl.(typeMap); ok {
65 return &lt.ElementTypeT
66 }
67 return nil
68}
diff --git a/vendor/github.com/zclconf/go-cty/cty/null.go b/vendor/github.com/zclconf/go-cty/cty/null.go
new file mode 100644
index 0000000..d58d028
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/null.go
@@ -0,0 +1,14 @@
1package cty
2
3// NullVal returns a null value of the given type. A null can be created of any
4// type, but operations on such values will always panic. Calling applications
5// are encouraged to use nulls only sparingly, particularly when user-provided
6// expressions are to be evaluated, since the precence of nulls creates a
7// much higher chance of evaluation errors that can't be caught by a type
8// checker.
9func NullVal(t Type) Value {
10 return Value{
11 ty: t,
12 v: nil,
13 }
14}
diff --git a/vendor/github.com/zclconf/go-cty/cty/object_type.go b/vendor/github.com/zclconf/go-cty/cty/object_type.go
new file mode 100644
index 0000000..2540883
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/object_type.go
@@ -0,0 +1,135 @@
1package cty
2
3import (
4 "fmt"
5)
6
7type typeObject struct {
8 typeImplSigil
9 AttrTypes map[string]Type
10}
11
12// Object creates an object type with the given attribute types.
13//
14// After a map is passed to this function the caller must no longer access it,
15// since ownership is transferred to this library.
16func Object(attrTypes map[string]Type) Type {
17 attrTypesNorm := make(map[string]Type, len(attrTypes))
18 for k, v := range attrTypes {
19 attrTypesNorm[NormalizeString(k)] = v
20 }
21
22 return Type{
23 typeObject{
24 AttrTypes: attrTypesNorm,
25 },
26 }
27}
28
29func (t typeObject) Equals(other Type) bool {
30 if ot, ok := other.typeImpl.(typeObject); ok {
31 if len(t.AttrTypes) != len(ot.AttrTypes) {
32 // Fast path: if we don't have the same number of attributes
33 // then we can't possibly be equal. This also avoids the need
34 // to test attributes in both directions below, since we know
35 // there can't be extras in "other".
36 return false
37 }
38
39 for attr, ty := range t.AttrTypes {
40 oty, ok := ot.AttrTypes[attr]
41 if !ok {
42 return false
43 }
44 if !oty.Equals(ty) {
45 return false
46 }
47 }
48
49 return true
50 }
51 return false
52}
53
54func (t typeObject) FriendlyName() string {
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
57 // probably want to make some extra effort to avoid ever printing out
58 // an object type FriendlyName in its entirety. For example, could
59 // produce an error message by diffing two object types and saying
60 // something like "Expected attribute foo to be string, but got number".
61 // TODO: Finish this
62 return "object"
63}
64
65func (t typeObject) GoString() string {
66 if len(t.AttrTypes) == 0 {
67 return "cty.EmptyObject"
68 }
69 return fmt.Sprintf("cty.Object(%#v)", t.AttrTypes)
70}
71
72// EmptyObject is a shorthand for Object(map[string]Type{}), to more
73// easily talk about the empty object type.
74var EmptyObject Type
75
76// EmptyObjectVal is the only possible non-null, non-unknown value of type
77// EmptyObject.
78var EmptyObjectVal Value
79
80func init() {
81 EmptyObject = Object(map[string]Type{})
82 EmptyObjectVal = Value{
83 ty: EmptyObject,
84 v: map[string]interface{}{},
85 }
86}
87
88// IsObjectType returns true if the given type is an object type, regardless
89// of its element type.
90func (t Type) IsObjectType() bool {
91 _, ok := t.typeImpl.(typeObject)
92 return ok
93}
94
95// HasAttribute returns true if the receiver has an attribute with the given
96// name, regardless of its type. Will panic if the reciever isn't an object
97// type; use IsObjectType to determine whether this operation will succeed.
98func (t Type) HasAttribute(name string) bool {
99 name = NormalizeString(name)
100 if ot, ok := t.typeImpl.(typeObject); ok {
101 _, hasAttr := ot.AttrTypes[name]
102 return hasAttr
103 }
104 panic("HasAttribute on non-object Type")
105}
106
107// AttributeType returns the type of the attribute with the given name. Will
108// panic if the receiver is not an object type (use IsObjectType to confirm)
109// or if the object type has no such attribute (use HasAttribute to confirm).
110func (t Type) AttributeType(name string) Type {
111 name = NormalizeString(name)
112 if ot, ok := t.typeImpl.(typeObject); ok {
113 aty, hasAttr := ot.AttrTypes[name]
114 if !hasAttr {
115 panic("no such attribute")
116 }
117 return aty
118 }
119 panic("AttributeType on non-object Type")
120}
121
122// AttributeTypes returns a map from attribute names to their associated
123// types. Will panic if the receiver is not an object type (use IsObjectType
124// to confirm).
125//
126// The returned map is part of the internal state of the type, and is provided
127// for read access only. It is forbidden for any caller to modify the returned
128// map. For many purposes the attribute-related methods of Value are more
129// appropriate and more convenient to use.
130func (t Type) AttributeTypes() map[string]Type {
131 if ot, ok := t.typeImpl.(typeObject); ok {
132 return ot.AttrTypes
133 }
134 panic("AttributeTypes on non-object Type")
135}
diff --git a/vendor/github.com/zclconf/go-cty/cty/path.go b/vendor/github.com/zclconf/go-cty/cty/path.go
new file mode 100644
index 0000000..84a9de0
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/path.go
@@ -0,0 +1,186 @@
1package cty
2
3import (
4 "errors"
5 "fmt"
6)
7
8// A Path is a sequence of operations to locate a nested value within a
9// data structure.
10//
11// The empty Path represents the given item. Any PathSteps within represent
12// taking a single step down into a data structure.
13//
14// Path has some convenience methods for gradually constructing a path,
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
17// where memory pressure is a concern.
18type Path []PathStep
19
20// PathStep represents a single step down into a data structure, as part
21// of a Path. PathStep is a closed interface, meaning that the only
22// permitted implementations are those within this package.
23type PathStep interface {
24 pathStepSigil() pathStepImpl
25 Apply(Value) (Value, error)
26}
27
28// embed pathImpl into a struct to declare it a PathStep implementation
29type pathStepImpl struct{}
30
31func (p pathStepImpl) pathStepSigil() pathStepImpl {
32 return p
33}
34
35// Index returns a new Path that is the reciever with an IndexStep appended
36// to the end.
37//
38// This is provided as a convenient way to construct paths, but each call
39// will create garbage so it should not be used where memory pressure is a
40// concern.
41func (p Path) Index(v Value) Path {
42 ret := make(Path, len(p)+1)
43 copy(ret, p)
44 ret[len(p)] = IndexStep{
45 Key: v,
46 }
47 return ret
48}
49
50// GetAttr returns a new Path that is the reciever with a GetAttrStep appended
51// to the end.
52//
53// This is provided as a convenient way to construct paths, but each call
54// will create garbage so it should not be used where memory pressure is a
55// concern.
56func (p Path) GetAttr(name string) Path {
57 ret := make(Path, len(p)+1)
58 copy(ret, p)
59 ret[len(p)] = GetAttrStep{
60 Name: name,
61 }
62 return ret
63}
64
65// 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,
67// the whole operation returns an error.
68func (p Path) Apply(val Value) (Value, error) {
69 var err error
70 for i, step := range p {
71 val, err = step.Apply(val)
72 if err != nil {
73 return NilVal, fmt.Errorf("at step %d: %s", i, err)
74 }
75 }
76 return val, nil
77}
78
79// LastStep applies the given path up to the last step and then returns
80// the resulting value and the final step.
81//
82// This is useful when dealing with assignment operations, since in that
83// case the *value* of the last step is not important (and may not, in fact,
84// present at all) and we care only about its location.
85//
86// Since LastStep applies all steps except the last, it will return errors
87// for those steps in the same way as Apply does.
88//
89// If the path has *no* steps then the returned PathStep will be nil,
90// representing that any operation should be applied directly to the
91// given value.
92func (p Path) LastStep(val Value) (Value, PathStep, error) {
93 var err error
94
95 if len(p) == 0 {
96 return val, nil, nil
97 }
98
99 journey := p[:len(p)-1]
100 val, err = journey.Apply(val)
101 if err != nil {
102 return NilVal, nil, err
103 }
104 return val, p[len(p)-1], nil
105}
106
107// Copy makes a shallow copy of the receiver. Often when paths are passed to
108// caller code they come with the constraint that they are valid only until
109// the caller returns, due to how they are constructed internally. Callers
110// can use Copy to conveniently produce a copy of the value that _they_ control
111// the validity of.
112func (p Path) Copy() Path {
113 ret := make(Path, len(p))
114 copy(ret, p)
115 return ret
116}
117
118// IndexStep is a Step implementation representing applying the index operation
119// to a value, which must be of either a list, map, or set type.
120//
121// When describing a path through a *type* rather than a concrete value,
122// the Key may be an unknown value, indicating that the step applies to
123// *any* key of the given type.
124//
125// When indexing into a set, the Key is actually the element being accessed
126// itself, since in sets elements are their own identity.
127type IndexStep struct {
128 pathStepImpl
129 Key Value
130}
131
132// Apply returns the value resulting from indexing the given value with
133// our key value.
134func (s IndexStep) Apply(val Value) (Value, error) {
135 switch s.Key.Type() {
136 case Number:
137 if !val.Type().IsListType() {
138 return NilVal, errors.New("not a list type")
139 }
140 case String:
141 if !val.Type().IsMapType() {
142 return NilVal, errors.New("not a map type")
143 }
144 default:
145 return NilVal, errors.New("key value not number or string")
146 }
147
148 has := val.HasIndex(s.Key)
149 if !has.IsKnown() {
150 return UnknownVal(val.Type().ElementType()), nil
151 }
152 if !has.True() {
153 return NilVal, errors.New("value does not have given index key")
154 }
155
156 return val.Index(s.Key), nil
157}
158
159func (s IndexStep) GoString() string {
160 return fmt.Sprintf("cty.IndexStep{Key:%#v}", s.Key)
161}
162
163// GetAttrStep is a Step implementation representing retrieving an attribute
164// from a value, which must be of an object type.
165type GetAttrStep struct {
166 pathStepImpl
167 Name string
168}
169
170// 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.
172func (s GetAttrStep) Apply(val Value) (Value, error) {
173 if !val.Type().IsObjectType() {
174 return NilVal, errors.New("not an object type")
175 }
176
177 if !val.Type().HasAttribute(s.Name) {
178 return NilVal, fmt.Errorf("object has no attribute %q", s.Name)
179 }
180
181 return val.GetAttr(s.Name), nil
182}
183
184func (s GetAttrStep) GoString() string {
185 return fmt.Sprintf("cty.GetAttrStep{Name:%q}", s.Name)
186}
diff --git a/vendor/github.com/zclconf/go-cty/cty/primitive_type.go b/vendor/github.com/zclconf/go-cty/cty/primitive_type.go
new file mode 100644
index 0000000..b8682dd
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/primitive_type.go
@@ -0,0 +1,122 @@
1package cty
2
3import "math/big"
4
5// primitiveType is the hidden implementation of the various primitive types
6// that are exposed as variables in this package.
7type primitiveType struct {
8 typeImplSigil
9 Kind primitiveTypeKind
10}
11
12type primitiveTypeKind byte
13
14const (
15 primitiveTypeBool primitiveTypeKind = 'B'
16 primitiveTypeNumber primitiveTypeKind = 'N'
17 primitiveTypeString primitiveTypeKind = 'S'
18)
19
20func (t primitiveType) Equals(other Type) bool {
21 if otherP, ok := other.typeImpl.(primitiveType); ok {
22 return otherP.Kind == t.Kind
23 }
24 return false
25}
26
27func (t primitiveType) FriendlyName() string {
28 switch t.Kind {
29 case primitiveTypeBool:
30 return "bool"
31 case primitiveTypeNumber:
32 return "number"
33 case primitiveTypeString:
34 return "string"
35 default:
36 // should never happen
37 panic("invalid primitive type")
38 }
39}
40
41func (t primitiveType) GoString() string {
42 switch t.Kind {
43 case primitiveTypeBool:
44 return "cty.Bool"
45 case primitiveTypeNumber:
46 return "cty.Number"
47 case primitiveTypeString:
48 return "cty.String"
49 default:
50 // should never happen
51 panic("invalid primitive type")
52 }
53}
54
55// Number is the numeric type. Number values are arbitrary-precision
56// decimal numbers, which can then be converted into Go's various numeric
57// types only if they are in the appropriate range.
58var Number Type
59
60// String is the string type. String values are sequences of unicode codepoints
61// encoded internally as UTF-8.
62var String Type
63
64// Bool is the boolean type. The two values of this type are True and False.
65var Bool Type
66
67// True is the truthy value of type Bool
68var True Value
69
70// False is the falsey value of type Bool
71var False Value
72
73// Zero is a number value representing exactly zero.
74var Zero Value
75
76// PositiveInfinity is a Number value representing positive infinity
77var PositiveInfinity Value
78
79// NegativeInfinity is a Number value representing negative infinity
80var NegativeInfinity Value
81
82func init() {
83 Number = Type{
84 primitiveType{Kind: primitiveTypeNumber},
85 }
86 String = Type{
87 primitiveType{Kind: primitiveTypeString},
88 }
89 Bool = Type{
90 primitiveType{Kind: primitiveTypeBool},
91 }
92 True = Value{
93 ty: Bool,
94 v: true,
95 }
96 False = Value{
97 ty: Bool,
98 v: false,
99 }
100 Zero = Value{
101 ty: Number,
102 v: big.NewFloat(0),
103 }
104 PositiveInfinity = Value{
105 ty: Number,
106 v: (&big.Float{}).SetInf(false),
107 }
108 NegativeInfinity = Value{
109 ty: Number,
110 v: (&big.Float{}).SetInf(true),
111 }
112}
113
114// IsPrimitiveType returns true if and only if the reciever is a primitive
115// type, which means it's either number, string, or bool. Any two primitive
116// types can be safely compared for equality using the standard == operator
117// without panic, which is not a guarantee that holds for all types. Primitive
118// types can therefore also be used in switch statements.
119func (t Type) IsPrimitiveType() bool {
120 _, ok := t.typeImpl.(primitiveType)
121 return ok
122}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/gob.go b/vendor/github.com/zclconf/go-cty/cty/set/gob.go
new file mode 100644
index 0000000..da2978f
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/gob.go
@@ -0,0 +1,76 @@
1package set
2
3import (
4 "bytes"
5 "encoding/gob"
6 "fmt"
7)
8
9// GobEncode is an implementation of the interface gob.GobEncoder, allowing
10// sets to be included in structures encoded via gob.
11//
12// The set rules are included in the serialized value, so the caller must
13// register its concrete rules type with gob.Register before using a
14// set in a gob, and possibly also implement GobEncode/GobDecode to customize
15// how any parameters are persisted.
16//
17// The set elements are also included, so if they are of non-primitive types
18// they too must be registered with gob.
19//
20// If the produced gob values will persist for a long time, the caller must
21// ensure compatibility of the rules implementation. In particular, if the
22// definition of element equivalence changes between encoding and decoding
23// then two distinct stored elements may be considered equivalent on decoding,
24// causing the recovered set to have fewer elements than when it was stored.
25func (s Set) GobEncode() ([]byte, error) {
26 gs := gobSet{
27 Version: 0,
28 Rules: s.rules,
29 Values: s.Values(),
30 }
31
32 buf := &bytes.Buffer{}
33 enc := gob.NewEncoder(buf)
34 err := enc.Encode(gs)
35 if err != nil {
36 return nil, fmt.Errorf("error encoding set.Set: %s", err)
37 }
38
39 return buf.Bytes(), nil
40}
41
42// GobDecode is the opposite of GobEncode. See GobEncode for information
43// on the requirements for and caveats of including set values in gobs.
44func (s *Set) GobDecode(buf []byte) error {
45 r := bytes.NewReader(buf)
46 dec := gob.NewDecoder(r)
47
48 var gs gobSet
49 err := dec.Decode(&gs)
50 if err != nil {
51 return fmt.Errorf("error decoding set.Set: %s", err)
52 }
53 if gs.Version != 0 {
54 return fmt.Errorf("unsupported set.Set encoding version %d; need 0", gs.Version)
55 }
56
57 victim := NewSetFromSlice(gs.Rules, gs.Values)
58 s.vals = victim.vals
59 s.rules = victim.rules
60 return nil
61}
62
63type gobSet struct {
64 Version int
65 Rules Rules
66
67 // The bucket-based representation is for efficient in-memory access, but
68 // for serialization it's enough to just retain the values themselves,
69 // which we can re-bucket using the rules (which may have changed!) when
70 // we re-inflate.
71 Values []interface{}
72}
73
74func init() {
75 gob.Register([]interface{}(nil))
76}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/iterator.go b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
new file mode 100644
index 0000000..f15498e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
@@ -0,0 +1,36 @@
1package set
2
3type Iterator struct {
4 bucketIds []int
5 vals map[int][]interface{}
6 bucketIdx int
7 valIdx int
8}
9
10func (it *Iterator) Value() interface{} {
11 return it.currentBucket()[it.valIdx]
12}
13
14func (it *Iterator) Next() bool {
15 if it.bucketIdx == -1 {
16 // init
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}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/ops.go b/vendor/github.com/zclconf/go-cty/cty/set/ops.go
new file mode 100644
index 0000000..726e707
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/ops.go
@@ -0,0 +1,199 @@
1package set
2
3import (
4 "sort"
5)
6
7// Add inserts the given value into the receiving Set.
8//
9// This mutates the set in-place. This operation is not thread-safe.
10func (s Set) Add(val interface{}) {
11 hv := s.rules.Hash(val)
12 if _, ok := s.vals[hv]; !ok {
13 s.vals[hv] = make([]interface{}, 0, 1)
14 }
15 bucket := s.vals[hv]
16
17 // See if an equivalent value is already present
18 for _, ev := range bucket {
19 if s.rules.Equivalent(val, ev) {
20 return
21 }
22 }
23
24 s.vals[hv] = append(bucket, val)
25}
26
27// Remove deletes the given value from the receiving set, if indeed it was
28// there in the first place. If the value is not present, this is a no-op.
29func (s Set) Remove(val interface{}) {
30 hv := s.rules.Hash(val)
31 bucket, ok := s.vals[hv]
32 if !ok {
33 return
34 }
35
36 for i, ev := range bucket {
37 if s.rules.Equivalent(val, ev) {
38 newBucket := make([]interface{}, 0, len(bucket)-1)
39 newBucket = append(newBucket, bucket[:i]...)
40 newBucket = append(newBucket, bucket[i+1:]...)
41 if len(newBucket) > 0 {
42 s.vals[hv] = newBucket
43 } else {
44 delete(s.vals, hv)
45 }
46 return
47 }
48 }
49}
50
51// Has returns true if the given value is in the receiving set, or false if
52// it is not.
53func (s Set) Has(val interface{}) bool {
54 hv := s.rules.Hash(val)
55 bucket, ok := s.vals[hv]
56 if !ok {
57 return false
58 }
59
60 for _, ev := range bucket {
61 if s.rules.Equivalent(val, ev) {
62 return true
63 }
64 }
65 return false
66}
67
68// Copy performs a shallow copy of the receiving set, returning a new set
69// with the same rules and elements.
70func (s Set) Copy() Set {
71 ret := NewSet(s.rules)
72 for k, v := range s.vals {
73 ret.vals[k] = v
74 }
75 return ret
76}
77
78// Iterator returns an iterator over values in the set, in an undefined order
79// that callers should not depend on.
80//
81// The pattern for using the returned iterator is:
82//
83// it := set.Iterator()
84// for it.Next() {
85// val := it.Value()
86// // ...
87// }
88//
89// Once an iterator has been created for a set, the set *must not* be mutated
90// until the iterator is no longer in use.
91func (s Set) Iterator() *Iterator {
92 // Sort the bucketIds to ensure that we always traverse in a
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
100 return &Iterator{
101 bucketIds: bucketIds,
102 vals: s.vals,
103 bucketIdx: -1,
104 }
105}
106
107// EachValue calls the given callback once for each value in the set, in an
108// undefined order that callers should not depend on.
109func (s Set) EachValue(cb func(interface{})) {
110 it := s.Iterator()
111 for it.Next() {
112 cb(it.Value())
113 }
114}
115
116// Values returns a slice of all of the values in the set in no particular
117// order. This is just a wrapper around EachValue that accumulates the results
118// in a slice for caller convenience.
119//
120// The returned slice will be nil if there are no values in the set.
121func (s Set) Values() []interface{} {
122 var ret []interface{}
123 s.EachValue(func(v interface{}) {
124 ret = append(ret, v)
125 })
126 return ret
127}
128
129// Length returns the number of values in the set.
130func (s Set) Length() int {
131 var count int
132 for _, bucket := range s.vals {
133 count = count + len(bucket)
134 }
135 return count
136}
137
138// Union returns a new set that contains all of the members of both the
139// receiving set and the given set. Both sets must have the same rules, or
140// else this function will panic.
141func (s1 Set) Union(s2 Set) Set {
142 mustHaveSameRules(s1, s2)
143 rs := NewSet(s1.rules)
144 s1.EachValue(func(v interface{}) {
145 rs.Add(v)
146 })
147 s2.EachValue(func(v interface{}) {
148 rs.Add(v)
149 })
150 return rs
151}
152
153// Intersection returns a new set that contains the values that both the
154// receiver and given sets have in common. Both sets must have the same rules,
155// or else this function will panic.
156func (s1 Set) Intersection(s2 Set) Set {
157 mustHaveSameRules(s1, s2)
158 rs := NewSet(s1.rules)
159 s1.EachValue(func(v interface{}) {
160 if s2.Has(v) {
161 rs.Add(v)
162 }
163 })
164 return rs
165}
166
167// Subtract returns a new set that contains all of the values from the receiver
168// that are not also in the given set. Both sets must have the same rules,
169// or else this function will panic.
170func (s1 Set) Subtract(s2 Set) Set {
171 mustHaveSameRules(s1, s2)
172 rs := NewSet(s1.rules)
173 s1.EachValue(func(v interface{}) {
174 if !s2.Has(v) {
175 rs.Add(v)
176 }
177 })
178 return rs
179}
180
181// SymmetricDifference returns a new set that contains all of the values from
182// both the receiver and given sets, except those that both sets have in
183// common. Both sets must have the same rules, or else this function will
184// panic.
185func (s1 Set) SymmetricDifference(s2 Set) Set {
186 mustHaveSameRules(s1, s2)
187 rs := NewSet(s1.rules)
188 s1.EachValue(func(v interface{}) {
189 if !s2.Has(v) {
190 rs.Add(v)
191 }
192 })
193 s2.EachValue(func(v interface{}) {
194 if !s1.Has(v) {
195 rs.Add(v)
196 }
197 })
198 return rs
199}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/rules.go b/vendor/github.com/zclconf/go-cty/cty/set/rules.go
new file mode 100644
index 0000000..7200184
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/rules.go
@@ -0,0 +1,25 @@
1package set
2
3// Rules represents the operations that define membership for a Set.
4//
5// Each Set has a Rules instance, whose methods must satisfy the interface
6// contracts given below for any value that will be added to the set.
7type Rules interface {
8 // Hash returns an int that somewhat-uniquely identifies the given value.
9 //
10 // A good hash function will minimize collisions for values that will be
11 // added to the set, though collisions *are* permitted. Collisions will
12 // simply reduce the efficiency of operations on the set.
13 Hash(interface{}) int
14
15 // Equivalent returns true if and only if the two values are considered
16 // equivalent for the sake of set membership. Two values that are
17 // equivalent cannot exist in the set at the same time, and if two
18 // equivalent values are added it is undefined which one will be
19 // returned when enumerating all of the set members.
20 //
21 // Two values that are equivalent *must* result in the same hash value,
22 // though it is *not* required that two values with the same hash value
23 // be equivalent.
24 Equivalent(interface{}, interface{}) bool
25}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set/set.go b/vendor/github.com/zclconf/go-cty/cty/set/set.go
new file mode 100644
index 0000000..b4fb316
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set/set.go
@@ -0,0 +1,62 @@
1package set
2
3import (
4 "fmt"
5)
6
7// Set is an implementation of the concept of a set: a collection where all
8// values are conceptually either in or out of the set, but the members are
9// not ordered.
10//
11// This type primarily exists to be the internal type of sets in cty, but
12// it is considered to be at the same level of abstraction as Go's built in
13// slice and map collection types, and so should make no cty-specific
14// assumptions.
15//
16// Set operations are not thread safe. It is the caller's responsibility to
17// provide mutex guarantees where necessary.
18//
19// Set operations are not optimized to minimize memory pressure. Mutating
20// a set will generally create garbage and so should perhaps be avoided in
21// tight loops where memory pressure is a concern.
22type Set struct {
23 vals map[int][]interface{}
24 rules Rules
25}
26
27// NewSet returns an empty set with the membership rules given.
28func NewSet(rules Rules) Set {
29 return Set{
30 vals: map[int][]interface{}{},
31 rules: rules,
32 }
33}
34
35func NewSetFromSlice(rules Rules, vals []interface{}) Set {
36 s := NewSet(rules)
37 for _, v := range vals {
38 s.Add(v)
39 }
40 return s
41}
42
43func sameRules(s1 Set, s2 Set) bool {
44 return s1.rules == s2.rules
45}
46
47func mustHaveSameRules(s1 Set, s2 Set) {
48 if !sameRules(s1, s2) {
49 panic(fmt.Errorf("incompatible set rules: %#v, %#v", s1.rules, s2.rules))
50 }
51}
52
53// HasRules returns true if and only if the receiving set has the given rules
54// instance as its rules.
55func (s Set) HasRules(rules Rules) bool {
56 return s.rules == rules
57}
58
59// Rules returns the receiving set's rules instance.
60func (s Set) Rules() Rules {
61 return s.rules
62}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set_helper.go b/vendor/github.com/zclconf/go-cty/cty/set_helper.go
new file mode 100644
index 0000000..a88ddaf
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set_helper.go
@@ -0,0 +1,126 @@
1package cty
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty/set"
7)
8
9// ValueSet is to cty.Set what []cty.Value is to cty.List and
10// map[string]cty.Value is to cty.Map. It's provided to allow callers a
11// convenient interface for manipulating sets before wrapping them in cty.Set
12// values using cty.SetValFromValueSet.
13//
14// Unlike value slices and value maps, ValueSet instances have a single
15// homogenous element type because that is a requirement of the underlying
16// set implementation, which uses the element type to select a suitable
17// hashing function.
18//
19// Set mutations are not concurrency-safe.
20type ValueSet struct {
21 // ValueSet is just a thin wrapper around a set.Set with our value-oriented
22 // "rules" applied. We do this so that the caller can work in terms of
23 // cty.Value objects even though the set internals use the raw values.
24 s set.Set
25}
26
27// NewValueSet creates and returns a new ValueSet with the given element type.
28func NewValueSet(ety Type) ValueSet {
29 return newValueSet(set.NewSet(setRules{Type: ety}))
30}
31
32func newValueSet(s set.Set) ValueSet {
33 return ValueSet{
34 s: s,
35 }
36}
37
38// ElementType returns the element type for the receiving ValueSet.
39func (s ValueSet) ElementType() Type {
40 return s.s.Rules().(setRules).Type
41}
42
43// Add inserts the given value into the receiving set.
44func (s ValueSet) Add(v Value) {
45 s.requireElementType(v)
46 s.s.Add(v.v)
47}
48
49// Remove deletes the given value from the receiving set, if indeed it was
50// there in the first place. If the value is not present, this is a no-op.
51func (s ValueSet) Remove(v Value) {
52 s.requireElementType(v)
53 s.s.Remove(v.v)
54}
55
56// Has returns true if the given value is in the receiving set, or false if
57// it is not.
58func (s ValueSet) Has(v Value) bool {
59 s.requireElementType(v)
60 return s.s.Has(v.v)
61}
62
63// Copy performs a shallow copy of the receiving set, returning a new set
64// with the same rules and elements.
65func (s ValueSet) Copy() ValueSet {
66 return newValueSet(s.s.Copy())
67}
68
69// Length returns the number of values in the set.
70func (s ValueSet) Length() int {
71 return s.s.Length()
72}
73
74// Values returns a slice of all of the values in the set in no particular
75// order.
76func (s ValueSet) Values() []Value {
77 l := s.s.Length()
78 if l == 0 {
79 return nil
80 }
81 ret := make([]Value, 0, l)
82 ety := s.ElementType()
83 for it := s.s.Iterator(); it.Next(); {
84 ret = append(ret, Value{
85 ty: ety,
86 v: it.Value(),
87 })
88 }
89 return ret
90}
91
92// Union returns a new set that contains all of the members of both the
93// receiving set and the given set. Both sets must have the same element type,
94// or else this function will panic.
95func (s ValueSet) Union(other ValueSet) ValueSet {
96 return newValueSet(s.s.Union(other.s))
97}
98
99// Intersection returns a new set that contains the values that both the
100// receiver and given sets have in common. Both sets must have the same element
101// type, or else this function will panic.
102func (s ValueSet) Intersection(other ValueSet) ValueSet {
103 return newValueSet(s.s.Intersection(other.s))
104}
105
106// Subtract returns a new set that contains all of the values from the receiver
107// that are not also in the given set. Both sets must have the same element
108// type, or else this function will panic.
109func (s ValueSet) Subtract(other ValueSet) ValueSet {
110 return newValueSet(s.s.Subtract(other.s))
111}
112
113// SymmetricDifference returns a new set that contains all of the values from
114// both the receiver and given sets, except those that both sets have in
115// common. Both sets must have the same element type, or else this function
116// will panic.
117func (s ValueSet) SymmetricDifference(other ValueSet) ValueSet {
118 return newValueSet(s.s.SymmetricDifference(other.s))
119}
120
121// requireElementType panics if the given value is not of the set's element type.
122func (s ValueSet) requireElementType(v Value) {
123 if !v.Type().Equals(s.ElementType()) {
124 panic(fmt.Errorf("attempt to use %#v value with set of %#v", v.Type(), s.ElementType()))
125 }
126}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set_internals.go b/vendor/github.com/zclconf/go-cty/cty/set_internals.go
new file mode 100644
index 0000000..ce738db
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set_internals.go
@@ -0,0 +1,146 @@
1package cty
2
3import (
4 "bytes"
5 "fmt"
6 "hash/crc32"
7 "math/big"
8 "sort"
9)
10
11// setRules provides a Rules implementation for the ./set package that
12// respects the equality rules for cty values of the given type.
13//
14// This implementation expects that values added to the set will be
15// valid internal values for the given Type, which is to say that wrapping
16// the given value in a Value struct along with the ruleset's type should
17// produce a valid, working Value.
18type setRules struct {
19 Type Type
20}
21
22func (r setRules) Hash(v interface{}) int {
23 hashBytes := makeSetHashBytes(Value{
24 ty: r.Type,
25 v: v,
26 })
27 return int(crc32.ChecksumIEEE(hashBytes))
28}
29
30func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool {
31 v1v := Value{
32 ty: r.Type,
33 v: v1,
34 }
35 v2v := Value{
36 ty: r.Type,
37 v: v2,
38 }
39
40 eqv := v1v.Equals(v2v)
41
42 // By comparing the result to true we ensure that an Unknown result,
43 // which will result if either value is unknown, will be considered
44 // as non-equivalent. Two unknown values are not equivalent for the
45 // sake of set membership.
46 return eqv.v == true
47}
48
49func makeSetHashBytes(val Value) []byte {
50 var buf bytes.Buffer
51 appendSetHashBytes(val, &buf)
52 return buf.Bytes()
53}
54
55func appendSetHashBytes(val Value, buf *bytes.Buffer) {
56 // Exactly what bytes we generate here don't matter as long as the following
57 // constraints hold:
58 // - Unknown and null values all generate distinct strings from
59 // each other and from any normal value of the given type.
60 // - The delimiter used to separate items in a compound structure can
61 // never appear literally in any of its elements.
62 // Since we don't support hetrogenous lists we don't need to worry about
63 // collisions between values of different types, apart from
64 // PseudoTypeDynamic.
65 // If in practice we *do* get a collision then it's not a big deal because
66 // the Equivalent function will still distinguish values, but set
67 // performance will be best if we are able to produce a distinct string
68 // for each distinct value, unknown values notwithstanding.
69 if !val.IsKnown() {
70 buf.WriteRune('?')
71 return
72 }
73 if val.IsNull() {
74 buf.WriteRune('~')
75 return
76 }
77
78 switch val.ty {
79 case Number:
80 buf.WriteString(val.v.(*big.Float).String())
81 return
82 case Bool:
83 if val.v.(bool) {
84 buf.WriteRune('T')
85 } else {
86 buf.WriteRune('F')
87 }
88 return
89 case String:
90 buf.WriteString(fmt.Sprintf("%q", val.v.(string)))
91 return
92 }
93
94 if val.ty.IsMapType() {
95 buf.WriteRune('{')
96 val.ForEachElement(func(keyVal, elementVal Value) bool {
97 appendSetHashBytes(keyVal, buf)
98 buf.WriteRune(':')
99 appendSetHashBytes(elementVal, buf)
100 buf.WriteRune(';')
101 return false
102 })
103 buf.WriteRune('}')
104 return
105 }
106
107 if val.ty.IsListType() || val.ty.IsSetType() {
108 buf.WriteRune('[')
109 val.ForEachElement(func(keyVal, elementVal Value) bool {
110 appendSetHashBytes(elementVal, buf)
111 buf.WriteRune(';')
112 return false
113 })
114 buf.WriteRune(']')
115 return
116 }
117
118 if val.ty.IsObjectType() {
119 buf.WriteRune('<')
120 attrNames := make([]string, 0, len(val.ty.AttributeTypes()))
121 for attrName := range val.ty.AttributeTypes() {
122 attrNames = append(attrNames, attrName)
123 }
124 sort.Strings(attrNames)
125 for _, attrName := range attrNames {
126 appendSetHashBytes(val.GetAttr(attrName), buf)
127 buf.WriteRune(';')
128 }
129 buf.WriteRune('>')
130 return
131 }
132
133 if val.ty.IsTupleType() {
134 buf.WriteRune('<')
135 val.ForEachElement(func(keyVal, elementVal Value) bool {
136 appendSetHashBytes(elementVal, buf)
137 buf.WriteRune(';')
138 return false
139 })
140 buf.WriteRune('>')
141 return
142 }
143
144 // should never get down here
145 panic("unsupported type in set hash")
146}
diff --git a/vendor/github.com/zclconf/go-cty/cty/set_type.go b/vendor/github.com/zclconf/go-cty/cty/set_type.go
new file mode 100644
index 0000000..952a2d2
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/set_type.go
@@ -0,0 +1,66 @@
1package cty
2
3import (
4 "fmt"
5)
6
7type typeSet struct {
8 typeImplSigil
9 ElementTypeT Type
10}
11
12// Set creates a set type with the given element Type.
13//
14// Set types are CollectionType implementations.
15func Set(elem Type) Type {
16 return Type{
17 typeSet{
18 ElementTypeT: elem,
19 },
20 }
21}
22
23// Equals returns true if the other Type is a set whose element type is
24// equal to that of the receiver.
25func (t typeSet) Equals(other Type) bool {
26 ot, isSet := other.typeImpl.(typeSet)
27 if !isSet {
28 return false
29 }
30
31 return t.ElementTypeT.Equals(ot.ElementTypeT)
32}
33
34func (t typeSet) FriendlyName() string {
35 return "set of " + t.ElementTypeT.FriendlyName()
36}
37
38func (t typeSet) ElementType() Type {
39 return t.ElementTypeT
40}
41
42func (t typeSet) GoString() string {
43 return fmt.Sprintf("cty.Set(%#v)", t.ElementTypeT)
44}
45
46// IsSetType returns true if the given type is a list type, regardless of its
47// element type.
48func (t Type) IsSetType() bool {
49 _, ok := t.typeImpl.(typeSet)
50 return ok
51}
52
53// SetElementType is a convenience method that checks if the given type is
54// a set type, returning a pointer to its element type if so and nil
55// otherwise. This is intended to allow convenient conditional branches,
56// like so:
57//
58// if et := t.SetElementType(); et != nil {
59// // Do something with *et
60// }
61func (t Type) SetElementType() *Type {
62 if lt, ok := t.typeImpl.(typeSet); ok {
63 return &lt.ElementTypeT
64 }
65 return nil
66}
diff --git a/vendor/github.com/zclconf/go-cty/cty/tuple_type.go b/vendor/github.com/zclconf/go-cty/cty/tuple_type.go
new file mode 100644
index 0000000..b98349e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/tuple_type.go
@@ -0,0 +1,121 @@
1package cty
2
3import (
4 "fmt"
5)
6
7type typeTuple struct {
8 typeImplSigil
9 ElemTypes []Type
10}
11
12// Tuple creates a tuple type with the given element types.
13//
14// After a slice is passed to this function the caller must no longer access
15// the underlying array, since ownership is transferred to this library.
16func Tuple(elemTypes []Type) Type {
17 return Type{
18 typeTuple{
19 ElemTypes: elemTypes,
20 },
21 }
22}
23
24func (t typeTuple) Equals(other Type) bool {
25 if ot, ok := other.typeImpl.(typeTuple); ok {
26 if len(t.ElemTypes) != len(ot.ElemTypes) {
27 // Fast path: if we don't have the same number of elements
28 // then we can't possibly be equal.
29 return false
30 }
31
32 for i, ty := range t.ElemTypes {
33 oty := ot.ElemTypes[i]
34 if !ok {
35 return false
36 }
37 if !oty.Equals(ty) {
38 return false
39 }
40 }
41
42 return true
43 }
44 return false
45}
46
47func (t typeTuple) FriendlyName() string {
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
50 // probably want to make some extra effort to avoid ever printing out
51 // a tuple type FriendlyName in its entirety. For example, could
52 // produce an error message by diffing two object types and saying
53 // something like "Expected attribute foo to be string, but got number".
54 // TODO: Finish this
55 return "tuple"
56}
57
58func (t typeTuple) GoString() string {
59 if len(t.ElemTypes) == 0 {
60 return "cty.EmptyTuple"
61 }
62 return fmt.Sprintf("cty.Tuple(%#v)", t.ElemTypes)
63}
64
65// EmptyTuple is a shorthand for Tuple([]Type{}), to more easily talk about
66// the empty tuple type.
67var EmptyTuple Type
68
69// EmptyTupleVal is the only possible non-null, non-unknown value of type
70// EmptyTuple.
71var EmptyTupleVal Value
72
73func init() {
74 EmptyTuple = Tuple([]Type{})
75 EmptyTupleVal = Value{
76 ty: EmptyTuple,
77 v: []interface{}{},
78 }
79}
80
81// IsTupleType returns true if the given type is an object type, regardless
82// of its element type.
83func (t Type) IsTupleType() bool {
84 _, ok := t.typeImpl.(typeTuple)
85 return ok
86}
87
88// Length returns the number of elements of the receiving tuple type.
89// Will panic if the reciever isn't a tuple type; use IsTupleType to determine
90// whether this operation will succeed.
91func (t Type) Length() int {
92 if ot, ok := t.typeImpl.(typeTuple); ok {
93 return len(ot.ElemTypes)
94 }
95 panic("Length on non-tuple Type")
96}
97
98// TupleElementType returns the type of the element with the given index. Will
99// panic if the receiver is not a tuple type (use IsTupleType to confirm)
100// or if the index is out of range (use Length to confirm).
101func (t Type) TupleElementType(idx int) Type {
102 if ot, ok := t.typeImpl.(typeTuple); ok {
103 return ot.ElemTypes[idx]
104 }
105 panic("TupleElementType on non-tuple Type")
106}
107
108// TupleElementTypes returns a slice of the recieving tuple type's element
109// types. Will panic if the receiver is not a tuple type (use IsTupleType
110// to confirm).
111//
112// The returned slice is part of the internal state of the type, and is provided
113// for read access only. It is forbidden for any caller to modify the
114// underlying array. For many purposes the element-related methods of Value
115// are more appropriate and more convenient to use.
116func (t Type) TupleElementTypes() []Type {
117 if ot, ok := t.typeImpl.(typeTuple); ok {
118 return ot.ElemTypes
119 }
120 panic("TupleElementTypes on non-tuple Type")
121}
diff --git a/vendor/github.com/zclconf/go-cty/cty/type.go b/vendor/github.com/zclconf/go-cty/cty/type.go
new file mode 100644
index 0000000..ae5f1c8
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/type.go
@@ -0,0 +1,95 @@
1package cty
2
3// Type represents value types within the type system.
4//
5// This is a closed interface type, meaning that only the concrete
6// implementations provided within this package are considered valid.
7type Type struct {
8 typeImpl
9}
10
11type typeImpl interface {
12 // isTypeImpl is a do-nothing method that exists only to express
13 // that a type is an implementation of typeImpl.
14 isTypeImpl() typeImplSigil
15
16 // Equals returns true if the other given Type exactly equals the
17 // receiver Type.
18 Equals(other Type) bool
19
20 // FriendlyName returns a human-friendly *English* name for the given
21 // type.
22 FriendlyName() string
23
24 // GoString implements the GoStringer interface from package fmt.
25 GoString() string
26}
27
28// Base implementation of Type to embed into concrete implementations
29// to signal that they are implementations of Type.
30type typeImplSigil struct{}
31
32func (t typeImplSigil) isTypeImpl() typeImplSigil {
33 return typeImplSigil{}
34}
35
36// Equals returns true if the other given Type exactly equals the receiver
37// type.
38func (t Type) Equals(other Type) bool {
39 return t.typeImpl.Equals(other)
40}
41
42// FriendlyName returns a human-friendly *English* name for the given type.
43func (t Type) FriendlyName() string {
44 return t.typeImpl.FriendlyName()
45}
46
47// GoString returns a string approximating how the receiver type would be
48// expressed in Go source code.
49func (t Type) GoString() string {
50 if t.typeImpl == nil {
51 return "cty.NilType"
52 }
53
54 return t.typeImpl.GoString()
55}
56
57// NilType is an invalid type used when a function is returning an error
58// and has no useful type to return. It should not be used and any methods
59// called on it will panic.
60var NilType = Type{}
61
62// HasDynamicTypes returns true either if the receiver is itself
63// DynamicPseudoType or if it is a compound type whose descendent elements
64// are DynamicPseudoType.
65func (t Type) HasDynamicTypes() bool {
66 switch {
67 case t == DynamicPseudoType:
68 return true
69 case t.IsPrimitiveType():
70 return false
71 case t.IsCollectionType():
72 return false
73 case t.IsObjectType():
74 attrTypes := t.AttributeTypes()
75 for _, at := range attrTypes {
76 if at.HasDynamicTypes() {
77 return true
78 }
79 }
80 return false
81 case t.IsTupleType():
82 elemTypes := t.TupleElementTypes()
83 for _, et := range elemTypes {
84 if et.HasDynamicTypes() {
85 return true
86 }
87 }
88 return false
89 case t.IsCapsuleType():
90 return false
91 default:
92 // Should never happen, since above should be exhaustive
93 panic("HasDynamicTypes does not support the given type")
94 }
95}
diff --git a/vendor/github.com/zclconf/go-cty/cty/type_conform.go b/vendor/github.com/zclconf/go-cty/cty/type_conform.go
new file mode 100644
index 0000000..b417dc7
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/type_conform.go
@@ -0,0 +1,142 @@
1package cty
2
3// TestConformance recursively walks the receiver and the given other type and
4// returns nil if the receiver *conforms* to the given type.
5//
6// Type conformance is similar to type equality but has one crucial difference:
7// PseudoTypeDynamic can be used within the given type to represent that
8// *any* type is allowed.
9//
10// If any non-conformities are found, the returned slice will be non-nil and
11// contain at least one error value. It will be nil if the type is entirely
12// conformant.
13//
14// Note that the special behavior of PseudoTypeDynamic is the *only* exception
15// to normal type equality. Calling applications may wish to apply their own
16// automatic conversion logic to the given data structure to create a more
17// liberal notion of conformance to a type.
18//
19// Returned errors are usually (but not always) PathError instances that
20// indicate where in the structure the error was found. If a returned error
21// is of that type then the error message is written for (English-speaking)
22// end-users working within the cty type system, not mentioning any Go-oriented
23// implementation details.
24func (t Type) TestConformance(other Type) []error {
25 path := make(Path, 0)
26 var errs []error
27 testConformance(t, other, path, &errs)
28 return errs
29}
30
31func testConformance(given Type, want Type, path Path, errs *[]error) {
32 if want.Equals(DynamicPseudoType) {
33 // anything goes!
34 return
35 }
36
37 if given.Equals(want) {
38 // Any equal types are always conformant
39 return
40 }
41
42 // The remainder of this function is concerned with detecting
43 // and reporting the specific non-conformance, since we wouldn't
44 // have got here if the types were not divergent.
45 // We treat compound structures as special so that we can report
46 // specifically what is non-conforming, rather than simply returning
47 // the entire type names and letting the user puzzle it out.
48
49 if given.IsObjectType() && want.IsObjectType() {
50 givenAttrs := given.AttributeTypes()
51 wantAttrs := want.AttributeTypes()
52
53 if len(givenAttrs) != len(wantAttrs) {
54 // Something is missing from one of them.
55 for k := range givenAttrs {
56 if _, exists := wantAttrs[k]; !exists {
57 *errs = append(
58 *errs,
59 errorf(path, "unsupported attribute %q", k),
60 )
61 }
62 }
63 for k := range wantAttrs {
64 if _, exists := givenAttrs[k]; !exists {
65 *errs = append(
66 *errs,
67 errorf(path, "missing required attribute %q", k),
68 )
69 }
70 }
71 }
72
73 path = append(path, nil)
74 pathIdx := len(path) - 1
75
76 for k, wantAttrType := range wantAttrs {
77 if givenAttrType, exists := givenAttrs[k]; exists {
78 path[pathIdx] = GetAttrStep{Name: k}
79 testConformance(givenAttrType, wantAttrType, path, errs)
80 }
81 }
82
83 path = path[0:pathIdx]
84
85 return
86 }
87
88 if given.IsTupleType() && want.IsTupleType() {
89 givenElems := given.TupleElementTypes()
90 wantElems := want.TupleElementTypes()
91
92 if len(givenElems) != len(wantElems) {
93 *errs = append(
94 *errs,
95 errorf(path, "%d elements are required, but got %d", len(wantElems), len(givenElems)),
96 )
97 return
98 }
99
100 path = append(path, nil)
101 pathIdx := len(path) - 1
102
103 for i, wantElemType := range wantElems {
104 givenElemType := givenElems[i]
105 path[pathIdx] = IndexStep{Key: NumberIntVal(int64(i))}
106 testConformance(givenElemType, wantElemType, path, errs)
107 }
108
109 path = path[0:pathIdx]
110
111 return
112 }
113
114 if given.IsListType() && want.IsListType() {
115 path = append(path, IndexStep{Key: UnknownVal(Number)})
116 pathIdx := len(path) - 1
117 testConformance(given.ElementType(), want.ElementType(), path, errs)
118 path = path[0:pathIdx]
119 return
120 }
121
122 if given.IsMapType() && want.IsMapType() {
123 path = append(path, IndexStep{Key: UnknownVal(String)})
124 pathIdx := len(path) - 1
125 testConformance(given.ElementType(), want.ElementType(), path, errs)
126 path = path[0:pathIdx]
127 return
128 }
129
130 if given.IsSetType() && want.IsSetType() {
131 path = append(path, IndexStep{Key: UnknownVal(given.ElementType())})
132 pathIdx := len(path) - 1
133 testConformance(given.ElementType(), want.ElementType(), path, errs)
134 path = path[0:pathIdx]
135 return
136 }
137
138 *errs = append(
139 *errs,
140 errorf(path, "%s required, but received %s", want.FriendlyName(), given.FriendlyName()),
141 )
142}
diff --git a/vendor/github.com/zclconf/go-cty/cty/types_to_register.go b/vendor/github.com/zclconf/go-cty/cty/types_to_register.go
new file mode 100644
index 0000000..e1e220a
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/types_to_register.go
@@ -0,0 +1,57 @@
1package cty
2
3import (
4 "encoding/gob"
5 "fmt"
6 "math/big"
7 "strings"
8
9 "github.com/zclconf/go-cty/cty/set"
10)
11
12// InternalTypesToRegister is a slice of values that covers all of the
13// internal types used in the representation of cty.Type and cty.Value
14// across all cty Types.
15//
16// This is intended to be used to register these types with encoding
17// packages that require registration of types used in interfaces, such as
18// encoding/gob, thus allowing cty types and values to be included in streams
19// created from those packages. However, registering with gob is not necessary
20// since that is done automatically as a side-effect of importing this package.
21//
22// Callers should not do anything with the values here except pass them on
23// verbatim to a registration function.
24//
25// If the calling application uses Capsule types that wrap local structs either
26// directly or indirectly, these structs may also need to be registered in
27// order to support encoding and decoding of values of these types. That is the
28// responsibility of the calling application.
29var InternalTypesToRegister []interface{}
30
31func init() {
32 InternalTypesToRegister = []interface{}{
33 primitiveType{},
34 typeList{},
35 typeMap{},
36 typeObject{},
37 typeSet{},
38 setRules{},
39 set.Set{},
40 typeTuple{},
41 big.Float{},
42 capsuleType{},
43 []interface{}(nil),
44 map[string]interface{}(nil),
45 }
46
47 // Register these with gob here, rather than in gob.go, to ensure
48 // that this will always happen after we build the above.
49 for _, tv := range InternalTypesToRegister {
50 typeName := fmt.Sprintf("%T", tv)
51 if strings.HasPrefix(typeName, "cty.") {
52 gob.RegisterName(fmt.Sprintf("github.com/zclconf/go-cty/%s", typeName), tv)
53 } else {
54 gob.Register(tv)
55 }
56 }
57}
diff --git a/vendor/github.com/zclconf/go-cty/cty/unknown.go b/vendor/github.com/zclconf/go-cty/cty/unknown.go
new file mode 100644
index 0000000..9f6fce9
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/unknown.go
@@ -0,0 +1,79 @@
1package cty
2
3// unknownType is the placeholder type used for the sigil value representing
4// "Unknown", to make it unambigiously distinct from any other possible value.
5type unknownType struct {
6}
7
8// Unknown is a special value that can be
9var unknown interface{} = &unknownType{}
10
11// UnknownVal returns an Value that represents an unknown value of the given
12// type. Unknown values can be used to represent a value that is
13// not yet known. Its meaning is undefined in cty, but it could be used by
14// an calling application to allow partial evaluation.
15//
16// Unknown values of any type can be created of any type. All operations on
17// Unknown values themselves return Unknown.
18func UnknownVal(t Type) Value {
19 return Value{
20 ty: t,
21 v: unknown,
22 }
23}
24
25func (t unknownType) GoString() string {
26 // This is the stringification of our internal unknown marker. The
27 // stringification of the public representation of unknowns is in
28 // Value.GoString.
29 return "cty.unknown"
30}
31
32type pseudoTypeDynamic struct {
33 typeImplSigil
34}
35
36// DynamicPseudoType represents the dynamic pseudo-type.
37//
38// This type can represent situations where a type is not yet known. Its
39// meaning is undefined in cty, but it could be used by a calling
40// application to allow expression type checking with some types not yet known.
41// For example, the application might optimistically permit any operation on
42// values of this type in type checking, allowing a partial type-check result,
43// and then repeat the check when more information is known to get the
44// final, concrete type.
45//
46// It is a pseudo-type because it is used only as a sigil to the calling
47// application. "Unknown" is the only valid value of this pseudo-type, so
48// operations on values of this type will always short-circuit as per
49// the rules for that special value.
50var DynamicPseudoType Type
51
52func (t pseudoTypeDynamic) Equals(other Type) bool {
53 _, ok := other.typeImpl.(pseudoTypeDynamic)
54 return ok
55}
56
57func (t pseudoTypeDynamic) FriendlyName() string {
58 return "dynamic"
59}
60
61func (t pseudoTypeDynamic) GoString() string {
62 return "cty.DynamicPseudoType"
63}
64
65// DynamicVal is the only valid value of the pseudo-type dynamic.
66// This value can be used as a placeholder where a value or expression's
67// type and value are both unknown, thus allowing partial evaluation. See
68// the docs for DynamicPseudoType for more information.
69var DynamicVal Value
70
71func init() {
72 DynamicPseudoType = Type{
73 pseudoTypeDynamic{},
74 }
75 DynamicVal = Value{
76 ty: DynamicPseudoType,
77 v: unknown,
78 }
79}
diff --git a/vendor/github.com/zclconf/go-cty/cty/value.go b/vendor/github.com/zclconf/go-cty/cty/value.go
new file mode 100644
index 0000000..80cb8f7
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/value.go
@@ -0,0 +1,98 @@
1package cty
2
3// Value represents a value of a particular type, and is the interface by
4// which operations are executed on typed values.
5//
6// Value has two different classes of method. Operation methods stay entirely
7// within the type system (methods accept and return Value instances) and
8// are intended for use in implementing a language in terms of cty, while
9// integration methods either enter or leave the type system, working with
10// native Go values. Operation methods are guaranteed to support all of the
11// expected short-circuit behavior for unknown and dynamic values, while
12// integration methods may not.
13//
14// The philosophy for the operations API is that it's the caller's
15// responsibility to ensure that the given types and values satisfy the
16// specified invariants during a separate type check, so that the caller is
17// able to return errors to its user from the application's own perspective.
18//
19// Consequently the design of these methods assumes such checks have already
20// been done and panics if any invariants turn out not to be satisfied. These
21// panic errors are not intended to be handled, but rather indicate a bug in
22// the calling application that should be fixed with more checks prior to
23// executing operations.
24//
25// A related consequence of this philosophy is that no automatic type
26// conversions are done. If a method specifies that its argument must be
27// number then it's the caller's responsibility to do that conversion before
28// the call, thus allowing the application to have more constrained conversion
29// rules than are offered by the built-in converter where necessary.
30type Value struct {
31 ty Type
32 v interface{}
33}
34
35// Type returns the type of the value.
36func (val Value) Type() Type {
37 return val.ty
38}
39
40// IsKnown returns true if the value is known. That is, if it is not
41// the result of the unknown value constructor Unknown(...), and is not
42// the result of an operation on another unknown value.
43//
44// Unknown values are only produced either directly or as a result of
45// operating on other unknown values, and so an application that never
46// introduces Unknown values can be guaranteed to never receive any either.
47func (val Value) IsKnown() bool {
48 return val.v != unknown
49}
50
51// IsNull returns true if the value is null. Values of any type can be
52// null, but any operations on a null value will panic. No operation ever
53// produces null, so an application that never introduces Null values can
54// be guaranteed to never receive any either.
55func (val Value) IsNull() bool {
56 return val.v == nil
57}
58
59// NilVal is an invalid Value that can be used as a placeholder when returning
60// with an error from a function that returns (Value, error).
61//
62// NilVal is *not* a valid error and so no operations may be performed on it.
63// Any attempt to use it will result in a panic.
64//
65// This should not be confused with the idea of a Null value, as returned by
66// NullVal. NilVal is a nil within the *Go* type system, and is invalid in
67// the cty type system. Null values *do* exist in the cty type system.
68var NilVal = Value{
69 ty: Type{typeImpl: nil},
70 v: nil,
71}
72
73// IsWhollyKnown is an extension of IsKnown that also recursively checks
74// inside collections and structures to see if there are any nested unknown
75// values.
76func (val Value) IsWhollyKnown() bool {
77 if !val.IsKnown() {
78 return false
79 }
80
81 if val.IsNull() {
82 // Can't recurse into a null, so we're done
83 return true
84 }
85
86 switch {
87 case val.CanIterateElements():
88 for it := val.ElementIterator(); it.Next(); {
89 _, ev := it.Element()
90 if !ev.IsWhollyKnown() {
91 return false
92 }
93 }
94 return true
95 default:
96 return true
97 }
98}
diff --git a/vendor/github.com/zclconf/go-cty/cty/value_init.go b/vendor/github.com/zclconf/go-cty/cty/value_init.go
new file mode 100644
index 0000000..495a83e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/value_init.go
@@ -0,0 +1,276 @@
1package cty
2
3import (
4 "fmt"
5 "math/big"
6 "reflect"
7
8 "golang.org/x/text/unicode/norm"
9
10 "github.com/zclconf/go-cty/cty/set"
11)
12
13// BoolVal returns a Value of type Number whose internal value is the given
14// bool.
15func BoolVal(v bool) Value {
16 return Value{
17 ty: Bool,
18 v: v,
19 }
20}
21
22// NumberVal returns a Value of type Number whose internal value is the given
23// big.Float. The returned value becomes the owner of the big.Float object,
24// and so it's forbidden for the caller to mutate the object after it's
25// wrapped in this way.
26func NumberVal(v *big.Float) Value {
27 return Value{
28 ty: Number,
29 v: v,
30 }
31}
32
33// NumberIntVal returns a Value of type Number whose internal value is equal
34// to the given integer.
35func NumberIntVal(v int64) Value {
36 return NumberVal(new(big.Float).SetInt64(v))
37}
38
39// NumberUIntVal returns a Value of type Number whose internal value is equal
40// to the given unsigned integer.
41func NumberUIntVal(v uint64) Value {
42 return NumberVal(new(big.Float).SetUint64(v))
43}
44
45// NumberFloatVal returns a Value of type Number whose internal value is
46// equal to the given float.
47func NumberFloatVal(v float64) Value {
48 return NumberVal(new(big.Float).SetFloat64(v))
49}
50
51// StringVal returns a Value of type String whose internal value is the
52// given string.
53//
54// Strings must be UTF-8 encoded sequences of valid unicode codepoints, and
55// they are NFC-normalized on entry into the world of cty values.
56//
57// If the given string is not valid UTF-8 then behavior of string operations
58// is undefined.
59func StringVal(v string) Value {
60 return Value{
61 ty: String,
62 v: NormalizeString(v),
63 }
64}
65
66// NormalizeString applies the same normalization that cty applies when
67// constructing string values.
68//
69// A return value from this function can be meaningfully compared byte-for-byte
70// with a Value.AsString result.
71func NormalizeString(s string) string {
72 return norm.NFC.String(s)
73}
74
75// ObjectVal returns a Value of an object type whose structure is defined
76// by the key names and value types in the given map.
77func ObjectVal(attrs map[string]Value) Value {
78 attrTypes := make(map[string]Type, len(attrs))
79 attrVals := make(map[string]interface{}, len(attrs))
80
81 for attr, val := range attrs {
82 attr = NormalizeString(attr)
83 attrTypes[attr] = val.ty
84 attrVals[attr] = val.v
85 }
86
87 return Value{
88 ty: Object(attrTypes),
89 v: attrVals,
90 }
91}
92
93// TupleVal returns a Value of a tuple type whose element types are
94// defined by the value types in the given slice.
95func TupleVal(elems []Value) Value {
96 elemTypes := make([]Type, len(elems))
97 elemVals := make([]interface{}, len(elems))
98
99 for i, val := range elems {
100 elemTypes[i] = val.ty
101 elemVals[i] = val.v
102 }
103
104 return Value{
105 ty: Tuple(elemTypes),
106 v: elemVals,
107 }
108}
109
110// ListVal returns a Value of list type whose element type is defined by
111// the types of the given values, which must be homogenous.
112//
113// If the types are not all consistent (aside from elements that are of the
114// dynamic pseudo-type) then this function will panic. It will panic also
115// if the given list is empty, since then the element type cannot be inferred.
116// (See also ListValEmpty.)
117func ListVal(vals []Value) Value {
118 if len(vals) == 0 {
119 panic("must not call ListVal with empty slice")
120 }
121 elementType := DynamicPseudoType
122 rawList := make([]interface{}, len(vals))
123
124 for i, val := range vals {
125 if elementType == DynamicPseudoType {
126 elementType = val.ty
127 } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
128 panic(fmt.Errorf(
129 "inconsistent list element types (%#v then %#v)",
130 elementType, val.ty,
131 ))
132 }
133
134 rawList[i] = val.v
135 }
136
137 return Value{
138 ty: List(elementType),
139 v: rawList,
140 }
141}
142
143// ListValEmpty returns an empty list of the given element type.
144func ListValEmpty(element Type) Value {
145 return Value{
146 ty: List(element),
147 v: []interface{}{},
148 }
149}
150
151// MapVal returns a Value of a map type whose element type is defined by
152// the types of the given values, which must be homogenous.
153//
154// If the types are not all consistent (aside from elements that are of the
155// dynamic pseudo-type) then this function will panic. It will panic also
156// if the given map is empty, since then the element type cannot be inferred.
157// (See also MapValEmpty.)
158func MapVal(vals map[string]Value) Value {
159 if len(vals) == 0 {
160 panic("must not call MapVal with empty map")
161 }
162 elementType := DynamicPseudoType
163 rawMap := make(map[string]interface{}, len(vals))
164
165 for key, val := range vals {
166 if elementType == DynamicPseudoType {
167 elementType = val.ty
168 } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
169 panic(fmt.Errorf(
170 "inconsistent map element types (%#v then %#v)",
171 elementType, val.ty,
172 ))
173 }
174
175 rawMap[NormalizeString(key)] = val.v
176 }
177
178 return Value{
179 ty: Map(elementType),
180 v: rawMap,
181 }
182}
183
184// MapValEmpty returns an empty map of the given element type.
185func MapValEmpty(element Type) Value {
186 return Value{
187 ty: Map(element),
188 v: map[string]interface{}{},
189 }
190}
191
192// SetVal returns a Value of set type whose element type is defined by
193// the types of the given values, which must be homogenous.
194//
195// If the types are not all consistent (aside from elements that are of the
196// dynamic pseudo-type) then this function will panic. It will panic also
197// if the given list is empty, since then the element type cannot be inferred.
198// (See also SetValEmpty.)
199func SetVal(vals []Value) Value {
200 if len(vals) == 0 {
201 panic("must not call SetVal with empty slice")
202 }
203 elementType := DynamicPseudoType
204 rawList := make([]interface{}, len(vals))
205
206 for i, val := range vals {
207 if elementType == DynamicPseudoType {
208 elementType = val.ty
209 } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
210 panic(fmt.Errorf(
211 "inconsistent set element types (%#v then %#v)",
212 elementType, val.ty,
213 ))
214 }
215
216 rawList[i] = val.v
217 }
218
219 rawVal := set.NewSetFromSlice(setRules{elementType}, rawList)
220
221 return Value{
222 ty: Set(elementType),
223 v: rawVal,
224 }
225}
226
227// SetValFromValueSet returns a Value of set type based on an already-constructed
228// ValueSet.
229//
230// The element type of the returned value is the element type of the given
231// set.
232func SetValFromValueSet(s ValueSet) Value {
233 ety := s.ElementType()
234 rawVal := s.s.Copy() // copy so caller can't mutate what we wrap
235
236 return Value{
237 ty: Set(ety),
238 v: rawVal,
239 }
240}
241
242// SetValEmpty returns an empty set of the given element type.
243func SetValEmpty(element Type) Value {
244 return Value{
245 ty: Set(element),
246 v: set.NewSet(setRules{element}),
247 }
248}
249
250// CapsuleVal creates a value of the given capsule type using the given
251// wrapVal, which must be a pointer to a value of the capsule type's native
252// type.
253//
254// This function will panic if the given type is not a capsule type, if
255// the given wrapVal is not compatible with the given capsule type, or if
256// wrapVal is not a pointer.
257func CapsuleVal(ty Type, wrapVal interface{}) Value {
258 if !ty.IsCapsuleType() {
259 panic("not a capsule type")
260 }
261
262 wv := reflect.ValueOf(wrapVal)
263 if wv.Kind() != reflect.Ptr {
264 panic("wrapVal is not a pointer")
265 }
266
267 it := ty.typeImpl.(*capsuleType).GoType
268 if !wv.Type().Elem().AssignableTo(it) {
269 panic("wrapVal target is not compatible with the given capsule type")
270 }
271
272 return Value{
273 ty: ty,
274 v: wrapVal,
275 }
276}
diff --git a/vendor/github.com/zclconf/go-cty/cty/value_ops.go b/vendor/github.com/zclconf/go-cty/cty/value_ops.go
new file mode 100644
index 0000000..967aa76
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/value_ops.go
@@ -0,0 +1,1071 @@
1package cty
2
3import (
4 "fmt"
5 "math/big"
6
7 "reflect"
8
9 "github.com/zclconf/go-cty/cty/set"
10)
11
12func (val Value) GoString() string {
13 if val == NilVal {
14 return "cty.NilVal"
15 }
16
17 if val.ty == DynamicPseudoType {
18 return "cty.DynamicVal"
19 }
20
21 if !val.IsKnown() {
22 return fmt.Sprintf("cty.UnknownVal(%#v)", val.ty)
23 }
24 if val.IsNull() {
25 return fmt.Sprintf("cty.NullVal(%#v)", val.ty)
26 }
27
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
30 // canonical internal representation of the given type.
31
32 switch val.ty {
33 case Bool:
34 if val.v.(bool) {
35 return "cty.True"
36 } else {
37 return "cty.False"
38 }
39 case Number:
40 fv := val.v.(*big.Float)
41 // We'll try to use NumberIntVal or NumberFloatVal if we can, since
42 // the fully-general initializer call is pretty ugly-looking.
43 if fv.IsInt() {
44 return fmt.Sprintf("cty.NumberIntVal(%#v)", fv)
45 }
46 if rfv, accuracy := fv.Float64(); accuracy == big.Exact {
47 return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv)
48 }
49 return fmt.Sprintf("cty.NumberVal(new(big.Float).Parse(\"%#v\", 10))", fv)
50 case String:
51 return fmt.Sprintf("cty.StringVal(%#v)", val.v)
52 }
53
54 switch {
55 case val.ty.IsSetType():
56 vals := val.v.(set.Set).Values()
57 if vals == nil || len(vals) == 0 {
58 return fmt.Sprintf("cty.SetValEmpty()")
59 } else {
60 return fmt.Sprintf("cty.SetVal(%#v)", vals)
61 }
62 case val.ty.IsCapsuleType():
63 return fmt.Sprintf("cty.CapsuleVal(%#v, %#v)", val.ty, val.v)
64 }
65
66 // Default exposes implementation details, so should actually cover
67 // all of the cases above for good caller UX.
68 return fmt.Sprintf("cty.Value{ty: %#v, v: %#v}", val.ty, val.v)
69}
70
71// Equals returns True if the receiver and the given other value have the
72// same type and are exactly equal in value.
73//
74// The usual short-circuit rules apply, so the result can be unknown or typed
75// as dynamic if either of the given values are. Use RawEquals to compare
76// if two values are equal *ignoring* the short-circuit rules.
77func (val Value) Equals(other Value) Value {
78 if val.ty.HasDynamicTypes() || other.ty.HasDynamicTypes() {
79 return UnknownVal(Bool)
80 }
81
82 if !val.ty.Equals(other.ty) {
83 return BoolVal(false)
84 }
85
86 if !(val.IsKnown() && other.IsKnown()) {
87 return UnknownVal(Bool)
88 }
89
90 if val.IsNull() || other.IsNull() {
91 if val.IsNull() && other.IsNull() {
92 return BoolVal(true)
93 }
94 return BoolVal(false)
95 }
96
97 ty := val.ty
98 result := false
99
100 switch {
101 case ty == Number:
102 result = val.v.(*big.Float).Cmp(other.v.(*big.Float)) == 0
103 case ty == Bool:
104 result = val.v.(bool) == other.v.(bool)
105 case ty == String:
106 // Simple equality is safe because we NFC-normalize strings as they
107 // enter our world from StringVal, and so we can assume strings are
108 // always in normal form.
109 result = val.v.(string) == other.v.(string)
110 case ty.IsObjectType():
111 oty := ty.typeImpl.(typeObject)
112 result = true
113 for attr, aty := range oty.AttrTypes {
114 lhs := Value{
115 ty: aty,
116 v: val.v.(map[string]interface{})[attr],
117 }
118 rhs := Value{
119 ty: aty,
120 v: other.v.(map[string]interface{})[attr],
121 }
122 eq := lhs.Equals(rhs)
123 if !eq.IsKnown() {
124 return UnknownVal(Bool)
125 }
126 if eq.False() {
127 result = false
128 break
129 }
130 }
131 case ty.IsTupleType():
132 tty := ty.typeImpl.(typeTuple)
133 result = true
134 for i, ety := range tty.ElemTypes {
135 lhs := Value{
136 ty: ety,
137 v: val.v.([]interface{})[i],
138 }
139 rhs := Value{
140 ty: ety,
141 v: other.v.([]interface{})[i],
142 }
143 eq := lhs.Equals(rhs)
144 if !eq.IsKnown() {
145 return UnknownVal(Bool)
146 }
147 if eq.False() {
148 result = false
149 break
150 }
151 }
152 case ty.IsListType():
153 ety := ty.typeImpl.(typeList).ElementTypeT
154 if len(val.v.([]interface{})) == len(other.v.([]interface{})) {
155 result = true
156 for i := range val.v.([]interface{}) {
157 lhs := Value{
158 ty: ety,
159 v: val.v.([]interface{})[i],
160 }
161 rhs := Value{
162 ty: ety,
163 v: other.v.([]interface{})[i],
164 }
165 eq := lhs.Equals(rhs)
166 if !eq.IsKnown() {
167 return UnknownVal(Bool)
168 }
169 if eq.False() {
170 result = false
171 break
172 }
173 }
174 }
175 case ty.IsSetType():
176 s1 := val.v.(set.Set)
177 s2 := other.v.(set.Set)
178 equal := true
179
180 // Note that by our definition of sets it's never possible for two
181 // sets that contain unknown values (directly or indicrectly) to
182 // ever be equal, even if they are otherwise identical.
183
184 // FIXME: iterating both lists and checking each item is not the
185 // ideal implementation here, but it works with the primitives we
186 // have in the set implementation. Perhaps the set implementation
187 // can provide its own equality test later.
188 s1.EachValue(func(v interface{}) {
189 if !s2.Has(v) {
190 equal = false
191 }
192 })
193 s2.EachValue(func(v interface{}) {
194 if !s1.Has(v) {
195 equal = false
196 }
197 })
198
199 result = equal
200 case ty.IsMapType():
201 ety := ty.typeImpl.(typeMap).ElementTypeT
202 if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) {
203 result = true
204 for k := range val.v.(map[string]interface{}) {
205 if _, ok := other.v.(map[string]interface{})[k]; !ok {
206 result = false
207 break
208 }
209 lhs := Value{
210 ty: ety,
211 v: val.v.(map[string]interface{})[k],
212 }
213 rhs := Value{
214 ty: ety,
215 v: other.v.(map[string]interface{})[k],
216 }
217 eq := lhs.Equals(rhs)
218 if !eq.IsKnown() {
219 return UnknownVal(Bool)
220 }
221 if eq.False() {
222 result = false
223 break
224 }
225 }
226 }
227 case ty.IsCapsuleType():
228 // A capsule type's encapsulated value is a pointer to a value of its
229 // native type, so we can just compare these to get the identity test
230 // we need.
231 return BoolVal(val.v == other.v)
232
233 default:
234 // should never happen
235 panic(fmt.Errorf("unsupported value type %#v in Equals", ty))
236 }
237
238 return BoolVal(result)
239}
240
241// NotEqual is a shorthand for Equals followed by Not.
242func (val Value) NotEqual(other Value) Value {
243 return val.Equals(other).Not()
244}
245
246// True returns true if the receiver is True, false if False, and panics if
247// the receiver is not of type Bool.
248//
249// This is a helper function to help write application logic that works with
250// values, rather than a first-class operation. It does not work with unknown
251// or null values. For more robust handling with unknown value
252// short-circuiting, use val.Equals(cty.True).
253func (val Value) True() bool {
254 if val.ty != Bool {
255 panic("not bool")
256 }
257 return val.Equals(True).v.(bool)
258}
259
260// False is the opposite of True.
261func (val Value) False() bool {
262 return !val.True()
263}
264
265// RawEquals returns true if and only if the two given values have the same
266// type and equal value, ignoring the usual short-circuit rules about
267// unknowns and dynamic types.
268//
269// This method is more appropriate for testing than for real use, since it
270// skips over usual semantics around unknowns but as a consequence allows
271// testing the result of another operation that is expected to return unknown.
272// It returns a primitive Go bool rather than a Value to remind us that it
273// is not a first-class value operation.
274func (val Value) RawEquals(other Value) bool {
275 if !val.ty.Equals(other.ty) {
276 return false
277 }
278 if (!val.IsKnown()) && (!other.IsKnown()) {
279 return true
280 }
281 if (val.IsKnown() && !other.IsKnown()) || (other.IsKnown() && !val.IsKnown()) {
282 return false
283 }
284 if val.IsNull() && other.IsNull() {
285 return true
286 }
287 if (val.IsNull() && !other.IsNull()) || (other.IsNull() && !val.IsNull()) {
288 return false
289 }
290 if val.ty == DynamicPseudoType && other.ty == DynamicPseudoType {
291 return true
292 }
293
294 ty := val.ty
295 switch {
296 case ty == Number || ty == Bool || ty == String || ty == DynamicPseudoType:
297 return val.Equals(other).True()
298 case ty.IsObjectType():
299 oty := ty.typeImpl.(typeObject)
300 for attr, aty := range oty.AttrTypes {
301 lhs := Value{
302 ty: aty,
303 v: val.v.(map[string]interface{})[attr],
304 }
305 rhs := Value{
306 ty: aty,
307 v: other.v.(map[string]interface{})[attr],
308 }
309 eq := lhs.RawEquals(rhs)
310 if !eq {
311 return false
312 }
313 }
314 return true
315 case ty.IsTupleType():
316 tty := ty.typeImpl.(typeTuple)
317 for i, ety := range tty.ElemTypes {
318 lhs := Value{
319 ty: ety,
320 v: val.v.([]interface{})[i],
321 }
322 rhs := Value{
323 ty: ety,
324 v: other.v.([]interface{})[i],
325 }
326 eq := lhs.RawEquals(rhs)
327 if !eq {
328 return false
329 }
330 }
331 return true
332 case ty.IsListType():
333 ety := ty.typeImpl.(typeList).ElementTypeT
334 if len(val.v.([]interface{})) == len(other.v.([]interface{})) {
335 for i := range val.v.([]interface{}) {
336 lhs := Value{
337 ty: ety,
338 v: val.v.([]interface{})[i],
339 }
340 rhs := Value{
341 ty: ety,
342 v: other.v.([]interface{})[i],
343 }
344 eq := lhs.RawEquals(rhs)
345 if !eq {
346 return false
347 }
348 }
349 return true
350 }
351 return false
352 case ty.IsSetType():
353 s1 := val.v.(set.Set)
354 s2 := other.v.(set.Set)
355
356 // Since we're intentionally ignoring our rule that two unknowns
357 // are never equal, we can cheat here.
358 // (This isn't 100% right since e.g. it will fail if the set contains
359 // numbers that are infinite, which DeepEqual can't compare properly.
360 // We're accepting that limitation for simplicity here, since this
361 // function is here primarily for testing.)
362 return reflect.DeepEqual(s1, s2)
363
364 case ty.IsMapType():
365 ety := ty.typeImpl.(typeMap).ElementTypeT
366 if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) {
367 for k := range val.v.(map[string]interface{}) {
368 if _, ok := other.v.(map[string]interface{})[k]; !ok {
369 return false
370 }
371 lhs := Value{
372 ty: ety,
373 v: val.v.(map[string]interface{})[k],
374 }
375 rhs := Value{
376 ty: ety,
377 v: other.v.(map[string]interface{})[k],
378 }
379 eq := lhs.RawEquals(rhs)
380 if !eq {
381 return false
382 }
383 }
384 return true
385 }
386 return false
387 case ty.IsCapsuleType():
388 // A capsule type's encapsulated value is a pointer to a value of its
389 // native type, so we can just compare these to get the identity test
390 // we need.
391 return val.v == other.v
392
393 default:
394 // should never happen
395 panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty))
396 }
397}
398
399// Add returns the sum of the receiver and the given other value. Both values
400// must be numbers; this method will panic if not.
401func (val Value) Add(other Value) Value {
402 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
403 shortCircuit = forceShortCircuitType(shortCircuit, Number)
404 return *shortCircuit
405 }
406
407 ret := new(big.Float)
408 ret.Add(val.v.(*big.Float), other.v.(*big.Float))
409 return NumberVal(ret)
410}
411
412// Subtract returns receiver minus the given other value. Both values must be
413// numbers; this method will panic if not.
414func (val Value) Subtract(other Value) Value {
415 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
416 shortCircuit = forceShortCircuitType(shortCircuit, Number)
417 return *shortCircuit
418 }
419
420 return val.Add(other.Negate())
421}
422
423// Negate returns the numeric negative of the receiver, which must be a number.
424// This method will panic when given a value of any other type.
425func (val Value) Negate() Value {
426 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
427 shortCircuit = forceShortCircuitType(shortCircuit, Number)
428 return *shortCircuit
429 }
430
431 ret := new(big.Float).Neg(val.v.(*big.Float))
432 return NumberVal(ret)
433}
434
435// Multiply returns the product of the receiver and the given other value.
436// Both values must be numbers; this method will panic if not.
437func (val Value) Multiply(other Value) Value {
438 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
439 shortCircuit = forceShortCircuitType(shortCircuit, Number)
440 return *shortCircuit
441 }
442
443 ret := new(big.Float)
444 ret.Mul(val.v.(*big.Float), other.v.(*big.Float))
445 return NumberVal(ret)
446}
447
448// Divide returns the quotient of the receiver and the given other value.
449// Both values must be numbers; this method will panic if not.
450//
451// If the "other" value is exactly zero, this operation will return either
452// PositiveInfinity or NegativeInfinity, depending on the sign of the
453// receiver value. For some use-cases the presence of infinities may be
454// undesirable, in which case the caller should check whether the
455// other value equals zero before calling and raise an error instead.
456//
457// If both values are zero or infinity, this function will panic with
458// an instance of big.ErrNaN.
459func (val Value) Divide(other Value) Value {
460 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
461 shortCircuit = forceShortCircuitType(shortCircuit, Number)
462 return *shortCircuit
463 }
464
465 ret := new(big.Float)
466 ret.Quo(val.v.(*big.Float), other.v.(*big.Float))
467 return NumberVal(ret)
468}
469
470// Modulo returns the remainder of an integer division of the receiver and
471// the given other value. Both values must be numbers; this method will panic
472// if not.
473//
474// If the "other" value is exactly zero, this operation will return either
475// PositiveInfinity or NegativeInfinity, depending on the sign of the
476// receiver value. For some use-cases the presence of infinities may be
477// undesirable, in which case the caller should check whether the
478// other value equals zero before calling and raise an error instead.
479//
480// This operation is primarily here for use with nonzero natural numbers.
481// Modulo with "other" as a non-natural number gets somewhat philosophical,
482// and this function takes a position on what that should mean, but callers
483// may wish to disallow such things outright or implement their own modulo
484// if they disagree with the interpretation used here.
485func (val Value) Modulo(other Value) Value {
486 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
487 shortCircuit = forceShortCircuitType(shortCircuit, Number)
488 return *shortCircuit
489 }
490
491 // We cheat a bit here with infinities, just abusing the Multiply operation
492 // to get an infinite result of the correct sign.
493 if val == PositiveInfinity || val == NegativeInfinity || other == PositiveInfinity || other == NegativeInfinity {
494 return val.Multiply(other)
495 }
496
497 if other.RawEquals(Zero) {
498 return val
499 }
500
501 // FIXME: This is a bit clumsy. Should come back later and see if there's a
502 // more straightforward way to do this.
503 rat := val.Divide(other)
504 ratFloorInt := &big.Int{}
505 rat.v.(*big.Float).Int(ratFloorInt)
506 work := (&big.Float{}).SetInt(ratFloorInt)
507 work.Mul(other.v.(*big.Float), work)
508 work.Sub(val.v.(*big.Float), work)
509
510 return NumberVal(work)
511}
512
513// Absolute returns the absolute (signless) value of the receiver, which must
514// be a number or this method will panic.
515func (val Value) Absolute() Value {
516 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
517 shortCircuit = forceShortCircuitType(shortCircuit, Number)
518 return *shortCircuit
519 }
520
521 ret := (&big.Float{}).Abs(val.v.(*big.Float))
522 return NumberVal(ret)
523}
524
525// GetAttr returns the value of the given attribute of the receiver, which
526// must be of an object type that has an attribute of the given name.
527// This method will panic if the receiver type is not compatible.
528//
529// The method will also panic if the given attribute name is not defined
530// for the value's type. Use the attribute-related methods on Type to
531// check for the validity of an attribute before trying to use it.
532//
533// This method may be called on a value whose type is DynamicPseudoType,
534// in which case the result will also be DynamicVal.
535func (val Value) GetAttr(name string) Value {
536 if val.ty == DynamicPseudoType {
537 return DynamicVal
538 }
539
540 if !val.ty.IsObjectType() {
541 panic("value is not an object")
542 }
543
544 name = NormalizeString(name)
545 if !val.ty.HasAttribute(name) {
546 panic("value has no attribute of that name")
547 }
548
549 attrType := val.ty.AttributeType(name)
550
551 if !val.IsKnown() {
552 return UnknownVal(attrType)
553 }
554
555 return Value{
556 ty: attrType,
557 v: val.v.(map[string]interface{})[name],
558 }
559}
560
561// Index returns the value of an element of the receiver, which must have
562// either a list, map or tuple type. This method will panic if the receiver
563// type is not compatible.
564//
565// The key value must be the correct type for the receving collection: a
566// number if the collection is a list or tuple, or a string if it is a map.
567// In the case of a list or tuple, the given number must be convertable to int
568// or this method will panic. The key may alternatively be of
569// DynamicPseudoType, in which case the result itself is an unknown of the
570// collection's element type.
571//
572// The result is of the receiver collection's element type, or in the case
573// of a tuple the type of the specific element index requested.
574//
575// This method may be called on a value whose type is DynamicPseudoType,
576// in which case the result will also be the DynamicValue.
577func (val Value) Index(key Value) Value {
578 if val.ty == DynamicPseudoType {
579 return DynamicVal
580 }
581
582 switch {
583 case val.Type().IsListType():
584 elty := val.Type().ElementType()
585 if key.Type() == DynamicPseudoType {
586 return UnknownVal(elty)
587 }
588
589 if key.Type() != Number {
590 panic("element key for list must be number")
591 }
592 if !key.IsKnown() {
593 return UnknownVal(elty)
594 }
595
596 if !val.IsKnown() {
597 return UnknownVal(elty)
598 }
599
600 index, accuracy := key.v.(*big.Float).Int64()
601 if accuracy != big.Exact || index < 0 {
602 panic("element key for list must be non-negative integer")
603 }
604
605 return Value{
606 ty: elty,
607 v: val.v.([]interface{})[index],
608 }
609 case val.Type().IsMapType():
610 elty := val.Type().ElementType()
611 if key.Type() == DynamicPseudoType {
612 return UnknownVal(elty)
613 }
614
615 if key.Type() != String {
616 panic("element key for map must be string")
617 }
618 if !key.IsKnown() {
619 return UnknownVal(elty)
620 }
621
622 if !val.IsKnown() {
623 return UnknownVal(elty)
624 }
625
626 keyStr := key.v.(string)
627
628 return Value{
629 ty: elty,
630 v: val.v.(map[string]interface{})[keyStr],
631 }
632 case val.Type().IsTupleType():
633 if key.Type() == DynamicPseudoType {
634 return DynamicVal
635 }
636
637 if key.Type() != Number {
638 panic("element key for tuple must be number")
639 }
640 if !key.IsKnown() {
641 return DynamicVal
642 }
643
644 index, accuracy := key.v.(*big.Float).Int64()
645 if accuracy != big.Exact || index < 0 {
646 panic("element key for list must be non-negative integer")
647 }
648
649 eltys := val.Type().TupleElementTypes()
650
651 if !val.IsKnown() {
652 return UnknownVal(eltys[index])
653 }
654
655 return Value{
656 ty: eltys[index],
657 v: val.v.([]interface{})[index],
658 }
659 default:
660 panic("not a list, map, or tuple type")
661 }
662}
663
664// HasIndex returns True if the receiver (which must be supported for Index)
665// has an element with the given index key, or False if it does not.
666//
667// The result will be UnknownVal(Bool) if either the collection or the
668// key value are unknown.
669//
670// This method will panic if the receiver is not indexable, but does not
671// impose any panic-causing type constraints on the key.
672func (val Value) HasIndex(key Value) Value {
673 if val.ty == DynamicPseudoType {
674 return UnknownVal(Bool)
675 }
676
677 switch {
678 case val.Type().IsListType():
679 if key.Type() == DynamicPseudoType {
680 return UnknownVal(Bool)
681 }
682
683 if key.Type() != Number {
684 return False
685 }
686 if !key.IsKnown() {
687 return UnknownVal(Bool)
688 }
689 if !val.IsKnown() {
690 return UnknownVal(Bool)
691 }
692
693 index, accuracy := key.v.(*big.Float).Int64()
694 if accuracy != big.Exact || index < 0 {
695 return False
696 }
697
698 return BoolVal(int(index) < len(val.v.([]interface{})) && index >= 0)
699 case val.Type().IsMapType():
700 if key.Type() == DynamicPseudoType {
701 return UnknownVal(Bool)
702 }
703
704 if key.Type() != String {
705 return False
706 }
707 if !key.IsKnown() {
708 return UnknownVal(Bool)
709 }
710 if !val.IsKnown() {
711 return UnknownVal(Bool)
712 }
713
714 keyStr := key.v.(string)
715 _, exists := val.v.(map[string]interface{})[keyStr]
716
717 return BoolVal(exists)
718 case val.Type().IsTupleType():
719 if key.Type() == DynamicPseudoType {
720 return UnknownVal(Bool)
721 }
722
723 if key.Type() != Number {
724 return False
725 }
726 if !key.IsKnown() {
727 return UnknownVal(Bool)
728 }
729
730 index, accuracy := key.v.(*big.Float).Int64()
731 if accuracy != big.Exact || index < 0 {
732 return False
733 }
734
735 length := val.Type().Length()
736 return BoolVal(int(index) < length && index >= 0)
737 default:
738 panic("not a list, map, or tuple type")
739 }
740}
741
742// HasElement returns True if the receiver (which must be of a set type)
743// has the given value as an element, or False if it does not.
744//
745// The result will be UnknownVal(Bool) if either the set or the
746// given value are unknown.
747//
748// This method will panic if the receiver is not a set, or if it is a null set.
749func (val Value) HasElement(elem Value) Value {
750 ty := val.Type()
751
752 if !ty.IsSetType() {
753 panic("not a set type")
754 }
755 if !val.IsKnown() || !elem.IsKnown() {
756 return UnknownVal(Bool)
757 }
758 if val.IsNull() {
759 panic("can't call HasElement on a nil value")
760 }
761 if ty.ElementType() != elem.Type() {
762 return False
763 }
764
765 s := val.v.(set.Set)
766 return BoolVal(s.Has(elem.v))
767}
768
769// Length returns the length of the receiver, which must be a collection type
770// or tuple type, as a number value. If the receiver is not a compatible type
771// then this method will panic.
772//
773// If the receiver is unknown then the result is also unknown.
774//
775// If the receiver is null then this function will panic.
776//
777// Note that Length is not supported for strings. To determine the length
778// of a string, call AsString and take the length of the native Go string
779// that is returned.
780func (val Value) Length() Value {
781 if val.Type().IsTupleType() {
782 // For tuples, we can return the length even if the value is not known.
783 return NumberIntVal(int64(val.Type().Length()))
784 }
785
786 if !val.IsKnown() {
787 return UnknownVal(Number)
788 }
789
790 return NumberIntVal(int64(val.LengthInt()))
791}
792
793// LengthInt is like Length except it returns an int. It has the same behavior
794// as Length except that it will panic if the receiver is unknown.
795//
796// This is an integration method provided for the convenience of code bridging
797// into Go's type system.
798func (val Value) LengthInt() int {
799 if val.Type().IsTupleType() {
800 // For tuples, we can return the length even if the value is not known.
801 return val.Type().Length()
802 }
803 if !val.IsKnown() {
804 panic("value is not known")
805 }
806 if val.IsNull() {
807 panic("value is null")
808 }
809
810 switch {
811
812 case val.ty.IsListType():
813 return len(val.v.([]interface{}))
814
815 case val.ty.IsSetType():
816 return val.v.(set.Set).Length()
817
818 case val.ty.IsMapType():
819 return len(val.v.(map[string]interface{}))
820
821 default:
822 panic("value is not a collection")
823 }
824}
825
826// ElementIterator returns an ElementIterator for iterating the elements
827// of the receiver, which must be a collection type, a tuple type, or an object
828// type. If called on a method of any other type, this method will panic.
829//
830// The value must be Known and non-Null, or this method will panic.
831//
832// If the receiver is of a list type, the returned keys will be of type Number
833// and the values will be of the list's element type.
834//
835// If the receiver is of a map type, the returned keys will be of type String
836// and the value will be of the map's element type. Elements are passed in
837// ascending lexicographical order by key.
838//
839// If the receiver is of a set type, each element is returned as both the
840// key and the value, since set members are their own identity.
841//
842// If the receiver is of a tuple type, the returned keys will be of type Number
843// and the value will be of the corresponding element's type.
844//
845// If the receiver is of an object type, the returned keys will be of type
846// String and the value will be of the corresponding attributes's type.
847//
848// ElementIterator is an integration method, so it cannot handle Unknown
849// values. This method will panic if the receiver is Unknown.
850func (val Value) ElementIterator() ElementIterator {
851 if !val.IsKnown() {
852 panic("can't use ElementIterator on unknown value")
853 }
854 if val.IsNull() {
855 panic("can't use ElementIterator on null value")
856 }
857 return elementIterator(val)
858}
859
860// CanIterateElements returns true if the receiver can support the
861// ElementIterator method (and by extension, ForEachElement) without panic.
862func (val Value) CanIterateElements() bool {
863 return canElementIterator(val)
864}
865
866// ForEachElement executes a given callback function for each element of
867// the receiver, which must be a collection type or tuple type, or this method
868// will panic.
869//
870// ForEachElement uses ElementIterator internally, and so the values passed
871// to the callback are as described for ElementIterator.
872//
873// Returns true if the iteration exited early due to the callback function
874// returning true, or false if the loop ran to completion.
875//
876// ForEachElement is an integration method, so it cannot handle Unknown
877// values. This method will panic if the receiver is Unknown.
878func (val Value) ForEachElement(cb ElementCallback) bool {
879 it := val.ElementIterator()
880 for it.Next() {
881 key, val := it.Element()
882 stop := cb(key, val)
883 if stop {
884 return true
885 }
886 }
887 return false
888}
889
890// Not returns the logical inverse of the receiver, which must be of type
891// Bool or this method will panic.
892func (val Value) Not() Value {
893 if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil {
894 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
895 return *shortCircuit
896 }
897
898 return BoolVal(!val.v.(bool))
899}
900
901// And returns the result of logical AND with the receiver and the other given
902// value, which must both be of type Bool or this method will panic.
903func (val Value) And(other Value) Value {
904 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
905 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
906 return *shortCircuit
907 }
908
909 return BoolVal(val.v.(bool) && other.v.(bool))
910}
911
912// Or returns the result of logical OR with the receiver and the other given
913// value, which must both be of type Bool or this method will panic.
914func (val Value) Or(other Value) Value {
915 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
916 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
917 return *shortCircuit
918 }
919
920 return BoolVal(val.v.(bool) || other.v.(bool))
921}
922
923// LessThan returns True if the receiver is less than the other given value,
924// which must both be numbers or this method will panic.
925func (val Value) LessThan(other Value) Value {
926 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
927 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
928 return *shortCircuit
929 }
930
931 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0)
932}
933
934// GreaterThan returns True if the receiver is greater than the other given
935// value, which must both be numbers or this method will panic.
936func (val Value) GreaterThan(other Value) Value {
937 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
938 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
939 return *shortCircuit
940 }
941
942 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0)
943}
944
945// LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or.
946func (val Value) LessThanOrEqualTo(other Value) Value {
947 return val.LessThan(other).Or(val.Equals(other))
948}
949
950// GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or.
951func (val Value) GreaterThanOrEqualTo(other Value) Value {
952 return val.GreaterThan(other).Or(val.Equals(other))
953}
954
955// AsString returns the native string from a non-null, non-unknown cty.String
956// value, or panics if called on any other value.
957func (val Value) AsString() string {
958 if val.ty != String {
959 panic("not a string")
960 }
961 if val.IsNull() {
962 panic("value is null")
963 }
964 if !val.IsKnown() {
965 panic("value is unknown")
966 }
967
968 return val.v.(string)
969}
970
971// AsBigFloat returns a big.Float representation of a non-null, non-unknown
972// cty.Number value, or panics if called on any other value.
973//
974// For more convenient conversions to other native numeric types, use the
975// "gocty" package.
976func (val Value) AsBigFloat() *big.Float {
977 if val.ty != Number {
978 panic("not a number")
979 }
980 if val.IsNull() {
981 panic("value is null")
982 }
983 if !val.IsKnown() {
984 panic("value is unknown")
985 }
986
987 // Copy the float so that callers can't mutate our internal state
988 ret := *(val.v.(*big.Float))
989
990 return &ret
991}
992
993// AsValueSlice returns a []cty.Value representation of a non-null, non-unknown
994// value of any type that CanIterateElements, or panics if called on
995// any other value.
996//
997// For more convenient conversions to slices of more specific types, use
998// the "gocty" package.
999func (val Value) AsValueSlice() []Value {
1000 l := val.LengthInt()
1001 if l == 0 {
1002 return nil
1003 }
1004
1005 ret := make([]Value, 0, l)
1006 for it := val.ElementIterator(); it.Next(); {
1007 _, v := it.Element()
1008 ret = append(ret, v)
1009 }
1010 return ret
1011}
1012
1013// AsValueMap returns a map[string]cty.Value representation of a non-null,
1014// non-unknown value of any type that CanIterateElements, or panics if called
1015// on any other value.
1016//
1017// For more convenient conversions to maps of more specific types, use
1018// the "gocty" package.
1019func (val Value) AsValueMap() map[string]Value {
1020 l := val.LengthInt()
1021 if l == 0 {
1022 return nil
1023 }
1024
1025 ret := make(map[string]Value, l)
1026 for it := val.ElementIterator(); it.Next(); {
1027 k, v := it.Element()
1028 ret[k.AsString()] = v
1029 }
1030 return ret
1031}
1032
1033// AsValueSet returns a ValueSet representation of a non-null,
1034// non-unknown value of any collection type, or panics if called
1035// on any other value.
1036//
1037// Unlike AsValueSlice and AsValueMap, this method requires specifically a
1038// collection type (list, set or map) and does not allow structural types
1039// (tuple or object), because the ValueSet type requires homogenous
1040// element types.
1041//
1042// The returned ValueSet can store only values of the receiver's element type.
1043func (val Value) AsValueSet() ValueSet {
1044 if !val.Type().IsCollectionType() {
1045 panic("not a collection type")
1046 }
1047
1048 // We don't give the caller our own set.Set (assuming we're a cty.Set value)
1049 // because then the caller could mutate our internals, which is forbidden.
1050 // Instead, we will construct a new set and append our elements into it.
1051 ret := NewValueSet(val.Type().ElementType())
1052 for it := val.ElementIterator(); it.Next(); {
1053 _, v := it.Element()
1054 ret.Add(v)
1055 }
1056 return ret
1057}
1058
1059// EncapsulatedValue returns the native value encapsulated in a non-null,
1060// non-unknown capsule-typed value, or panics if called on any other value.
1061//
1062// The result is the same pointer that was passed to CapsuleVal to create
1063// the value. Since cty considers values to be immutable, it is strongly
1064// recommended to treat the encapsulated value itself as immutable too.
1065func (val Value) EncapsulatedValue() interface{} {
1066 if !val.Type().IsCapsuleType() {
1067 panic("not a capsule-typed value")
1068 }
1069
1070 return val.v
1071}
diff --git a/vendor/github.com/zclconf/go-cty/cty/walk.go b/vendor/github.com/zclconf/go-cty/cty/walk.go
new file mode 100644
index 0000000..a6943ba
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/walk.go
@@ -0,0 +1,182 @@
1package cty
2
3// Walk visits all of the values in a possibly-complex structure, calling
4// a given function for each value.
5//
6// For example, given a list of strings the callback would first be called
7// with the whole list and then called once for each element of the list.
8//
9// The callback function may prevent recursive visits to child values by
10// returning false. The callback function my halt the walk altogether by
11// returning a non-nil error. If the returned error is about the element
12// currently being visited, it is recommended to use the provided path
13// value to produce a PathError describing that context.
14//
15// The path passed to the given function may not be used after that function
16// returns, since its backing array is re-used for other calls.
17func Walk(val Value, cb func(Path, Value) (bool, error)) error {
18 var path Path
19 return walk(path, val, cb)
20}
21
22func walk(path Path, val Value, cb func(Path, Value) (bool, error)) error {
23 deeper, err := cb(path, val)
24 if err != nil {
25 return err
26 }
27 if !deeper {
28 return nil
29 }
30
31 if val.IsNull() || !val.IsKnown() {
32 // Can't recurse into null or unknown values, regardless of type
33 return nil
34 }
35
36 ty := val.Type()
37 switch {
38 case ty.IsObjectType():
39 for it := val.ElementIterator(); it.Next(); {
40 nameVal, av := it.Element()
41 path := append(path, GetAttrStep{
42 Name: nameVal.AsString(),
43 })
44 err := walk(path, av, cb)
45 if err != nil {
46 return err
47 }
48 }
49 case val.CanIterateElements():
50 for it := val.ElementIterator(); it.Next(); {
51 kv, ev := it.Element()
52 path := append(path, IndexStep{
53 Key: kv,
54 })
55 err := walk(path, ev, cb)
56 if err != nil {
57 return err
58 }
59 }
60 }
61 return nil
62}
63
64// Transform visits all of the values in a possibly-complex structure,
65// calling a given function for each value which has an opportunity to
66// replace that value.
67//
68// Unlike Walk, Transform visits child nodes first, so for a list of strings
69// it would first visit the strings and then the _new_ list constructed
70// from the transformed values of the list items.
71//
72// This is useful for creating the effect of being able to make deep mutations
73// to a value even though values are immutable. However, it's the responsibility
74// of the given function to preserve expected invariants, such as homogenity of
75// element types in collections; this function can panic if such invariants
76// are violated, just as if new values were constructed directly using the
77// value constructor functions. An easy way to preserve invariants is to
78// ensure that the transform function never changes the value type.
79//
80// The callback function my halt the walk altogether by
81// returning a non-nil error. If the returned error is about the element
82// currently being visited, it is recommended to use the provided path
83// value to produce a PathError describing that context.
84//
85// The path passed to the given function may not be used after that function
86// returns, since its backing array is re-used for other calls.
87func Transform(val Value, cb func(Path, Value) (Value, error)) (Value, error) {
88 var path Path
89 return transform(path, val, cb)
90}
91
92func transform(path Path, val Value, cb func(Path, Value) (Value, error)) (Value, error) {
93 ty := val.Type()
94 var newVal Value
95
96 switch {
97
98 case val.IsNull() || !val.IsKnown():
99 // Can't recurse into null or unknown values, regardless of type
100 newVal = val
101
102 case ty.IsListType() || ty.IsSetType() || ty.IsTupleType():
103 l := val.LengthInt()
104 switch l {
105 case 0:
106 // No deep transform for an empty sequence
107 newVal = val
108 default:
109 elems := make([]Value, 0, l)
110 for it := val.ElementIterator(); it.Next(); {
111 kv, ev := it.Element()
112 path := append(path, IndexStep{
113 Key: kv,
114 })
115 newEv, err := transform(path, ev, cb)
116 if err != nil {
117 return DynamicVal, err
118 }
119 elems = append(elems, newEv)
120 }
121 switch {
122 case ty.IsListType():
123 newVal = ListVal(elems)
124 case ty.IsSetType():
125 newVal = SetVal(elems)
126 case ty.IsTupleType():
127 newVal = TupleVal(elems)
128 default:
129 panic("unknown sequence type") // should never happen because of the case we are in
130 }
131 }
132
133 case ty.IsMapType():
134 l := val.LengthInt()
135 switch l {
136 case 0:
137 // No deep transform for an empty map
138 newVal = val
139 default:
140 elems := make(map[string]Value)
141 for it := val.ElementIterator(); it.Next(); {
142 kv, ev := it.Element()
143 path := append(path, IndexStep{
144 Key: kv,
145 })
146 newEv, err := transform(path, ev, cb)
147 if err != nil {
148 return DynamicVal, err
149 }
150 elems[kv.AsString()] = newEv
151 }
152 newVal = MapVal(elems)
153 }
154
155 case ty.IsObjectType():
156 switch {
157 case ty.Equals(EmptyObject):
158 // No deep transform for an empty object
159 newVal = val
160 default:
161 atys := ty.AttributeTypes()
162 newAVs := make(map[string]Value)
163 for name := range atys {
164 av := val.GetAttr(name)
165 path := append(path, GetAttrStep{
166 Name: name,
167 })
168 newAV, err := transform(path, av, cb)
169 if err != nil {
170 return DynamicVal, err
171 }
172 newAVs[name] = newAV
173 }
174 newVal = ObjectVal(newAVs)
175 }
176
177 default:
178 newVal = val
179 }
180
181 return cb(path, newVal)
182}