]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/zclconf/go-cty/cty/value_ops.go
afd621cf4ffaecc50bce87bb0b5900556888825d
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / zclconf / go-cty / cty / value_ops.go
1 package cty
2
3 import (
4 "fmt"
5 "math/big"
6 "reflect"
7
8 "github.com/zclconf/go-cty/cty/set"
9 )
10
11 // GoString is an implementation of fmt.GoStringer that produces concise
12 // source-like representations of values suitable for use in debug messages.
13 func (val Value) GoString() string {
14 if val == NilVal {
15 return "cty.NilVal"
16 }
17
18 if val.IsNull() {
19 return fmt.Sprintf("cty.NullVal(%#v)", val.ty)
20 }
21 if val == DynamicVal { // is unknown, so must be before the IsKnown check below
22 return "cty.DynamicVal"
23 }
24 if !val.IsKnown() {
25 return fmt.Sprintf("cty.UnknownVal(%#v)", val.ty)
26 }
27
28 // By the time we reach here we've dealt with all of the exceptions around
29 // unknowns and nulls, so we're guaranteed that the values are the
30 // canonical internal representation of the given type.
31
32 switch val.ty {
33 case Bool:
34 if val.v.(bool) {
35 return "cty.True"
36 }
37 return "cty.False"
38 case Number:
39 fv := val.v.(*big.Float)
40 // We'll try to use NumberIntVal or NumberFloatVal if we can, since
41 // the fully-general initializer call is pretty ugly-looking.
42 if fv.IsInt() {
43 return fmt.Sprintf("cty.NumberIntVal(%#v)", fv)
44 }
45 if rfv, accuracy := fv.Float64(); accuracy == big.Exact {
46 return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv)
47 }
48 return fmt.Sprintf("cty.MustParseNumberVal(%q)", fv.Text('f', -1))
49 case String:
50 return fmt.Sprintf("cty.StringVal(%#v)", val.v)
51 }
52
53 switch {
54 case val.ty.IsSetType():
55 vals := val.AsValueSlice()
56 if len(vals) == 0 {
57 return fmt.Sprintf("cty.SetValEmpty(%#v)", val.ty.ElementType())
58 }
59 return fmt.Sprintf("cty.SetVal(%#v)", vals)
60 case val.ty.IsListType():
61 vals := val.AsValueSlice()
62 if len(vals) == 0 {
63 return fmt.Sprintf("cty.ListValEmpty(%#v)", val.ty.ElementType())
64 }
65 return fmt.Sprintf("cty.ListVal(%#v)", vals)
66 case val.ty.IsMapType():
67 vals := val.AsValueMap()
68 if len(vals) == 0 {
69 return fmt.Sprintf("cty.MapValEmpty(%#v)", val.ty.ElementType())
70 }
71 return fmt.Sprintf("cty.MapVal(%#v)", vals)
72 case val.ty.IsTupleType():
73 if val.ty.Equals(EmptyTuple) {
74 return "cty.EmptyTupleVal"
75 }
76 vals := val.AsValueSlice()
77 return fmt.Sprintf("cty.TupleVal(%#v)", vals)
78 case val.ty.IsObjectType():
79 if val.ty.Equals(EmptyObject) {
80 return "cty.EmptyObjectVal"
81 }
82 vals := val.AsValueMap()
83 return fmt.Sprintf("cty.ObjectVal(%#v)", vals)
84 case val.ty.IsCapsuleType():
85 return fmt.Sprintf("cty.CapsuleVal(%#v, %#v)", val.ty, val.v)
86 }
87
88 // Default exposes implementation details, so should actually cover
89 // all of the cases above for good caller UX.
90 return fmt.Sprintf("cty.Value{ty: %#v, v: %#v}", val.ty, val.v)
91 }
92
93 // Equals returns True if the receiver and the given other value have the
94 // same type and are exactly equal in value.
95 //
96 // As a special case, two null values are always equal regardless of type.
97 //
98 // The usual short-circuit rules apply, so the result will be unknown if
99 // either of the given values are.
100 //
101 // Use RawEquals to compare if two values are equal *ignoring* the
102 // short-circuit rules and the exception for null values.
103 func (val Value) Equals(other Value) Value {
104 // Start by handling Unknown values before considering types.
105 // This needs to be done since Null values are always equal regardless of
106 // type.
107 switch {
108 case !val.IsKnown() && !other.IsKnown():
109 // both unknown
110 return UnknownVal(Bool)
111 case val.IsKnown() && !other.IsKnown():
112 switch {
113 case val.IsNull(), other.ty.HasDynamicTypes():
114 // If known is Null, we need to wait for the unkown value since
115 // nulls of any type are equal.
116 // An unkown with a dynamic type compares as unknown, which we need
117 // to check before the type comparison below.
118 return UnknownVal(Bool)
119 case !val.ty.Equals(other.ty):
120 // There is no null comparison or dynamic types, so unequal types
121 // will never be equal.
122 return False
123 default:
124 return UnknownVal(Bool)
125 }
126 case other.IsKnown() && !val.IsKnown():
127 switch {
128 case other.IsNull(), val.ty.HasDynamicTypes():
129 // If known is Null, we need to wait for the unkown value since
130 // nulls of any type are equal.
131 // An unkown with a dynamic type compares as unknown, which we need
132 // to check before the type comparison below.
133 return UnknownVal(Bool)
134 case !other.ty.Equals(val.ty):
135 // There's no null comparison or dynamic types, so unequal types
136 // will never be equal.
137 return False
138 default:
139 return UnknownVal(Bool)
140 }
141 }
142
143 switch {
144 case val.IsNull() && other.IsNull():
145 // Nulls are always equal, regardless of type
146 return BoolVal(true)
147 case val.IsNull() || other.IsNull():
148 // If only one is null then the result must be false
149 return BoolVal(false)
150 }
151
152 if val.ty.HasDynamicTypes() || other.ty.HasDynamicTypes() {
153 return UnknownVal(Bool)
154 }
155
156 if !val.ty.Equals(other.ty) {
157 return BoolVal(false)
158 }
159
160 ty := val.ty
161 result := false
162
163 switch {
164 case ty == Number:
165 result = val.v.(*big.Float).Cmp(other.v.(*big.Float)) == 0
166 case ty == Bool:
167 result = val.v.(bool) == other.v.(bool)
168 case ty == String:
169 // Simple equality is safe because we NFC-normalize strings as they
170 // enter our world from StringVal, and so we can assume strings are
171 // always in normal form.
172 result = val.v.(string) == other.v.(string)
173 case ty.IsObjectType():
174 oty := ty.typeImpl.(typeObject)
175 result = true
176 for attr, aty := range oty.AttrTypes {
177 lhs := Value{
178 ty: aty,
179 v: val.v.(map[string]interface{})[attr],
180 }
181 rhs := Value{
182 ty: aty,
183 v: other.v.(map[string]interface{})[attr],
184 }
185 eq := lhs.Equals(rhs)
186 if !eq.IsKnown() {
187 return UnknownVal(Bool)
188 }
189 if eq.False() {
190 result = false
191 break
192 }
193 }
194 case ty.IsTupleType():
195 tty := ty.typeImpl.(typeTuple)
196 result = true
197 for i, ety := range tty.ElemTypes {
198 lhs := Value{
199 ty: ety,
200 v: val.v.([]interface{})[i],
201 }
202 rhs := Value{
203 ty: ety,
204 v: other.v.([]interface{})[i],
205 }
206 eq := lhs.Equals(rhs)
207 if !eq.IsKnown() {
208 return UnknownVal(Bool)
209 }
210 if eq.False() {
211 result = false
212 break
213 }
214 }
215 case ty.IsListType():
216 ety := ty.typeImpl.(typeList).ElementTypeT
217 if len(val.v.([]interface{})) == len(other.v.([]interface{})) {
218 result = true
219 for i := range val.v.([]interface{}) {
220 lhs := Value{
221 ty: ety,
222 v: val.v.([]interface{})[i],
223 }
224 rhs := Value{
225 ty: ety,
226 v: other.v.([]interface{})[i],
227 }
228 eq := lhs.Equals(rhs)
229 if !eq.IsKnown() {
230 return UnknownVal(Bool)
231 }
232 if eq.False() {
233 result = false
234 break
235 }
236 }
237 }
238 case ty.IsSetType():
239 s1 := val.v.(set.Set)
240 s2 := other.v.(set.Set)
241 equal := true
242
243 // Note that by our definition of sets it's never possible for two
244 // sets that contain unknown values (directly or indicrectly) to
245 // ever be equal, even if they are otherwise identical.
246
247 // FIXME: iterating both lists and checking each item is not the
248 // ideal implementation here, but it works with the primitives we
249 // have in the set implementation. Perhaps the set implementation
250 // can provide its own equality test later.
251 s1.EachValue(func(v interface{}) {
252 if !s2.Has(v) {
253 equal = false
254 }
255 })
256 s2.EachValue(func(v interface{}) {
257 if !s1.Has(v) {
258 equal = false
259 }
260 })
261
262 result = equal
263 case ty.IsMapType():
264 ety := ty.typeImpl.(typeMap).ElementTypeT
265 if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) {
266 result = true
267 for k := range val.v.(map[string]interface{}) {
268 if _, ok := other.v.(map[string]interface{})[k]; !ok {
269 result = false
270 break
271 }
272 lhs := Value{
273 ty: ety,
274 v: val.v.(map[string]interface{})[k],
275 }
276 rhs := Value{
277 ty: ety,
278 v: other.v.(map[string]interface{})[k],
279 }
280 eq := lhs.Equals(rhs)
281 if !eq.IsKnown() {
282 return UnknownVal(Bool)
283 }
284 if eq.False() {
285 result = false
286 break
287 }
288 }
289 }
290 case ty.IsCapsuleType():
291 // A capsule type's encapsulated value is a pointer to a value of its
292 // native type, so we can just compare these to get the identity test
293 // we need.
294 return BoolVal(val.v == other.v)
295
296 default:
297 // should never happen
298 panic(fmt.Errorf("unsupported value type %#v in Equals", ty))
299 }
300
301 return BoolVal(result)
302 }
303
304 // NotEqual is a shorthand for Equals followed by Not.
305 func (val Value) NotEqual(other Value) Value {
306 return val.Equals(other).Not()
307 }
308
309 // True returns true if the receiver is True, false if False, and panics if
310 // the receiver is not of type Bool.
311 //
312 // This is a helper function to help write application logic that works with
313 // values, rather than a first-class operation. It does not work with unknown
314 // or null values. For more robust handling with unknown value
315 // short-circuiting, use val.Equals(cty.True).
316 func (val Value) True() bool {
317 if val.ty != Bool {
318 panic("not bool")
319 }
320 return val.Equals(True).v.(bool)
321 }
322
323 // False is the opposite of True.
324 func (val Value) False() bool {
325 return !val.True()
326 }
327
328 // RawEquals returns true if and only if the two given values have the same
329 // type and equal value, ignoring the usual short-circuit rules about
330 // unknowns and dynamic types.
331 //
332 // This method is more appropriate for testing than for real use, since it
333 // skips over usual semantics around unknowns but as a consequence allows
334 // testing the result of another operation that is expected to return unknown.
335 // It returns a primitive Go bool rather than a Value to remind us that it
336 // is not a first-class value operation.
337 func (val Value) RawEquals(other Value) bool {
338 if !val.ty.Equals(other.ty) {
339 return false
340 }
341 if (!val.IsKnown()) && (!other.IsKnown()) {
342 return true
343 }
344 if (val.IsKnown() && !other.IsKnown()) || (other.IsKnown() && !val.IsKnown()) {
345 return false
346 }
347 if val.IsNull() && other.IsNull() {
348 return true
349 }
350 if (val.IsNull() && !other.IsNull()) || (other.IsNull() && !val.IsNull()) {
351 return false
352 }
353 if val.ty == DynamicPseudoType && other.ty == DynamicPseudoType {
354 return true
355 }
356
357 ty := val.ty
358 switch {
359 case ty == Number || ty == Bool || ty == String || ty == DynamicPseudoType:
360 return val.Equals(other).True()
361 case ty.IsObjectType():
362 oty := ty.typeImpl.(typeObject)
363 for attr, aty := range oty.AttrTypes {
364 lhs := Value{
365 ty: aty,
366 v: val.v.(map[string]interface{})[attr],
367 }
368 rhs := Value{
369 ty: aty,
370 v: other.v.(map[string]interface{})[attr],
371 }
372 eq := lhs.RawEquals(rhs)
373 if !eq {
374 return false
375 }
376 }
377 return true
378 case ty.IsTupleType():
379 tty := ty.typeImpl.(typeTuple)
380 for i, ety := range tty.ElemTypes {
381 lhs := Value{
382 ty: ety,
383 v: val.v.([]interface{})[i],
384 }
385 rhs := Value{
386 ty: ety,
387 v: other.v.([]interface{})[i],
388 }
389 eq := lhs.RawEquals(rhs)
390 if !eq {
391 return false
392 }
393 }
394 return true
395 case ty.IsListType():
396 ety := ty.typeImpl.(typeList).ElementTypeT
397 if len(val.v.([]interface{})) == len(other.v.([]interface{})) {
398 for i := range val.v.([]interface{}) {
399 lhs := Value{
400 ty: ety,
401 v: val.v.([]interface{})[i],
402 }
403 rhs := Value{
404 ty: ety,
405 v: other.v.([]interface{})[i],
406 }
407 eq := lhs.RawEquals(rhs)
408 if !eq {
409 return false
410 }
411 }
412 return true
413 }
414 return false
415 case ty.IsSetType():
416 s1 := val.v.(set.Set)
417 s2 := other.v.(set.Set)
418
419 // Since we're intentionally ignoring our rule that two unknowns
420 // are never equal, we can cheat here.
421 // (This isn't 100% right since e.g. it will fail if the set contains
422 // numbers that are infinite, which DeepEqual can't compare properly.
423 // We're accepting that limitation for simplicity here, since this
424 // function is here primarily for testing.)
425 return reflect.DeepEqual(s1, s2)
426
427 case ty.IsMapType():
428 ety := ty.typeImpl.(typeMap).ElementTypeT
429 if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) {
430 for k := range val.v.(map[string]interface{}) {
431 if _, ok := other.v.(map[string]interface{})[k]; !ok {
432 return false
433 }
434 lhs := Value{
435 ty: ety,
436 v: val.v.(map[string]interface{})[k],
437 }
438 rhs := Value{
439 ty: ety,
440 v: other.v.(map[string]interface{})[k],
441 }
442 eq := lhs.RawEquals(rhs)
443 if !eq {
444 return false
445 }
446 }
447 return true
448 }
449 return false
450 case ty.IsCapsuleType():
451 // A capsule type's encapsulated value is a pointer to a value of its
452 // native type, so we can just compare these to get the identity test
453 // we need.
454 return val.v == other.v
455
456 default:
457 // should never happen
458 panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty))
459 }
460 }
461
462 // Add returns the sum of the receiver and the given other value. Both values
463 // must be numbers; this method will panic if not.
464 func (val Value) Add(other Value) Value {
465 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
466 shortCircuit = forceShortCircuitType(shortCircuit, Number)
467 return *shortCircuit
468 }
469
470 ret := new(big.Float)
471 ret.Add(val.v.(*big.Float), other.v.(*big.Float))
472 return NumberVal(ret)
473 }
474
475 // Subtract returns receiver minus the given other value. Both values must be
476 // numbers; this method will panic if not.
477 func (val Value) Subtract(other Value) Value {
478 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
479 shortCircuit = forceShortCircuitType(shortCircuit, Number)
480 return *shortCircuit
481 }
482
483 return val.Add(other.Negate())
484 }
485
486 // Negate returns the numeric negative of the receiver, which must be a number.
487 // This method will panic when given a value of any other type.
488 func (val Value) Negate() Value {
489 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
490 shortCircuit = forceShortCircuitType(shortCircuit, Number)
491 return *shortCircuit
492 }
493
494 ret := new(big.Float).Neg(val.v.(*big.Float))
495 return NumberVal(ret)
496 }
497
498 // Multiply returns the product of the receiver and the given other value.
499 // Both values must be numbers; this method will panic if not.
500 func (val Value) Multiply(other Value) Value {
501 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
502 shortCircuit = forceShortCircuitType(shortCircuit, Number)
503 return *shortCircuit
504 }
505
506 ret := new(big.Float)
507 ret.Mul(val.v.(*big.Float), other.v.(*big.Float))
508 return NumberVal(ret)
509 }
510
511 // Divide returns the quotient of the receiver and the given other value.
512 // Both values must be numbers; this method will panic if not.
513 //
514 // If the "other" value is exactly zero, this operation will return either
515 // PositiveInfinity or NegativeInfinity, depending on the sign of the
516 // receiver value. For some use-cases the presence of infinities may be
517 // undesirable, in which case the caller should check whether the
518 // other value equals zero before calling and raise an error instead.
519 //
520 // If both values are zero or infinity, this function will panic with
521 // an instance of big.ErrNaN.
522 func (val Value) Divide(other Value) Value {
523 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
524 shortCircuit = forceShortCircuitType(shortCircuit, Number)
525 return *shortCircuit
526 }
527
528 ret := new(big.Float)
529 ret.Quo(val.v.(*big.Float), other.v.(*big.Float))
530 return NumberVal(ret)
531 }
532
533 // Modulo returns the remainder of an integer division of the receiver and
534 // the given other value. Both values must be numbers; this method will panic
535 // if not.
536 //
537 // If the "other" value is exactly zero, this operation will return either
538 // PositiveInfinity or NegativeInfinity, depending on the sign of the
539 // receiver value. For some use-cases the presence of infinities may be
540 // undesirable, in which case the caller should check whether the
541 // other value equals zero before calling and raise an error instead.
542 //
543 // This operation is primarily here for use with nonzero natural numbers.
544 // Modulo with "other" as a non-natural number gets somewhat philosophical,
545 // and this function takes a position on what that should mean, but callers
546 // may wish to disallow such things outright or implement their own modulo
547 // if they disagree with the interpretation used here.
548 func (val Value) Modulo(other Value) Value {
549 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
550 shortCircuit = forceShortCircuitType(shortCircuit, Number)
551 return *shortCircuit
552 }
553
554 // We cheat a bit here with infinities, just abusing the Multiply operation
555 // to get an infinite result of the correct sign.
556 if val == PositiveInfinity || val == NegativeInfinity || other == PositiveInfinity || other == NegativeInfinity {
557 return val.Multiply(other)
558 }
559
560 if other.RawEquals(Zero) {
561 return val
562 }
563
564 // FIXME: This is a bit clumsy. Should come back later and see if there's a
565 // more straightforward way to do this.
566 rat := val.Divide(other)
567 ratFloorInt := &big.Int{}
568 rat.v.(*big.Float).Int(ratFloorInt)
569 work := (&big.Float{}).SetInt(ratFloorInt)
570 work.Mul(other.v.(*big.Float), work)
571 work.Sub(val.v.(*big.Float), work)
572
573 return NumberVal(work)
574 }
575
576 // Absolute returns the absolute (signless) value of the receiver, which must
577 // be a number or this method will panic.
578 func (val Value) Absolute() Value {
579 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
580 shortCircuit = forceShortCircuitType(shortCircuit, Number)
581 return *shortCircuit
582 }
583
584 ret := (&big.Float{}).Abs(val.v.(*big.Float))
585 return NumberVal(ret)
586 }
587
588 // GetAttr returns the value of the given attribute of the receiver, which
589 // must be of an object type that has an attribute of the given name.
590 // This method will panic if the receiver type is not compatible.
591 //
592 // The method will also panic if the given attribute name is not defined
593 // for the value's type. Use the attribute-related methods on Type to
594 // check for the validity of an attribute before trying to use it.
595 //
596 // This method may be called on a value whose type is DynamicPseudoType,
597 // in which case the result will also be DynamicVal.
598 func (val Value) GetAttr(name string) Value {
599 if val.ty == DynamicPseudoType {
600 return DynamicVal
601 }
602
603 if !val.ty.IsObjectType() {
604 panic("value is not an object")
605 }
606
607 name = NormalizeString(name)
608 if !val.ty.HasAttribute(name) {
609 panic("value has no attribute of that name")
610 }
611
612 attrType := val.ty.AttributeType(name)
613
614 if !val.IsKnown() {
615 return UnknownVal(attrType)
616 }
617
618 return Value{
619 ty: attrType,
620 v: val.v.(map[string]interface{})[name],
621 }
622 }
623
624 // Index returns the value of an element of the receiver, which must have
625 // either a list, map or tuple type. This method will panic if the receiver
626 // type is not compatible.
627 //
628 // The key value must be the correct type for the receving collection: a
629 // number if the collection is a list or tuple, or a string if it is a map.
630 // In the case of a list or tuple, the given number must be convertable to int
631 // or this method will panic. The key may alternatively be of
632 // DynamicPseudoType, in which case the result itself is an unknown of the
633 // collection's element type.
634 //
635 // The result is of the receiver collection's element type, or in the case
636 // of a tuple the type of the specific element index requested.
637 //
638 // This method may be called on a value whose type is DynamicPseudoType,
639 // in which case the result will also be the DynamicValue.
640 func (val Value) Index(key Value) Value {
641 if val.ty == DynamicPseudoType {
642 return DynamicVal
643 }
644
645 switch {
646 case val.Type().IsListType():
647 elty := val.Type().ElementType()
648 if key.Type() == DynamicPseudoType {
649 return UnknownVal(elty)
650 }
651
652 if key.Type() != Number {
653 panic("element key for list must be number")
654 }
655 if !key.IsKnown() {
656 return UnknownVal(elty)
657 }
658
659 if !val.IsKnown() {
660 return UnknownVal(elty)
661 }
662
663 index, accuracy := key.v.(*big.Float).Int64()
664 if accuracy != big.Exact || index < 0 {
665 panic("element key for list must be non-negative integer")
666 }
667
668 return Value{
669 ty: elty,
670 v: val.v.([]interface{})[index],
671 }
672 case val.Type().IsMapType():
673 elty := val.Type().ElementType()
674 if key.Type() == DynamicPseudoType {
675 return UnknownVal(elty)
676 }
677
678 if key.Type() != String {
679 panic("element key for map must be string")
680 }
681 if !key.IsKnown() {
682 return UnknownVal(elty)
683 }
684
685 if !val.IsKnown() {
686 return UnknownVal(elty)
687 }
688
689 keyStr := key.v.(string)
690
691 return Value{
692 ty: elty,
693 v: val.v.(map[string]interface{})[keyStr],
694 }
695 case val.Type().IsTupleType():
696 if key.Type() == DynamicPseudoType {
697 return DynamicVal
698 }
699
700 if key.Type() != Number {
701 panic("element key for tuple must be number")
702 }
703 if !key.IsKnown() {
704 return DynamicVal
705 }
706
707 index, accuracy := key.v.(*big.Float).Int64()
708 if accuracy != big.Exact || index < 0 {
709 panic("element key for list must be non-negative integer")
710 }
711
712 eltys := val.Type().TupleElementTypes()
713
714 if !val.IsKnown() {
715 return UnknownVal(eltys[index])
716 }
717
718 return Value{
719 ty: eltys[index],
720 v: val.v.([]interface{})[index],
721 }
722 default:
723 panic("not a list, map, or tuple type")
724 }
725 }
726
727 // HasIndex returns True if the receiver (which must be supported for Index)
728 // has an element with the given index key, or False if it does not.
729 //
730 // The result will be UnknownVal(Bool) if either the collection or the
731 // key value are unknown.
732 //
733 // This method will panic if the receiver is not indexable, but does not
734 // impose any panic-causing type constraints on the key.
735 func (val Value) HasIndex(key Value) Value {
736 if val.ty == DynamicPseudoType {
737 return UnknownVal(Bool)
738 }
739
740 switch {
741 case val.Type().IsListType():
742 if key.Type() == DynamicPseudoType {
743 return UnknownVal(Bool)
744 }
745
746 if key.Type() != Number {
747 return False
748 }
749 if !key.IsKnown() {
750 return UnknownVal(Bool)
751 }
752 if !val.IsKnown() {
753 return UnknownVal(Bool)
754 }
755
756 index, accuracy := key.v.(*big.Float).Int64()
757 if accuracy != big.Exact || index < 0 {
758 return False
759 }
760
761 return BoolVal(int(index) < len(val.v.([]interface{})) && index >= 0)
762 case val.Type().IsMapType():
763 if key.Type() == DynamicPseudoType {
764 return UnknownVal(Bool)
765 }
766
767 if key.Type() != String {
768 return False
769 }
770 if !key.IsKnown() {
771 return UnknownVal(Bool)
772 }
773 if !val.IsKnown() {
774 return UnknownVal(Bool)
775 }
776
777 keyStr := key.v.(string)
778 _, exists := val.v.(map[string]interface{})[keyStr]
779
780 return BoolVal(exists)
781 case val.Type().IsTupleType():
782 if key.Type() == DynamicPseudoType {
783 return UnknownVal(Bool)
784 }
785
786 if key.Type() != Number {
787 return False
788 }
789 if !key.IsKnown() {
790 return UnknownVal(Bool)
791 }
792
793 index, accuracy := key.v.(*big.Float).Int64()
794 if accuracy != big.Exact || index < 0 {
795 return False
796 }
797
798 length := val.Type().Length()
799 return BoolVal(int(index) < length && index >= 0)
800 default:
801 panic("not a list, map, or tuple type")
802 }
803 }
804
805 // HasElement returns True if the receiver (which must be of a set type)
806 // has the given value as an element, or False if it does not.
807 //
808 // The result will be UnknownVal(Bool) if either the set or the
809 // given value are unknown.
810 //
811 // This method will panic if the receiver is not a set, or if it is a null set.
812 func (val Value) HasElement(elem Value) Value {
813 ty := val.Type()
814
815 if !ty.IsSetType() {
816 panic("not a set type")
817 }
818 if !val.IsKnown() || !elem.IsKnown() {
819 return UnknownVal(Bool)
820 }
821 if val.IsNull() {
822 panic("can't call HasElement on a nil value")
823 }
824 if !ty.ElementType().Equals(elem.Type()) {
825 return False
826 }
827
828 s := val.v.(set.Set)
829 return BoolVal(s.Has(elem.v))
830 }
831
832 // Length returns the length of the receiver, which must be a collection type
833 // or tuple type, as a number value. If the receiver is not a compatible type
834 // then this method will panic.
835 //
836 // If the receiver is unknown then the result is also unknown.
837 //
838 // If the receiver is null then this function will panic.
839 //
840 // Note that Length is not supported for strings. To determine the length
841 // of a string, call AsString and take the length of the native Go string
842 // that is returned.
843 func (val Value) Length() Value {
844 if val.Type().IsTupleType() {
845 // For tuples, we can return the length even if the value is not known.
846 return NumberIntVal(int64(val.Type().Length()))
847 }
848
849 if !val.IsKnown() {
850 return UnknownVal(Number)
851 }
852
853 return NumberIntVal(int64(val.LengthInt()))
854 }
855
856 // LengthInt is like Length except it returns an int. It has the same behavior
857 // as Length except that it will panic if the receiver is unknown.
858 //
859 // This is an integration method provided for the convenience of code bridging
860 // into Go's type system.
861 func (val Value) LengthInt() int {
862 if val.Type().IsTupleType() {
863 // For tuples, we can return the length even if the value is not known.
864 return val.Type().Length()
865 }
866 if val.Type().IsObjectType() {
867 // For objects, the length is the number of attributes associated with the type.
868 return len(val.Type().AttributeTypes())
869 }
870 if !val.IsKnown() {
871 panic("value is not known")
872 }
873 if val.IsNull() {
874 panic("value is null")
875 }
876
877 switch {
878
879 case val.ty.IsListType():
880 return len(val.v.([]interface{}))
881
882 case val.ty.IsSetType():
883 return val.v.(set.Set).Length()
884
885 case val.ty.IsMapType():
886 return len(val.v.(map[string]interface{}))
887
888 default:
889 panic("value is not a collection")
890 }
891 }
892
893 // ElementIterator returns an ElementIterator for iterating the elements
894 // of the receiver, which must be a collection type, a tuple type, or an object
895 // type. If called on a method of any other type, this method will panic.
896 //
897 // The value must be Known and non-Null, or this method will panic.
898 //
899 // If the receiver is of a list type, the returned keys will be of type Number
900 // and the values will be of the list's element type.
901 //
902 // If the receiver is of a map type, the returned keys will be of type String
903 // and the value will be of the map's element type. Elements are passed in
904 // ascending lexicographical order by key.
905 //
906 // If the receiver is of a set type, each element is returned as both the
907 // key and the value, since set members are their own identity.
908 //
909 // If the receiver is of a tuple type, the returned keys will be of type Number
910 // and the value will be of the corresponding element's type.
911 //
912 // If the receiver is of an object type, the returned keys will be of type
913 // String and the value will be of the corresponding attributes's type.
914 //
915 // ElementIterator is an integration method, so it cannot handle Unknown
916 // values. This method will panic if the receiver is Unknown.
917 func (val Value) ElementIterator() ElementIterator {
918 if !val.IsKnown() {
919 panic("can't use ElementIterator on unknown value")
920 }
921 if val.IsNull() {
922 panic("can't use ElementIterator on null value")
923 }
924 return elementIterator(val)
925 }
926
927 // CanIterateElements returns true if the receiver can support the
928 // ElementIterator method (and by extension, ForEachElement) without panic.
929 func (val Value) CanIterateElements() bool {
930 return canElementIterator(val)
931 }
932
933 // ForEachElement executes a given callback function for each element of
934 // the receiver, which must be a collection type or tuple type, or this method
935 // will panic.
936 //
937 // ForEachElement uses ElementIterator internally, and so the values passed
938 // to the callback are as described for ElementIterator.
939 //
940 // Returns true if the iteration exited early due to the callback function
941 // returning true, or false if the loop ran to completion.
942 //
943 // ForEachElement is an integration method, so it cannot handle Unknown
944 // values. This method will panic if the receiver is Unknown.
945 func (val Value) ForEachElement(cb ElementCallback) bool {
946 it := val.ElementIterator()
947 for it.Next() {
948 key, val := it.Element()
949 stop := cb(key, val)
950 if stop {
951 return true
952 }
953 }
954 return false
955 }
956
957 // Not returns the logical inverse of the receiver, which must be of type
958 // Bool or this method will panic.
959 func (val Value) Not() Value {
960 if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil {
961 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
962 return *shortCircuit
963 }
964
965 return BoolVal(!val.v.(bool))
966 }
967
968 // And returns the result of logical AND with the receiver and the other given
969 // value, which must both be of type Bool or this method will panic.
970 func (val Value) And(other Value) Value {
971 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
972 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
973 return *shortCircuit
974 }
975
976 return BoolVal(val.v.(bool) && other.v.(bool))
977 }
978
979 // Or returns the result of logical OR with the receiver and the other given
980 // value, which must both be of type Bool or this method will panic.
981 func (val Value) Or(other Value) Value {
982 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
983 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
984 return *shortCircuit
985 }
986
987 return BoolVal(val.v.(bool) || other.v.(bool))
988 }
989
990 // LessThan returns True if the receiver is less than the other given value,
991 // which must both be numbers or this method will panic.
992 func (val Value) LessThan(other Value) Value {
993 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
994 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
995 return *shortCircuit
996 }
997
998 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0)
999 }
1000
1001 // GreaterThan returns True if the receiver is greater than the other given
1002 // value, which must both be numbers or this method will panic.
1003 func (val Value) GreaterThan(other Value) Value {
1004 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
1005 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1006 return *shortCircuit
1007 }
1008
1009 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0)
1010 }
1011
1012 // LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or.
1013 func (val Value) LessThanOrEqualTo(other Value) Value {
1014 return val.LessThan(other).Or(val.Equals(other))
1015 }
1016
1017 // GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or.
1018 func (val Value) GreaterThanOrEqualTo(other Value) Value {
1019 return val.GreaterThan(other).Or(val.Equals(other))
1020 }
1021
1022 // AsString returns the native string from a non-null, non-unknown cty.String
1023 // value, or panics if called on any other value.
1024 func (val Value) AsString() string {
1025 if val.ty != String {
1026 panic("not a string")
1027 }
1028 if val.IsNull() {
1029 panic("value is null")
1030 }
1031 if !val.IsKnown() {
1032 panic("value is unknown")
1033 }
1034
1035 return val.v.(string)
1036 }
1037
1038 // AsBigFloat returns a big.Float representation of a non-null, non-unknown
1039 // cty.Number value, or panics if called on any other value.
1040 //
1041 // For more convenient conversions to other native numeric types, use the
1042 // "gocty" package.
1043 func (val Value) AsBigFloat() *big.Float {
1044 if val.ty != Number {
1045 panic("not a number")
1046 }
1047 if val.IsNull() {
1048 panic("value is null")
1049 }
1050 if !val.IsKnown() {
1051 panic("value is unknown")
1052 }
1053
1054 // Copy the float so that callers can't mutate our internal state
1055 ret := *(val.v.(*big.Float))
1056
1057 return &ret
1058 }
1059
1060 // AsValueSlice returns a []cty.Value representation of a non-null, non-unknown
1061 // value of any type that CanIterateElements, or panics if called on
1062 // any other value.
1063 //
1064 // For more convenient conversions to slices of more specific types, use
1065 // the "gocty" package.
1066 func (val Value) AsValueSlice() []Value {
1067 l := val.LengthInt()
1068 if l == 0 {
1069 return nil
1070 }
1071
1072 ret := make([]Value, 0, l)
1073 for it := val.ElementIterator(); it.Next(); {
1074 _, v := it.Element()
1075 ret = append(ret, v)
1076 }
1077 return ret
1078 }
1079
1080 // AsValueMap returns a map[string]cty.Value representation of a non-null,
1081 // non-unknown value of any type that CanIterateElements, or panics if called
1082 // on any other value.
1083 //
1084 // For more convenient conversions to maps of more specific types, use
1085 // the "gocty" package.
1086 func (val Value) AsValueMap() map[string]Value {
1087 l := val.LengthInt()
1088 if l == 0 {
1089 return nil
1090 }
1091
1092 ret := make(map[string]Value, l)
1093 for it := val.ElementIterator(); it.Next(); {
1094 k, v := it.Element()
1095 ret[k.AsString()] = v
1096 }
1097 return ret
1098 }
1099
1100 // AsValueSet returns a ValueSet representation of a non-null,
1101 // non-unknown value of any collection type, or panics if called
1102 // on any other value.
1103 //
1104 // Unlike AsValueSlice and AsValueMap, this method requires specifically a
1105 // collection type (list, set or map) and does not allow structural types
1106 // (tuple or object), because the ValueSet type requires homogenous
1107 // element types.
1108 //
1109 // The returned ValueSet can store only values of the receiver's element type.
1110 func (val Value) AsValueSet() ValueSet {
1111 if !val.Type().IsCollectionType() {
1112 panic("not a collection type")
1113 }
1114
1115 // We don't give the caller our own set.Set (assuming we're a cty.Set value)
1116 // because then the caller could mutate our internals, which is forbidden.
1117 // Instead, we will construct a new set and append our elements into it.
1118 ret := NewValueSet(val.Type().ElementType())
1119 for it := val.ElementIterator(); it.Next(); {
1120 _, v := it.Element()
1121 ret.Add(v)
1122 }
1123 return ret
1124 }
1125
1126 // EncapsulatedValue returns the native value encapsulated in a non-null,
1127 // non-unknown capsule-typed value, or panics if called on any other value.
1128 //
1129 // The result is the same pointer that was passed to CapsuleVal to create
1130 // the value. Since cty considers values to be immutable, it is strongly
1131 // recommended to treat the encapsulated value itself as immutable too.
1132 func (val Value) EncapsulatedValue() interface{} {
1133 if !val.Type().IsCapsuleType() {
1134 panic("not a capsule-typed value")
1135 }
1136
1137 return val.v
1138 }