diff options
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.go | 226 |
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 @@ | |||
1 | package convert | ||
2 | |||
3 | import ( | ||
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.) | ||
14 | func 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.) | ||
54 | func 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. | ||
91 | func 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. | ||
161 | func 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 | } | ||