aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go226
1 files changed, 226 insertions, 0 deletions
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}