]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/zclconf/go-cty/cty/value_init.go
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / zclconf / go-cty / cty / value_init.go
1 package cty
2
3 import (
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.
15 func 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.
26 func 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.
35 func 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.
41 func 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.
47 func 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.
59 func 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.
71 func 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.
77 func 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.
95 func 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.)
117 func 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.
144 func 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.)
158 func 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.
185 func 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.)
199 func 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.
232 func 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.
243 func 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.
257 func 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 }