8 "github.com/zclconf/go-cty/cty/set"
11 // GoString is an implementation of fmt.GoStringer that produces concise
12 // source-like representations of values suitable for use in debug messages.
13 func (val Value) GoString() string {
19 return fmt.Sprintf("cty.NullVal(%#v)", val.ty)
21 if val == DynamicVal { // is unknown, so must be before the IsKnown check below
22 return "cty.DynamicVal"
25 return fmt.Sprintf("cty.UnknownVal(%#v)", val.ty)
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.
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.
43 return fmt.Sprintf("cty.NumberIntVal(%#v)", fv)
45 if rfv, accuracy := fv.Float64(); accuracy == big.Exact {
46 return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv)
48 return fmt.Sprintf("cty.MustParseNumberVal(%q)", fv.Text('f', -1))
50 return fmt.Sprintf("cty.StringVal(%#v)", val.v)
54 case val.ty.IsSetType():
55 vals := val.AsValueSlice()
57 return fmt.Sprintf("cty.SetValEmpty(%#v)", val.ty.ElementType())
59 return fmt.Sprintf("cty.SetVal(%#v)", vals)
60 case val.ty.IsListType():
61 vals := val.AsValueSlice()
63 return fmt.Sprintf("cty.ListValEmpty(%#v)", val.ty.ElementType())
65 return fmt.Sprintf("cty.ListVal(%#v)", vals)
66 case val.ty.IsMapType():
67 vals := val.AsValueMap()
69 return fmt.Sprintf("cty.MapValEmpty(%#v)", val.ty.ElementType())
71 return fmt.Sprintf("cty.MapVal(%#v)", vals)
72 case val.ty.IsTupleType():
73 if val.ty.Equals(EmptyTuple) {
74 return "cty.EmptyTupleVal"
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"
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)
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)
93 // Equals returns True if the receiver and the given other value have the
94 // same type and are exactly equal in value.
96 // As a special case, two null values are always equal regardless of type.
98 // The usual short-circuit rules apply, so the result will be unknown if
99 // either of the given values are.
101 // Use RawEquals to compare if two values are equal *ignoring* the
102 // short-circuit rules and the exception for null values.
103 func (val Value) Equals(other Value) Value {
104 // Start by handling Unknown values before considering types.
105 // This needs to be done since Null values are always equal regardless of
108 case !val.IsKnown() && !other.IsKnown():
110 return UnknownVal(Bool)
111 case val.IsKnown() && !other.IsKnown():
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.
124 return UnknownVal(Bool)
126 case other.IsKnown() && !val.IsKnown():
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.
139 return UnknownVal(Bool)
144 case val.IsNull() && other.IsNull():
145 // Nulls are always equal, regardless of type
147 case val.IsNull() || other.IsNull():
148 // If only one is null then the result must be false
149 return BoolVal(false)
152 if val.ty.HasDynamicTypes() || other.ty.HasDynamicTypes() {
153 return UnknownVal(Bool)
156 if !val.ty.Equals(other.ty) {
157 return BoolVal(false)
165 result = val.v.(*big.Float).Cmp(other.v.(*big.Float)) == 0
167 result = val.v.(bool) == other.v.(bool)
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)
176 for attr, aty := range oty.AttrTypes {
179 v: val.v.(map[string]interface{})[attr],
183 v: other.v.(map[string]interface{})[attr],
185 eq := lhs.Equals(rhs)
187 return UnknownVal(Bool)
194 case ty.IsTupleType():
195 tty := ty.typeImpl.(typeTuple)
197 for i, ety := range tty.ElemTypes {
200 v: val.v.([]interface{})[i],
204 v: other.v.([]interface{})[i],
206 eq := lhs.Equals(rhs)
208 return UnknownVal(Bool)
215 case ty.IsListType():
216 ety := ty.typeImpl.(typeList).ElementTypeT
217 if len(val.v.([]interface{})) == len(other.v.([]interface{})) {
219 for i := range val.v.([]interface{}) {
222 v: val.v.([]interface{})[i],
226 v: other.v.([]interface{})[i],
228 eq := lhs.Equals(rhs)
230 return UnknownVal(Bool)
239 s1 := val.v.(set.Set)
240 s2 := other.v.(set.Set)
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.
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{}) {
256 s2.EachValue(func(v interface{}) {
264 ety := ty.typeImpl.(typeMap).ElementTypeT
265 if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) {
267 for k := range val.v.(map[string]interface{}) {
268 if _, ok := other.v.(map[string]interface{})[k]; !ok {
274 v: val.v.(map[string]interface{})[k],
278 v: other.v.(map[string]interface{})[k],
280 eq := lhs.Equals(rhs)
282 return UnknownVal(Bool)
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
294 return BoolVal(val.v == other.v)
297 // should never happen
298 panic(fmt.Errorf("unsupported value type %#v in Equals", ty))
301 return BoolVal(result)
304 // NotEqual is a shorthand for Equals followed by Not.
305 func (val Value) NotEqual(other Value) Value {
306 return val.Equals(other).Not()
309 // True returns true if the receiver is True, false if False, and panics if
310 // the receiver is not of type Bool.
312 // This is a helper function to help write application logic that works with
313 // values, rather than a first-class operation. It does not work with unknown
314 // or null values. For more robust handling with unknown value
315 // short-circuiting, use val.Equals(cty.True).
316 func (val Value) True() bool {
320 return val.Equals(True).v.(bool)
323 // False is the opposite of True.
324 func (val Value) False() bool {
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.
332 // This method is more appropriate for testing than for real use, since it
333 // skips over usual semantics around unknowns but as a consequence allows
334 // testing the result of another operation that is expected to return unknown.
335 // It returns a primitive Go bool rather than a Value to remind us that it
336 // is not a first-class value operation.
337 func (val Value) RawEquals(other Value) bool {
338 if !val.ty.Equals(other.ty) {
341 if (!val.IsKnown()) && (!other.IsKnown()) {
344 if (val.IsKnown() && !other.IsKnown()) || (other.IsKnown() && !val.IsKnown()) {
347 if val.IsNull() && other.IsNull() {
350 if (val.IsNull() && !other.IsNull()) || (other.IsNull() && !val.IsNull()) {
353 if val.ty == DynamicPseudoType && other.ty == DynamicPseudoType {
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 {
366 v: val.v.(map[string]interface{})[attr],
370 v: other.v.(map[string]interface{})[attr],
372 eq := lhs.RawEquals(rhs)
378 case ty.IsTupleType():
379 tty := ty.typeImpl.(typeTuple)
380 for i, ety := range tty.ElemTypes {
383 v: val.v.([]interface{})[i],
387 v: other.v.([]interface{})[i],
389 eq := lhs.RawEquals(rhs)
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{}) {
401 v: val.v.([]interface{})[i],
405 v: other.v.([]interface{})[i],
407 eq := lhs.RawEquals(rhs)
416 s1 := val.v.(set.Set)
417 s2 := other.v.(set.Set)
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)
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 {
436 v: val.v.(map[string]interface{})[k],
440 v: other.v.(map[string]interface{})[k],
442 eq := lhs.RawEquals(rhs)
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
454 return val.v == other.v
457 // should never happen
458 panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty))
462 // Add returns the sum of the receiver and the given other value. Both values
463 // must be numbers; this method will panic if not.
464 func (val Value) Add(other Value) Value {
465 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
466 shortCircuit = forceShortCircuitType(shortCircuit, Number)
470 ret := new(big.Float)
471 ret.Add(val.v.(*big.Float), other.v.(*big.Float))
472 return NumberVal(ret)
475 // Subtract returns receiver minus the given other value. Both values must be
476 // numbers; this method will panic if not.
477 func (val Value) Subtract(other Value) Value {
478 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
479 shortCircuit = forceShortCircuitType(shortCircuit, Number)
483 return val.Add(other.Negate())
486 // Negate returns the numeric negative of the receiver, which must be a number.
487 // This method will panic when given a value of any other type.
488 func (val Value) Negate() Value {
489 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
490 shortCircuit = forceShortCircuitType(shortCircuit, Number)
494 ret := new(big.Float).Neg(val.v.(*big.Float))
495 return NumberVal(ret)
498 // Multiply returns the product of the receiver and the given other value.
499 // Both values must be numbers; this method will panic if not.
500 func (val Value) Multiply(other Value) Value {
501 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
502 shortCircuit = forceShortCircuitType(shortCircuit, Number)
506 ret := new(big.Float)
507 ret.Mul(val.v.(*big.Float), other.v.(*big.Float))
508 return NumberVal(ret)
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.
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.
520 // If both values are zero or infinity, this function will panic with
521 // an instance of big.ErrNaN.
522 func (val Value) Divide(other Value) Value {
523 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
524 shortCircuit = forceShortCircuitType(shortCircuit, Number)
528 ret := new(big.Float)
529 ret.Quo(val.v.(*big.Float), other.v.(*big.Float))
530 return NumberVal(ret)
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
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.
543 // This operation is primarily here for use with nonzero natural numbers.
544 // Modulo with "other" as a non-natural number gets somewhat philosophical,
545 // and this function takes a position on what that should mean, but callers
546 // may wish to disallow such things outright or implement their own modulo
547 // if they disagree with the interpretation used here.
548 func (val Value) Modulo(other Value) Value {
549 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
550 shortCircuit = forceShortCircuitType(shortCircuit, Number)
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)
560 if other.RawEquals(Zero) {
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)
573 return NumberVal(work)
576 // Absolute returns the absolute (signless) value of the receiver, which must
577 // be a number or this method will panic.
578 func (val Value) Absolute() Value {
579 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
580 shortCircuit = forceShortCircuitType(shortCircuit, Number)
584 ret := (&big.Float{}).Abs(val.v.(*big.Float))
585 return NumberVal(ret)
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.
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.
596 // This method may be called on a value whose type is DynamicPseudoType,
597 // in which case the result will also be DynamicVal.
598 func (val Value) GetAttr(name string) Value {
599 if val.ty == DynamicPseudoType {
603 if !val.ty.IsObjectType() {
604 panic("value is not an object")
607 name = NormalizeString(name)
608 if !val.ty.HasAttribute(name) {
609 panic("value has no attribute of that name")
612 attrType := val.ty.AttributeType(name)
615 return UnknownVal(attrType)
620 v: val.v.(map[string]interface{})[name],
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.
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.
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.
638 // This method may be called on a value whose type is DynamicPseudoType,
639 // in which case the result will also be the DynamicValue.
640 func (val Value) Index(key Value) Value {
641 if val.ty == DynamicPseudoType {
646 case val.Type().IsListType():
647 elty := val.Type().ElementType()
648 if key.Type() == DynamicPseudoType {
649 return UnknownVal(elty)
652 if key.Type() != Number {
653 panic("element key for list must be number")
656 return UnknownVal(elty)
660 return UnknownVal(elty)
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")
670 v: val.v.([]interface{})[index],
672 case val.Type().IsMapType():
673 elty := val.Type().ElementType()
674 if key.Type() == DynamicPseudoType {
675 return UnknownVal(elty)
678 if key.Type() != String {
679 panic("element key for map must be string")
682 return UnknownVal(elty)
686 return UnknownVal(elty)
689 keyStr := key.v.(string)
693 v: val.v.(map[string]interface{})[keyStr],
695 case val.Type().IsTupleType():
696 if key.Type() == DynamicPseudoType {
700 if key.Type() != Number {
701 panic("element key for tuple must be number")
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")
712 eltys := val.Type().TupleElementTypes()
715 return UnknownVal(eltys[index])
720 v: val.v.([]interface{})[index],
723 panic("not a list, map, or tuple type")
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.
730 // The result will be UnknownVal(Bool) if either the collection or the
731 // key value are unknown.
733 // This method will panic if the receiver is not indexable, but does not
734 // impose any panic-causing type constraints on the key.
735 func (val Value) HasIndex(key Value) Value {
736 if val.ty == DynamicPseudoType {
737 return UnknownVal(Bool)
741 case val.Type().IsListType():
742 if key.Type() == DynamicPseudoType {
743 return UnknownVal(Bool)
746 if key.Type() != Number {
750 return UnknownVal(Bool)
753 return UnknownVal(Bool)
756 index, accuracy := key.v.(*big.Float).Int64()
757 if accuracy != big.Exact || index < 0 {
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)
767 if key.Type() != String {
771 return UnknownVal(Bool)
774 return UnknownVal(Bool)
777 keyStr := key.v.(string)
778 _, exists := val.v.(map[string]interface{})[keyStr]
780 return BoolVal(exists)
781 case val.Type().IsTupleType():
782 if key.Type() == DynamicPseudoType {
783 return UnknownVal(Bool)
786 if key.Type() != Number {
790 return UnknownVal(Bool)
793 index, accuracy := key.v.(*big.Float).Int64()
794 if accuracy != big.Exact || index < 0 {
798 length := val.Type().Length()
799 return BoolVal(int(index) < length && index >= 0)
801 panic("not a list, map, or tuple type")
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.
808 // The result will be UnknownVal(Bool) if either the set or the
809 // given value are unknown.
811 // This method will panic if the receiver is not a set, or if it is a null set.
812 func (val Value) HasElement(elem Value) Value {
816 panic("not a set type")
818 if !val.IsKnown() || !elem.IsKnown() {
819 return UnknownVal(Bool)
822 panic("can't call HasElement on a nil value")
824 if !ty.ElementType().Equals(elem.Type()) {
829 return BoolVal(s.Has(elem.v))
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.
836 // If the receiver is unknown then the result is also unknown.
838 // If the receiver is null then this function will panic.
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
843 func (val Value) Length() Value {
844 if val.Type().IsTupleType() {
845 // For tuples, we can return the length even if the value is not known.
846 return NumberIntVal(int64(val.Type().Length()))
850 return UnknownVal(Number)
853 return NumberIntVal(int64(val.LengthInt()))
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.
859 // This is an integration method provided for the convenience of code bridging
860 // into Go's type system.
861 func (val Value) LengthInt() int {
862 if val.Type().IsTupleType() {
863 // For tuples, we can return the length even if the value is not known.
864 return val.Type().Length()
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())
871 panic("value is not known")
874 panic("value is null")
879 case val.ty.IsListType():
880 return len(val.v.([]interface{}))
882 case val.ty.IsSetType():
883 return val.v.(set.Set).Length()
885 case val.ty.IsMapType():
886 return len(val.v.(map[string]interface{}))
889 panic("value is not a collection")
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.
897 // The value must be Known and non-Null, or this method will panic.
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.
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.
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.
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.
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.
915 // ElementIterator is an integration method, so it cannot handle Unknown
916 // values. This method will panic if the receiver is Unknown.
917 func (val Value) ElementIterator() ElementIterator {
919 panic("can't use ElementIterator on unknown value")
922 panic("can't use ElementIterator on null value")
924 return elementIterator(val)
927 // CanIterateElements returns true if the receiver can support the
928 // ElementIterator method (and by extension, ForEachElement) without panic.
929 func (val Value) CanIterateElements() bool {
930 return canElementIterator(val)
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
937 // ForEachElement uses ElementIterator internally, and so the values passed
938 // to the callback are as described for ElementIterator.
940 // Returns true if the iteration exited early due to the callback function
941 // returning true, or false if the loop ran to completion.
943 // ForEachElement is an integration method, so it cannot handle Unknown
944 // values. This method will panic if the receiver is Unknown.
945 func (val Value) ForEachElement(cb ElementCallback) bool {
946 it := val.ElementIterator()
948 key, val := it.Element()
957 // Not returns the logical inverse of the receiver, which must be of type
958 // Bool or this method will panic.
959 func (val Value) Not() Value {
960 if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil {
961 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
965 return BoolVal(!val.v.(bool))
968 // And returns the result of logical AND with the receiver and the other given
969 // value, which must both be of type Bool or this method will panic.
970 func (val Value) And(other Value) Value {
971 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
972 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
976 return BoolVal(val.v.(bool) && other.v.(bool))
979 // Or returns the result of logical OR with the receiver and the other given
980 // value, which must both be of type Bool or this method will panic.
981 func (val Value) Or(other Value) Value {
982 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
983 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
987 return BoolVal(val.v.(bool) || other.v.(bool))
990 // LessThan returns True if the receiver is less than the other given value,
991 // which must both be numbers or this method will panic.
992 func (val Value) LessThan(other Value) Value {
993 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
994 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
998 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0)
1001 // GreaterThan returns True if the receiver is greater than the other given
1002 // value, which must both be numbers or this method will panic.
1003 func (val Value) GreaterThan(other Value) Value {
1004 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
1005 shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1006 return *shortCircuit
1009 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0)
1012 // LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or.
1013 func (val Value) LessThanOrEqualTo(other Value) Value {
1014 return val.LessThan(other).Or(val.Equals(other))
1017 // GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or.
1018 func (val Value) GreaterThanOrEqualTo(other Value) Value {
1019 return val.GreaterThan(other).Or(val.Equals(other))
1022 // AsString returns the native string from a non-null, non-unknown cty.String
1023 // value, or panics if called on any other value.
1024 func (val Value) AsString() string {
1025 if val.ty != String {
1026 panic("not a string")
1029 panic("value is null")
1032 panic("value is unknown")
1035 return val.v.(string)
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.
1041 // For more convenient conversions to other native numeric types, use the
1043 func (val Value) AsBigFloat() *big.Float {
1044 if val.ty != Number {
1045 panic("not a number")
1048 panic("value is null")
1051 panic("value is unknown")
1054 // Copy the float so that callers can't mutate our internal state
1055 ret := *(val.v.(*big.Float))
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
1064 // For more convenient conversions to slices of more specific types, use
1065 // the "gocty" package.
1066 func (val Value) AsValueSlice() []Value {
1067 l := val.LengthInt()
1072 ret := make([]Value, 0, l)
1073 for it := val.ElementIterator(); it.Next(); {
1074 _, v := it.Element()
1075 ret = append(ret, v)
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.
1084 // For more convenient conversions to maps of more specific types, use
1085 // the "gocty" package.
1086 func (val Value) AsValueMap() map[string]Value {
1087 l := val.LengthInt()
1092 ret := make(map[string]Value, l)
1093 for it := val.ElementIterator(); it.Next(); {
1094 k, v := it.Element()
1095 ret[k.AsString()] = v
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.
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
1109 // The returned ValueSet can store only values of the receiver's element type.
1110 func (val Value) AsValueSet() ValueSet {
1111 if !val.Type().IsCollectionType() {
1112 panic("not a collection type")
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()
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.
1129 // The result is the same pointer that was passed to CapsuleVal to create
1130 // the value. Since cty considers values to be immutable, it is strongly
1131 // recommended to treat the encapsulated value itself as immutable too.
1132 func (val Value) EncapsulatedValue() interface{} {
1133 if !val.Type().IsCapsuleType() {
1134 panic("not a capsule-typed value")