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