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