]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / zclconf / go-cty / cty / json / unmarshal.go
CommitLineData
15c0b25d
AP
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:
107c1cdb 75 val, err := cty.ParseNumberVal(v)
15c0b25d
AP
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}