1package cty
2
3import (
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.
13func (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.
103func (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.
305func (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).
316func (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.
324func (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.
337func (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.
464func (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.
477func (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.
488func (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.
500func (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.
522func (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.
548func (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.
578func (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.
598func (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.
640func (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.
735func (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.
812func (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.
843func (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.
861func (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.
917func (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.
929func (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.
945func (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.
959func (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.
970func (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.
981func (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.
992func (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.
1003func (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.
1013func (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.
1018func (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.
1024func (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.
1043func (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.
1066func (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.
1086func (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.
1110func (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.
1132func (val Value) EncapsulatedValue() interface{} {
1133	if !val.Type().IsCapsuleType() {
1134		panic("not a capsule-typed value")
1135	}
1136
1137	return val.v
1138}
1139