1package cty 2 3import ( 4 "fmt" 5 "math/big" 6 7 "github.com/zclconf/go-cty/cty/set" 8) 9 10// GoString is an implementation of fmt.GoStringer that produces concise 11// source-like representations of values suitable for use in debug messages. 12func (val Value) GoString() string { 13 if val.IsMarked() { 14 unVal, marks := val.Unmark() 15 if len(marks) == 1 { 16 var mark interface{} 17 for m := range marks { 18 mark = m 19 } 20 return fmt.Sprintf("%#v.Mark(%#v)", unVal, mark) 21 } 22 return fmt.Sprintf("%#v.WithMarks(%#v)", unVal, marks) 23 } 24 25 if val == NilVal { 26 return "cty.NilVal" 27 } 28 29 if val.IsNull() { 30 return fmt.Sprintf("cty.NullVal(%#v)", val.ty) 31 } 32 if val == DynamicVal { // is unknown, so must be before the IsKnown check below 33 return "cty.DynamicVal" 34 } 35 if !val.IsKnown() { 36 return fmt.Sprintf("cty.UnknownVal(%#v)", val.ty) 37 } 38 39 // By the time we reach here we've dealt with all of the exceptions around 40 // unknowns and nulls, so we're guaranteed that the values are the 41 // canonical internal representation of the given type. 42 43 switch val.ty { 44 case Bool: 45 if val.v.(bool) { 46 return "cty.True" 47 } 48 return "cty.False" 49 case Number: 50 fv := val.v.(*big.Float) 51 // We'll try to use NumberIntVal or NumberFloatVal if we can, since 52 // the fully-general initializer call is pretty ugly-looking. 53 if fv.IsInt() { 54 return fmt.Sprintf("cty.NumberIntVal(%#v)", fv) 55 } 56 if rfv, accuracy := fv.Float64(); accuracy == big.Exact { 57 return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv) 58 } 59 return fmt.Sprintf("cty.MustParseNumberVal(%q)", fv.Text('f', -1)) 60 case String: 61 return fmt.Sprintf("cty.StringVal(%#v)", val.v) 62 } 63 64 switch { 65 case val.ty.IsSetType(): 66 vals := val.AsValueSlice() 67 if len(vals) == 0 { 68 return fmt.Sprintf("cty.SetValEmpty(%#v)", val.ty.ElementType()) 69 } 70 return fmt.Sprintf("cty.SetVal(%#v)", vals) 71 case val.ty.IsListType(): 72 vals := val.AsValueSlice() 73 if len(vals) == 0 { 74 return fmt.Sprintf("cty.ListValEmpty(%#v)", val.ty.ElementType()) 75 } 76 return fmt.Sprintf("cty.ListVal(%#v)", vals) 77 case val.ty.IsMapType(): 78 vals := val.AsValueMap() 79 if len(vals) == 0 { 80 return fmt.Sprintf("cty.MapValEmpty(%#v)", val.ty.ElementType()) 81 } 82 return fmt.Sprintf("cty.MapVal(%#v)", vals) 83 case val.ty.IsTupleType(): 84 if val.ty.Equals(EmptyTuple) { 85 return "cty.EmptyTupleVal" 86 } 87 vals := val.AsValueSlice() 88 return fmt.Sprintf("cty.TupleVal(%#v)", vals) 89 case val.ty.IsObjectType(): 90 if val.ty.Equals(EmptyObject) { 91 return "cty.EmptyObjectVal" 92 } 93 vals := val.AsValueMap() 94 return fmt.Sprintf("cty.ObjectVal(%#v)", vals) 95 case val.ty.IsCapsuleType(): 96 impl := val.ty.CapsuleOps().GoString 97 if impl == nil { 98 return fmt.Sprintf("cty.CapsuleVal(%#v, %#v)", val.ty, val.v) 99 } 100 return impl(val.EncapsulatedValue()) 101 } 102 103 // Default exposes implementation details, so should actually cover 104 // all of the cases above for good caller UX. 105 return fmt.Sprintf("cty.Value{ty: %#v, v: %#v}", val.ty, val.v) 106} 107 108// Equals returns True if the receiver and the given other value have the 109// same type and are exactly equal in value. 110// 111// As a special case, two null values are always equal regardless of type. 112// 113// The usual short-circuit rules apply, so the result will be unknown if 114// either of the given values are. 115// 116// Use RawEquals to compare if two values are equal *ignoring* the 117// short-circuit rules and the exception for null values. 118func (val Value) Equals(other Value) Value { 119 if val.IsMarked() || other.IsMarked() { 120 val, valMarks := val.Unmark() 121 other, otherMarks := other.Unmark() 122 return val.Equals(other).WithMarks(valMarks, otherMarks) 123 } 124 125 // Start by handling Unknown values before considering types. 126 // This needs to be done since Null values are always equal regardless of 127 // type. 128 switch { 129 case !val.IsKnown() && !other.IsKnown(): 130 // both unknown 131 return UnknownVal(Bool) 132 case val.IsKnown() && !other.IsKnown(): 133 switch { 134 case val.IsNull(), other.ty.HasDynamicTypes(): 135 // If known is Null, we need to wait for the unknown value since 136 // nulls of any type are equal. 137 // An unknown with a dynamic type compares as unknown, which we need 138 // to check before the type comparison below. 139 return UnknownVal(Bool) 140 case !val.ty.Equals(other.ty): 141 // There is no null comparison or dynamic types, so unequal types 142 // will never be equal. 143 return False 144 default: 145 return UnknownVal(Bool) 146 } 147 case other.IsKnown() && !val.IsKnown(): 148 switch { 149 case other.IsNull(), val.ty.HasDynamicTypes(): 150 // If known is Null, we need to wait for the unknown value since 151 // nulls of any type are equal. 152 // An unknown with a dynamic type compares as unknown, which we need 153 // to check before the type comparison below. 154 return UnknownVal(Bool) 155 case !other.ty.Equals(val.ty): 156 // There's no null comparison or dynamic types, so unequal types 157 // will never be equal. 158 return False 159 default: 160 return UnknownVal(Bool) 161 } 162 } 163 164 switch { 165 case val.IsNull() && other.IsNull(): 166 // Nulls are always equal, regardless of type 167 return BoolVal(true) 168 case val.IsNull() || other.IsNull(): 169 // If only one is null then the result must be false 170 return BoolVal(false) 171 } 172 173 // Check if there are any nested dynamic values making this comparison 174 // unknown. 175 if !val.HasWhollyKnownType() || !other.HasWhollyKnownType() { 176 // Even if we have dynamic values, we can still determine inequality if 177 // there is no way the types could later conform. 178 if val.ty.TestConformance(other.ty) != nil && other.ty.TestConformance(val.ty) != nil { 179 return BoolVal(false) 180 } 181 182 return UnknownVal(Bool) 183 } 184 185 if !val.ty.Equals(other.ty) { 186 return BoolVal(false) 187 } 188 189 ty := val.ty 190 result := false 191 192 switch { 193 case ty == Number: 194 result = val.v.(*big.Float).Cmp(other.v.(*big.Float)) == 0 195 case ty == Bool: 196 result = val.v.(bool) == other.v.(bool) 197 case ty == String: 198 // Simple equality is safe because we NFC-normalize strings as they 199 // enter our world from StringVal, and so we can assume strings are 200 // always in normal form. 201 result = val.v.(string) == other.v.(string) 202 case ty.IsObjectType(): 203 oty := ty.typeImpl.(typeObject) 204 result = true 205 for attr, aty := range oty.AttrTypes { 206 lhs := Value{ 207 ty: aty, 208 v: val.v.(map[string]interface{})[attr], 209 } 210 rhs := Value{ 211 ty: aty, 212 v: other.v.(map[string]interface{})[attr], 213 } 214 eq := lhs.Equals(rhs) 215 if !eq.IsKnown() { 216 return UnknownVal(Bool) 217 } 218 if eq.False() { 219 result = false 220 break 221 } 222 } 223 case ty.IsTupleType(): 224 tty := ty.typeImpl.(typeTuple) 225 result = true 226 for i, ety := range tty.ElemTypes { 227 lhs := Value{ 228 ty: ety, 229 v: val.v.([]interface{})[i], 230 } 231 rhs := Value{ 232 ty: ety, 233 v: other.v.([]interface{})[i], 234 } 235 eq := lhs.Equals(rhs) 236 if !eq.IsKnown() { 237 return UnknownVal(Bool) 238 } 239 if eq.False() { 240 result = false 241 break 242 } 243 } 244 case ty.IsListType(): 245 ety := ty.typeImpl.(typeList).ElementTypeT 246 if len(val.v.([]interface{})) == len(other.v.([]interface{})) { 247 result = true 248 for i := range val.v.([]interface{}) { 249 lhs := Value{ 250 ty: ety, 251 v: val.v.([]interface{})[i], 252 } 253 rhs := Value{ 254 ty: ety, 255 v: other.v.([]interface{})[i], 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.IsSetType(): 268 s1 := val.v.(set.Set) 269 s2 := other.v.(set.Set) 270 equal := true 271 272 // Two sets are equal if all of their values are known and all values 273 // in one are also in the other. 274 for it := s1.Iterator(); it.Next(); { 275 rv := it.Value() 276 if rv == unknown { // "unknown" is the internal representation of unknown-ness 277 return UnknownVal(Bool) 278 } 279 if !s2.Has(rv) { 280 equal = false 281 } 282 } 283 for it := s2.Iterator(); it.Next(); { 284 rv := it.Value() 285 if rv == unknown { // "unknown" is the internal representation of unknown-ness 286 return UnknownVal(Bool) 287 } 288 if !s1.Has(rv) { 289 equal = false 290 } 291 } 292 293 result = equal 294 case ty.IsMapType(): 295 ety := ty.typeImpl.(typeMap).ElementTypeT 296 if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) { 297 result = true 298 for k := range val.v.(map[string]interface{}) { 299 if _, ok := other.v.(map[string]interface{})[k]; !ok { 300 result = false 301 break 302 } 303 lhs := Value{ 304 ty: ety, 305 v: val.v.(map[string]interface{})[k], 306 } 307 rhs := Value{ 308 ty: ety, 309 v: other.v.(map[string]interface{})[k], 310 } 311 eq := lhs.Equals(rhs) 312 if !eq.IsKnown() { 313 return UnknownVal(Bool) 314 } 315 if eq.False() { 316 result = false 317 break 318 } 319 } 320 } 321 case ty.IsCapsuleType(): 322 impl := val.ty.CapsuleOps().Equals 323 if impl == nil { 324 impl := val.ty.CapsuleOps().RawEquals 325 if impl == nil { 326 // A capsule type's encapsulated value is a pointer to a value of its 327 // native type, so we can just compare these to get the identity test 328 // we need. 329 return BoolVal(val.v == other.v) 330 } 331 return BoolVal(impl(val.v, other.v)) 332 } 333 ret := impl(val.v, other.v) 334 if !ret.Type().Equals(Bool) { 335 panic(fmt.Sprintf("Equals for %#v returned %#v, not cty.Bool", ty, ret.Type())) 336 } 337 return ret 338 339 default: 340 // should never happen 341 panic(fmt.Errorf("unsupported value type %#v in Equals", ty)) 342 } 343 344 return BoolVal(result) 345} 346 347// NotEqual is a shorthand for Equals followed by Not. 348func (val Value) NotEqual(other Value) Value { 349 return val.Equals(other).Not() 350} 351 352// True returns true if the receiver is True, false if False, and panics if 353// the receiver is not of type Bool. 354// 355// This is a helper function to help write application logic that works with 356// values, rather than a first-class operation. It does not work with unknown 357// or null values. For more robust handling with unknown value 358// short-circuiting, use val.Equals(cty.True). 359func (val Value) True() bool { 360 val.assertUnmarked() 361 if val.ty != Bool { 362 panic("not bool") 363 } 364 return val.Equals(True).v.(bool) 365} 366 367// False is the opposite of True. 368func (val Value) False() bool { 369 return !val.True() 370} 371 372// RawEquals returns true if and only if the two given values have the same 373// type and equal value, ignoring the usual short-circuit rules about 374// unknowns and dynamic types. 375// 376// This method is more appropriate for testing than for real use, since it 377// skips over usual semantics around unknowns but as a consequence allows 378// testing the result of another operation that is expected to return unknown. 379// It returns a primitive Go bool rather than a Value to remind us that it 380// is not a first-class value operation. 381func (val Value) RawEquals(other Value) bool { 382 if !val.ty.Equals(other.ty) { 383 return false 384 } 385 if !val.HasSameMarks(other) { 386 return false 387 } 388 // Since we've now checked the marks, we'll unmark for the rest of this... 389 val = val.unmarkForce() 390 other = other.unmarkForce() 391 392 if (!val.IsKnown()) && (!other.IsKnown()) { 393 return true 394 } 395 if (val.IsKnown() && !other.IsKnown()) || (other.IsKnown() && !val.IsKnown()) { 396 return false 397 } 398 if val.IsNull() && other.IsNull() { 399 return true 400 } 401 if (val.IsNull() && !other.IsNull()) || (other.IsNull() && !val.IsNull()) { 402 return false 403 } 404 if val.ty == DynamicPseudoType && other.ty == DynamicPseudoType { 405 return true 406 } 407 408 ty := val.ty 409 switch { 410 case ty == Number || ty == Bool || ty == String || ty == DynamicPseudoType: 411 return val.Equals(other).True() 412 case ty.IsObjectType(): 413 oty := ty.typeImpl.(typeObject) 414 for attr, aty := range oty.AttrTypes { 415 lhs := Value{ 416 ty: aty, 417 v: val.v.(map[string]interface{})[attr], 418 } 419 rhs := Value{ 420 ty: aty, 421 v: other.v.(map[string]interface{})[attr], 422 } 423 eq := lhs.RawEquals(rhs) 424 if !eq { 425 return false 426 } 427 } 428 return true 429 case ty.IsTupleType(): 430 tty := ty.typeImpl.(typeTuple) 431 for i, ety := range tty.ElemTypes { 432 lhs := Value{ 433 ty: ety, 434 v: val.v.([]interface{})[i], 435 } 436 rhs := Value{ 437 ty: ety, 438 v: other.v.([]interface{})[i], 439 } 440 eq := lhs.RawEquals(rhs) 441 if !eq { 442 return false 443 } 444 } 445 return true 446 case ty.IsListType(): 447 ety := ty.typeImpl.(typeList).ElementTypeT 448 if len(val.v.([]interface{})) == len(other.v.([]interface{})) { 449 for i := range val.v.([]interface{}) { 450 lhs := Value{ 451 ty: ety, 452 v: val.v.([]interface{})[i], 453 } 454 rhs := Value{ 455 ty: ety, 456 v: other.v.([]interface{})[i], 457 } 458 eq := lhs.RawEquals(rhs) 459 if !eq { 460 return false 461 } 462 } 463 return true 464 } 465 return false 466 467 case ty.IsSetType(): 468 // Convert the set values into a slice so that we can compare each 469 // value. This is safe because the underlying sets are ordered (see 470 // setRules in set_internals.go), and so the results are guaranteed to 471 // be in a consistent order for two equal sets 472 setList1 := val.AsValueSlice() 473 setList2 := other.AsValueSlice() 474 475 // If both physical sets have the same length and they have all of their 476 // _known_ values in common, we know that both sets also have the same 477 // number of unknown values. 478 if len(setList1) != len(setList2) { 479 return false 480 } 481 482 for i := range setList1 { 483 eq := setList1[i].RawEquals(setList2[i]) 484 if !eq { 485 return false 486 } 487 } 488 489 // If we got here without returning false already then our sets are 490 // equal enough for RawEquals purposes. 491 return true 492 493 case ty.IsMapType(): 494 ety := ty.typeImpl.(typeMap).ElementTypeT 495 if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) { 496 for k := range val.v.(map[string]interface{}) { 497 if _, ok := other.v.(map[string]interface{})[k]; !ok { 498 return false 499 } 500 lhs := Value{ 501 ty: ety, 502 v: val.v.(map[string]interface{})[k], 503 } 504 rhs := Value{ 505 ty: ety, 506 v: other.v.(map[string]interface{})[k], 507 } 508 eq := lhs.RawEquals(rhs) 509 if !eq { 510 return false 511 } 512 } 513 return true 514 } 515 return false 516 case ty.IsCapsuleType(): 517 impl := val.ty.CapsuleOps().RawEquals 518 if impl == nil { 519 // A capsule type's encapsulated value is a pointer to a value of its 520 // native type, so we can just compare these to get the identity test 521 // we need. 522 return val.v == other.v 523 } 524 return impl(val.v, other.v) 525 526 default: 527 // should never happen 528 panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty)) 529 } 530} 531 532// Add returns the sum of the receiver and the given other value. Both values 533// must be numbers; this method will panic if not. 534func (val Value) Add(other Value) Value { 535 if val.IsMarked() || other.IsMarked() { 536 val, valMarks := val.Unmark() 537 other, otherMarks := other.Unmark() 538 return val.Add(other).WithMarks(valMarks, otherMarks) 539 } 540 541 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 542 shortCircuit = forceShortCircuitType(shortCircuit, Number) 543 return *shortCircuit 544 } 545 546 ret := new(big.Float) 547 ret.Add(val.v.(*big.Float), other.v.(*big.Float)) 548 return NumberVal(ret) 549} 550 551// Subtract returns receiver minus the given other value. Both values must be 552// numbers; this method will panic if not. 553func (val Value) Subtract(other Value) Value { 554 if val.IsMarked() || other.IsMarked() { 555 val, valMarks := val.Unmark() 556 other, otherMarks := other.Unmark() 557 return val.Subtract(other).WithMarks(valMarks, otherMarks) 558 } 559 560 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 561 shortCircuit = forceShortCircuitType(shortCircuit, Number) 562 return *shortCircuit 563 } 564 565 return val.Add(other.Negate()) 566} 567 568// Negate returns the numeric negative of the receiver, which must be a number. 569// This method will panic when given a value of any other type. 570func (val Value) Negate() Value { 571 if val.IsMarked() { 572 val, valMarks := val.Unmark() 573 return val.Negate().WithMarks(valMarks) 574 } 575 576 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil { 577 shortCircuit = forceShortCircuitType(shortCircuit, Number) 578 return *shortCircuit 579 } 580 581 ret := new(big.Float).Neg(val.v.(*big.Float)) 582 return NumberVal(ret) 583} 584 585// Multiply returns the product of the receiver and the given other value. 586// Both values must be numbers; this method will panic if not. 587func (val Value) Multiply(other Value) Value { 588 if val.IsMarked() || other.IsMarked() { 589 val, valMarks := val.Unmark() 590 other, otherMarks := other.Unmark() 591 return val.Multiply(other).WithMarks(valMarks, otherMarks) 592 } 593 594 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 595 shortCircuit = forceShortCircuitType(shortCircuit, Number) 596 return *shortCircuit 597 } 598 599 // find the larger precision of the arguments 600 resPrec := val.v.(*big.Float).Prec() 601 otherPrec := other.v.(*big.Float).Prec() 602 if otherPrec > resPrec { 603 resPrec = otherPrec 604 } 605 606 // make sure we have enough precision for the product 607 ret := new(big.Float).SetPrec(512) 608 ret.Mul(val.v.(*big.Float), other.v.(*big.Float)) 609 610 // now reduce the precision back to the greater argument, or the minimum 611 // required by the product. 612 minPrec := ret.MinPrec() 613 if minPrec > resPrec { 614 resPrec = minPrec 615 } 616 ret.SetPrec(resPrec) 617 618 return NumberVal(ret) 619} 620 621// Divide returns the quotient of the receiver and the given other value. 622// Both values must be numbers; this method will panic if not. 623// 624// If the "other" value is exactly zero, this operation will return either 625// PositiveInfinity or NegativeInfinity, depending on the sign of the 626// receiver value. For some use-cases the presence of infinities may be 627// undesirable, in which case the caller should check whether the 628// other value equals zero before calling and raise an error instead. 629// 630// If both values are zero or infinity, this function will panic with 631// an instance of big.ErrNaN. 632func (val Value) Divide(other Value) Value { 633 if val.IsMarked() || other.IsMarked() { 634 val, valMarks := val.Unmark() 635 other, otherMarks := other.Unmark() 636 return val.Divide(other).WithMarks(valMarks, otherMarks) 637 } 638 639 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 640 shortCircuit = forceShortCircuitType(shortCircuit, Number) 641 return *shortCircuit 642 } 643 644 ret := new(big.Float) 645 ret.Quo(val.v.(*big.Float), other.v.(*big.Float)) 646 return NumberVal(ret) 647} 648 649// Modulo returns the remainder of an integer division of the receiver and 650// the given other value. Both values must be numbers; this method will panic 651// if not. 652// 653// If the "other" value is exactly zero, this operation will return either 654// PositiveInfinity or NegativeInfinity, depending on the sign of the 655// receiver value. For some use-cases the presence of infinities may be 656// undesirable, in which case the caller should check whether the 657// other value equals zero before calling and raise an error instead. 658// 659// This operation is primarily here for use with nonzero natural numbers. 660// Modulo with "other" as a non-natural number gets somewhat philosophical, 661// and this function takes a position on what that should mean, but callers 662// may wish to disallow such things outright or implement their own modulo 663// if they disagree with the interpretation used here. 664func (val Value) Modulo(other Value) Value { 665 if val.IsMarked() || other.IsMarked() { 666 val, valMarks := val.Unmark() 667 other, otherMarks := other.Unmark() 668 return val.Modulo(other).WithMarks(valMarks, otherMarks) 669 } 670 671 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 672 shortCircuit = forceShortCircuitType(shortCircuit, Number) 673 return *shortCircuit 674 } 675 676 // We cheat a bit here with infinities, just abusing the Multiply operation 677 // to get an infinite result of the correct sign. 678 if val == PositiveInfinity || val == NegativeInfinity || other == PositiveInfinity || other == NegativeInfinity { 679 return val.Multiply(other) 680 } 681 682 if other.RawEquals(Zero) { 683 return val 684 } 685 686 // FIXME: This is a bit clumsy. Should come back later and see if there's a 687 // more straightforward way to do this. 688 rat := val.Divide(other) 689 ratFloorInt, _ := rat.v.(*big.Float).Int(nil) 690 691 // start with a copy of the original larger value so that we do not lose 692 // precision. 693 v := val.v.(*big.Float) 694 work := new(big.Float).Copy(v).SetInt(ratFloorInt) 695 work.Mul(other.v.(*big.Float), work) 696 work.Sub(v, work) 697 698 return NumberVal(work) 699} 700 701// Absolute returns the absolute (signless) value of the receiver, which must 702// be a number or this method will panic. 703func (val Value) Absolute() Value { 704 if val.IsMarked() { 705 val, valMarks := val.Unmark() 706 return val.Absolute().WithMarks(valMarks) 707 } 708 709 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil { 710 shortCircuit = forceShortCircuitType(shortCircuit, Number) 711 return *shortCircuit 712 } 713 714 ret := (&big.Float{}).Abs(val.v.(*big.Float)) 715 return NumberVal(ret) 716} 717 718// GetAttr returns the value of the given attribute of the receiver, which 719// must be of an object type that has an attribute of the given name. 720// This method will panic if the receiver type is not compatible. 721// 722// The method will also panic if the given attribute name is not defined 723// for the value's type. Use the attribute-related methods on Type to 724// check for the validity of an attribute before trying to use it. 725// 726// This method may be called on a value whose type is DynamicPseudoType, 727// in which case the result will also be DynamicVal. 728func (val Value) GetAttr(name string) Value { 729 if val.IsMarked() { 730 val, valMarks := val.Unmark() 731 return val.GetAttr(name).WithMarks(valMarks) 732 } 733 734 if val.ty == DynamicPseudoType { 735 return DynamicVal 736 } 737 738 if !val.ty.IsObjectType() { 739 panic("value is not an object") 740 } 741 742 name = NormalizeString(name) 743 if !val.ty.HasAttribute(name) { 744 panic("value has no attribute of that name") 745 } 746 747 attrType := val.ty.AttributeType(name) 748 749 if !val.IsKnown() { 750 return UnknownVal(attrType) 751 } 752 753 return Value{ 754 ty: attrType, 755 v: val.v.(map[string]interface{})[name], 756 } 757} 758 759// Index returns the value of an element of the receiver, which must have 760// either a list, map or tuple type. This method will panic if the receiver 761// type is not compatible. 762// 763// The key value must be the correct type for the receving collection: a 764// number if the collection is a list or tuple, or a string if it is a map. 765// In the case of a list or tuple, the given number must be convertable to int 766// or this method will panic. The key may alternatively be of 767// DynamicPseudoType, in which case the result itself is an unknown of the 768// collection's element type. 769// 770// The result is of the receiver collection's element type, or in the case 771// of a tuple the type of the specific element index requested. 772// 773// This method may be called on a value whose type is DynamicPseudoType, 774// in which case the result will also be the DynamicValue. 775func (val Value) Index(key Value) Value { 776 if val.IsMarked() || key.IsMarked() { 777 val, valMarks := val.Unmark() 778 key, keyMarks := key.Unmark() 779 return val.Index(key).WithMarks(valMarks, keyMarks) 780 } 781 782 if val.ty == DynamicPseudoType { 783 return DynamicVal 784 } 785 786 switch { 787 case val.Type().IsListType(): 788 elty := val.Type().ElementType() 789 if key.Type() == DynamicPseudoType { 790 return UnknownVal(elty) 791 } 792 793 if key.Type() != Number { 794 panic("element key for list must be number") 795 } 796 if !key.IsKnown() { 797 return UnknownVal(elty) 798 } 799 800 if !val.IsKnown() { 801 return UnknownVal(elty) 802 } 803 804 index, accuracy := key.v.(*big.Float).Int64() 805 if accuracy != big.Exact || index < 0 { 806 panic("element key for list must be non-negative integer") 807 } 808 809 return Value{ 810 ty: elty, 811 v: val.v.([]interface{})[index], 812 } 813 case val.Type().IsMapType(): 814 elty := val.Type().ElementType() 815 if key.Type() == DynamicPseudoType { 816 return UnknownVal(elty) 817 } 818 819 if key.Type() != String { 820 panic("element key for map must be string") 821 } 822 if !key.IsKnown() { 823 return UnknownVal(elty) 824 } 825 826 if !val.IsKnown() { 827 return UnknownVal(elty) 828 } 829 830 keyStr := key.v.(string) 831 832 return Value{ 833 ty: elty, 834 v: val.v.(map[string]interface{})[keyStr], 835 } 836 case val.Type().IsTupleType(): 837 if key.Type() == DynamicPseudoType { 838 return DynamicVal 839 } 840 841 if key.Type() != Number { 842 panic("element key for tuple must be number") 843 } 844 if !key.IsKnown() { 845 return DynamicVal 846 } 847 848 index, accuracy := key.v.(*big.Float).Int64() 849 if accuracy != big.Exact || index < 0 { 850 panic("element key for list must be non-negative integer") 851 } 852 853 eltys := val.Type().TupleElementTypes() 854 855 if !val.IsKnown() { 856 return UnknownVal(eltys[index]) 857 } 858 859 return Value{ 860 ty: eltys[index], 861 v: val.v.([]interface{})[index], 862 } 863 default: 864 panic("not a list, map, or tuple type") 865 } 866} 867 868// HasIndex returns True if the receiver (which must be supported for Index) 869// has an element with the given index key, or False if it does not. 870// 871// The result will be UnknownVal(Bool) if either the collection or the 872// key value are unknown. 873// 874// This method will panic if the receiver is not indexable, but does not 875// impose any panic-causing type constraints on the key. 876func (val Value) HasIndex(key Value) Value { 877 if val.IsMarked() || key.IsMarked() { 878 val, valMarks := val.Unmark() 879 key, keyMarks := key.Unmark() 880 return val.HasIndex(key).WithMarks(valMarks, keyMarks) 881 } 882 883 if val.ty == DynamicPseudoType { 884 return UnknownVal(Bool) 885 } 886 887 switch { 888 case val.Type().IsListType(): 889 if key.Type() == DynamicPseudoType { 890 return UnknownVal(Bool) 891 } 892 893 if key.Type() != Number { 894 return False 895 } 896 if !key.IsKnown() { 897 return UnknownVal(Bool) 898 } 899 if !val.IsKnown() { 900 return UnknownVal(Bool) 901 } 902 903 index, accuracy := key.v.(*big.Float).Int64() 904 if accuracy != big.Exact || index < 0 { 905 return False 906 } 907 908 return BoolVal(int(index) < len(val.v.([]interface{})) && index >= 0) 909 case val.Type().IsMapType(): 910 if key.Type() == DynamicPseudoType { 911 return UnknownVal(Bool) 912 } 913 914 if key.Type() != String { 915 return False 916 } 917 if !key.IsKnown() { 918 return UnknownVal(Bool) 919 } 920 if !val.IsKnown() { 921 return UnknownVal(Bool) 922 } 923 924 keyStr := key.v.(string) 925 _, exists := val.v.(map[string]interface{})[keyStr] 926 927 return BoolVal(exists) 928 case val.Type().IsTupleType(): 929 if key.Type() == DynamicPseudoType { 930 return UnknownVal(Bool) 931 } 932 933 if key.Type() != Number { 934 return False 935 } 936 if !key.IsKnown() { 937 return UnknownVal(Bool) 938 } 939 940 index, accuracy := key.v.(*big.Float).Int64() 941 if accuracy != big.Exact || index < 0 { 942 return False 943 } 944 945 length := val.Type().Length() 946 return BoolVal(int(index) < length && index >= 0) 947 default: 948 panic("not a list, map, or tuple type") 949 } 950} 951 952// HasElement returns True if the receiver (which must be of a set type) 953// has the given value as an element, or False if it does not. 954// 955// The result will be UnknownVal(Bool) if either the set or the 956// given value are unknown. 957// 958// This method will panic if the receiver is not a set, or if it is a null set. 959func (val Value) HasElement(elem Value) Value { 960 if val.IsMarked() || elem.IsMarked() { 961 val, valMarks := val.Unmark() 962 elem, elemMarks := elem.Unmark() 963 return val.HasElement(elem).WithMarks(valMarks, elemMarks) 964 } 965 966 ty := val.Type() 967 968 if !ty.IsSetType() { 969 panic("not a set type") 970 } 971 if !val.IsKnown() || !elem.IsKnown() { 972 return UnknownVal(Bool) 973 } 974 if val.IsNull() { 975 panic("can't call HasElement on a nil value") 976 } 977 if !ty.ElementType().Equals(elem.Type()) { 978 return False 979 } 980 981 s := val.v.(set.Set) 982 return BoolVal(s.Has(elem.v)) 983} 984 985// Length returns the length of the receiver, which must be a collection type 986// or tuple type, as a number value. If the receiver is not a compatible type 987// then this method will panic. 988// 989// If the receiver is unknown then the result is also unknown. 990// 991// If the receiver is null then this function will panic. 992// 993// Note that Length is not supported for strings. To determine the length 994// of a string, use the Length function in funcs/stdlib. 995func (val Value) Length() Value { 996 if val.IsMarked() { 997 val, valMarks := val.Unmark() 998 return val.Length().WithMarks(valMarks) 999 } 1000 1001 if val.Type().IsTupleType() { 1002 // For tuples, we can return the length even if the value is not known. 1003 return NumberIntVal(int64(val.Type().Length())) 1004 } 1005 1006 if !val.IsKnown() { 1007 return UnknownVal(Number) 1008 } 1009 if val.Type().IsSetType() { 1010 // The Length rules are a little different for sets because if any 1011 // unknown values are present then the values they are standing in for 1012 // may or may not be equal to other elements in the set, and thus they 1013 // may or may not coalesce with other elements and produce fewer 1014 // items in the resulting set. 1015 storeLength := int64(val.v.(set.Set).Length()) 1016 if storeLength == 1 || val.IsWhollyKnown() { 1017 // If our set is wholly known then we know its length. 1018 // 1019 // We also know the length if the physical store has only one 1020 // element, even if that element is unknown, because there's 1021 // nothing else in the set for it to coalesce with and a single 1022 // unknown value cannot represent more than one known value. 1023 return NumberIntVal(storeLength) 1024 } 1025 // Otherwise, we cannot predict the length. 1026 return UnknownVal(Number) 1027 } 1028 1029 return NumberIntVal(int64(val.LengthInt())) 1030} 1031 1032// LengthInt is like Length except it returns an int. It has the same behavior 1033// as Length except that it will panic if the receiver is unknown. 1034// 1035// This is an integration method provided for the convenience of code bridging 1036// into Go's type system. 1037// 1038// For backward compatibility with an earlier implementation error, LengthInt's 1039// result can disagree with Length's result for any set containing unknown 1040// values. Length can potentially indicate the set's length is unknown in that 1041// case, whereas LengthInt will return the maximum possible length as if the 1042// unknown values were each a placeholder for a value not equal to any other 1043// value in the set. 1044func (val Value) LengthInt() int { 1045 val.assertUnmarked() 1046 if val.Type().IsTupleType() { 1047 // For tuples, we can return the length even if the value is not known. 1048 return val.Type().Length() 1049 } 1050 if val.Type().IsObjectType() { 1051 // For objects, the length is the number of attributes associated with the type. 1052 return len(val.Type().AttributeTypes()) 1053 } 1054 if !val.IsKnown() { 1055 panic("value is not known") 1056 } 1057 if val.IsNull() { 1058 panic("value is null") 1059 } 1060 1061 switch { 1062 1063 case val.ty.IsListType(): 1064 return len(val.v.([]interface{})) 1065 1066 case val.ty.IsSetType(): 1067 // NOTE: This is technically not correct in cases where the set 1068 // contains unknown values, because in that case we can't know how 1069 // many known values those unknown values are standing in for -- they 1070 // might coalesce with other values once known. 1071 // 1072 // However, this incorrect behavior is preserved for backward 1073 // compatibility with callers that were relying on LengthInt rather 1074 // than calling Length. Instead of panicking when a set contains an 1075 // unknown value, LengthInt returns the largest possible length. 1076 return val.v.(set.Set).Length() 1077 1078 case val.ty.IsMapType(): 1079 return len(val.v.(map[string]interface{})) 1080 1081 default: 1082 panic("value is not a collection") 1083 } 1084} 1085 1086// ElementIterator returns an ElementIterator for iterating the elements 1087// of the receiver, which must be a collection type, a tuple type, or an object 1088// type. If called on a method of any other type, this method will panic. 1089// 1090// The value must be Known and non-Null, or this method will panic. 1091// 1092// If the receiver is of a list type, the returned keys will be of type Number 1093// and the values will be of the list's element type. 1094// 1095// If the receiver is of a map type, the returned keys will be of type String 1096// and the value will be of the map's element type. Elements are passed in 1097// ascending lexicographical order by key. 1098// 1099// If the receiver is of a set type, each element is returned as both the 1100// key and the value, since set members are their own identity. 1101// 1102// If the receiver is of a tuple type, the returned keys will be of type Number 1103// and the value will be of the corresponding element's type. 1104// 1105// If the receiver is of an object type, the returned keys will be of type 1106// String and the value will be of the corresponding attributes's type. 1107// 1108// ElementIterator is an integration method, so it cannot handle Unknown 1109// values. This method will panic if the receiver is Unknown. 1110func (val Value) ElementIterator() ElementIterator { 1111 val.assertUnmarked() 1112 if !val.IsKnown() { 1113 panic("can't use ElementIterator on unknown value") 1114 } 1115 if val.IsNull() { 1116 panic("can't use ElementIterator on null value") 1117 } 1118 return elementIterator(val) 1119} 1120 1121// CanIterateElements returns true if the receiver can support the 1122// ElementIterator method (and by extension, ForEachElement) without panic. 1123func (val Value) CanIterateElements() bool { 1124 return canElementIterator(val) 1125} 1126 1127// ForEachElement executes a given callback function for each element of 1128// the receiver, which must be a collection type or tuple type, or this method 1129// will panic. 1130// 1131// ForEachElement uses ElementIterator internally, and so the values passed 1132// to the callback are as described for ElementIterator. 1133// 1134// Returns true if the iteration exited early due to the callback function 1135// returning true, or false if the loop ran to completion. 1136// 1137// ForEachElement is an integration method, so it cannot handle Unknown 1138// values. This method will panic if the receiver is Unknown. 1139func (val Value) ForEachElement(cb ElementCallback) bool { 1140 val.assertUnmarked() 1141 it := val.ElementIterator() 1142 for it.Next() { 1143 key, val := it.Element() 1144 stop := cb(key, val) 1145 if stop { 1146 return true 1147 } 1148 } 1149 return false 1150} 1151 1152// Not returns the logical inverse of the receiver, which must be of type 1153// Bool or this method will panic. 1154func (val Value) Not() Value { 1155 if val.IsMarked() { 1156 val, valMarks := val.Unmark() 1157 return val.Not().WithMarks(valMarks) 1158 } 1159 1160 if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil { 1161 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1162 return *shortCircuit 1163 } 1164 1165 return BoolVal(!val.v.(bool)) 1166} 1167 1168// And returns the result of logical AND with the receiver and the other given 1169// value, which must both be of type Bool or this method will panic. 1170func (val Value) And(other Value) Value { 1171 if val.IsMarked() || other.IsMarked() { 1172 val, valMarks := val.Unmark() 1173 other, otherMarks := other.Unmark() 1174 return val.And(other).WithMarks(valMarks, otherMarks) 1175 } 1176 1177 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil { 1178 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1179 return *shortCircuit 1180 } 1181 1182 return BoolVal(val.v.(bool) && other.v.(bool)) 1183} 1184 1185// Or returns the result of logical OR with the receiver and the other given 1186// value, which must both be of type Bool or this method will panic. 1187func (val Value) Or(other Value) Value { 1188 if val.IsMarked() || other.IsMarked() { 1189 val, valMarks := val.Unmark() 1190 other, otherMarks := other.Unmark() 1191 return val.Or(other).WithMarks(valMarks, otherMarks) 1192 } 1193 1194 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil { 1195 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1196 return *shortCircuit 1197 } 1198 1199 return BoolVal(val.v.(bool) || other.v.(bool)) 1200} 1201 1202// LessThan returns True if the receiver is less than the other given value, 1203// which must both be numbers or this method will panic. 1204func (val Value) LessThan(other Value) Value { 1205 if val.IsMarked() || other.IsMarked() { 1206 val, valMarks := val.Unmark() 1207 other, otherMarks := other.Unmark() 1208 return val.LessThan(other).WithMarks(valMarks, otherMarks) 1209 } 1210 1211 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil { 1212 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1213 return *shortCircuit 1214 } 1215 1216 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0) 1217} 1218 1219// GreaterThan returns True if the receiver is greater than the other given 1220// value, which must both be numbers or this method will panic. 1221func (val Value) GreaterThan(other Value) Value { 1222 if val.IsMarked() || other.IsMarked() { 1223 val, valMarks := val.Unmark() 1224 other, otherMarks := other.Unmark() 1225 return val.GreaterThan(other).WithMarks(valMarks, otherMarks) 1226 } 1227 1228 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil { 1229 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1230 return *shortCircuit 1231 } 1232 1233 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0) 1234} 1235 1236// LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or. 1237func (val Value) LessThanOrEqualTo(other Value) Value { 1238 return val.LessThan(other).Or(val.Equals(other)) 1239} 1240 1241// GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or. 1242func (val Value) GreaterThanOrEqualTo(other Value) Value { 1243 return val.GreaterThan(other).Or(val.Equals(other)) 1244} 1245 1246// AsString returns the native string from a non-null, non-unknown cty.String 1247// value, or panics if called on any other value. 1248func (val Value) AsString() string { 1249 val.assertUnmarked() 1250 if val.ty != String { 1251 panic("not a string") 1252 } 1253 if val.IsNull() { 1254 panic("value is null") 1255 } 1256 if !val.IsKnown() { 1257 panic("value is unknown") 1258 } 1259 1260 return val.v.(string) 1261} 1262 1263// AsBigFloat returns a big.Float representation of a non-null, non-unknown 1264// cty.Number value, or panics if called on any other value. 1265// 1266// For more convenient conversions to other native numeric types, use the 1267// "gocty" package. 1268func (val Value) AsBigFloat() *big.Float { 1269 val.assertUnmarked() 1270 if val.ty != Number { 1271 panic("not a number") 1272 } 1273 if val.IsNull() { 1274 panic("value is null") 1275 } 1276 if !val.IsKnown() { 1277 panic("value is unknown") 1278 } 1279 1280 // Copy the float so that callers can't mutate our internal state 1281 ret := *(val.v.(*big.Float)) 1282 1283 return &ret 1284} 1285 1286// AsValueSlice returns a []cty.Value representation of a non-null, non-unknown 1287// value of any type that CanIterateElements, or panics if called on 1288// any other value. 1289// 1290// For more convenient conversions to slices of more specific types, use 1291// the "gocty" package. 1292func (val Value) AsValueSlice() []Value { 1293 val.assertUnmarked() 1294 l := val.LengthInt() 1295 if l == 0 { 1296 return nil 1297 } 1298 1299 ret := make([]Value, 0, l) 1300 for it := val.ElementIterator(); it.Next(); { 1301 _, v := it.Element() 1302 ret = append(ret, v) 1303 } 1304 return ret 1305} 1306 1307// AsValueMap returns a map[string]cty.Value representation of a non-null, 1308// non-unknown value of any type that CanIterateElements, or panics if called 1309// on any other value. 1310// 1311// For more convenient conversions to maps of more specific types, use 1312// the "gocty" package. 1313func (val Value) AsValueMap() map[string]Value { 1314 val.assertUnmarked() 1315 l := val.LengthInt() 1316 if l == 0 { 1317 return nil 1318 } 1319 1320 ret := make(map[string]Value, l) 1321 for it := val.ElementIterator(); it.Next(); { 1322 k, v := it.Element() 1323 ret[k.AsString()] = v 1324 } 1325 return ret 1326} 1327 1328// AsValueSet returns a ValueSet representation of a non-null, 1329// non-unknown value of any collection type, or panics if called 1330// on any other value. 1331// 1332// Unlike AsValueSlice and AsValueMap, this method requires specifically a 1333// collection type (list, set or map) and does not allow structural types 1334// (tuple or object), because the ValueSet type requires homogenous 1335// element types. 1336// 1337// The returned ValueSet can store only values of the receiver's element type. 1338func (val Value) AsValueSet() ValueSet { 1339 val.assertUnmarked() 1340 if !val.Type().IsCollectionType() { 1341 panic("not a collection type") 1342 } 1343 1344 // We don't give the caller our own set.Set (assuming we're a cty.Set value) 1345 // because then the caller could mutate our internals, which is forbidden. 1346 // Instead, we will construct a new set and append our elements into it. 1347 ret := NewValueSet(val.Type().ElementType()) 1348 for it := val.ElementIterator(); it.Next(); { 1349 _, v := it.Element() 1350 ret.Add(v) 1351 } 1352 return ret 1353} 1354 1355// EncapsulatedValue returns the native value encapsulated in a non-null, 1356// non-unknown capsule-typed value, or panics if called on any other value. 1357// 1358// The result is the same pointer that was passed to CapsuleVal to create 1359// the value. Since cty considers values to be immutable, it is strongly 1360// recommended to treat the encapsulated value itself as immutable too. 1361func (val Value) EncapsulatedValue() interface{} { 1362 val.assertUnmarked() 1363 if !val.Type().IsCapsuleType() { 1364 panic("not a capsule-typed value") 1365 } 1366 1367 return val.v 1368} 1369