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