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