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.ContainsMarked() || other.ContainsMarked() { 120 val, valMarks := val.UnmarkDeep() 121 other, otherMarks := other.UnmarkDeep() 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 !val.HasSameMarks(other) { 496 return false 497 } 498 valUn, _ := val.Unmark() 499 otherUn, _ := other.Unmark() 500 if len(valUn.v.(map[string]interface{})) == len(otherUn.v.(map[string]interface{})) { 501 for k := range valUn.v.(map[string]interface{}) { 502 if _, ok := otherUn.v.(map[string]interface{})[k]; !ok { 503 return false 504 } 505 lhs := Value{ 506 ty: ety, 507 v: valUn.v.(map[string]interface{})[k], 508 } 509 rhs := Value{ 510 ty: ety, 511 v: otherUn.v.(map[string]interface{})[k], 512 } 513 eq := lhs.RawEquals(rhs) 514 if !eq { 515 return false 516 } 517 } 518 return true 519 } 520 return false 521 case ty.IsCapsuleType(): 522 impl := val.ty.CapsuleOps().RawEquals 523 if impl == nil { 524 // A capsule type's encapsulated value is a pointer to a value of its 525 // native type, so we can just compare these to get the identity test 526 // we need. 527 return val.v == other.v 528 } 529 return impl(val.v, other.v) 530 531 default: 532 // should never happen 533 panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty)) 534 } 535} 536 537// Add returns the sum of the receiver and the given other value. Both values 538// must be numbers; this method will panic if not. 539func (val Value) Add(other Value) Value { 540 if val.IsMarked() || other.IsMarked() { 541 val, valMarks := val.Unmark() 542 other, otherMarks := other.Unmark() 543 return val.Add(other).WithMarks(valMarks, otherMarks) 544 } 545 546 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 547 shortCircuit = forceShortCircuitType(shortCircuit, Number) 548 return *shortCircuit 549 } 550 551 ret := new(big.Float) 552 ret.Add(val.v.(*big.Float), other.v.(*big.Float)) 553 return NumberVal(ret) 554} 555 556// Subtract returns receiver minus the given other value. Both values must be 557// numbers; this method will panic if not. 558func (val Value) Subtract(other Value) Value { 559 if val.IsMarked() || other.IsMarked() { 560 val, valMarks := val.Unmark() 561 other, otherMarks := other.Unmark() 562 return val.Subtract(other).WithMarks(valMarks, otherMarks) 563 } 564 565 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 566 shortCircuit = forceShortCircuitType(shortCircuit, Number) 567 return *shortCircuit 568 } 569 570 return val.Add(other.Negate()) 571} 572 573// Negate returns the numeric negative of the receiver, which must be a number. 574// This method will panic when given a value of any other type. 575func (val Value) Negate() Value { 576 if val.IsMarked() { 577 val, valMarks := val.Unmark() 578 return val.Negate().WithMarks(valMarks) 579 } 580 581 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil { 582 shortCircuit = forceShortCircuitType(shortCircuit, Number) 583 return *shortCircuit 584 } 585 586 ret := new(big.Float).Neg(val.v.(*big.Float)) 587 return NumberVal(ret) 588} 589 590// Multiply returns the product of the receiver and the given other value. 591// Both values must be numbers; this method will panic if not. 592func (val Value) Multiply(other Value) Value { 593 if val.IsMarked() || other.IsMarked() { 594 val, valMarks := val.Unmark() 595 other, otherMarks := other.Unmark() 596 return val.Multiply(other).WithMarks(valMarks, otherMarks) 597 } 598 599 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 600 shortCircuit = forceShortCircuitType(shortCircuit, Number) 601 return *shortCircuit 602 } 603 604 // find the larger precision of the arguments 605 resPrec := val.v.(*big.Float).Prec() 606 otherPrec := other.v.(*big.Float).Prec() 607 if otherPrec > resPrec { 608 resPrec = otherPrec 609 } 610 611 // make sure we have enough precision for the product 612 ret := new(big.Float).SetPrec(512) 613 ret.Mul(val.v.(*big.Float), other.v.(*big.Float)) 614 615 // now reduce the precision back to the greater argument, or the minimum 616 // required by the product. 617 minPrec := ret.MinPrec() 618 if minPrec > resPrec { 619 resPrec = minPrec 620 } 621 ret.SetPrec(resPrec) 622 623 return NumberVal(ret) 624} 625 626// Divide returns the quotient of the receiver and the given other value. 627// Both values must be numbers; this method will panic if not. 628// 629// If the "other" value is exactly zero, this operation will return either 630// PositiveInfinity or NegativeInfinity, depending on the sign of the 631// receiver value. For some use-cases the presence of infinities may be 632// undesirable, in which case the caller should check whether the 633// other value equals zero before calling and raise an error instead. 634// 635// If both values are zero or infinity, this function will panic with 636// an instance of big.ErrNaN. 637func (val Value) Divide(other Value) Value { 638 if val.IsMarked() || other.IsMarked() { 639 val, valMarks := val.Unmark() 640 other, otherMarks := other.Unmark() 641 return val.Divide(other).WithMarks(valMarks, otherMarks) 642 } 643 644 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 645 shortCircuit = forceShortCircuitType(shortCircuit, Number) 646 return *shortCircuit 647 } 648 649 ret := new(big.Float) 650 ret.Quo(val.v.(*big.Float), other.v.(*big.Float)) 651 return NumberVal(ret) 652} 653 654// Modulo returns the remainder of an integer division of the receiver and 655// the given other value. Both values must be numbers; this method will panic 656// if not. 657// 658// If the "other" value is exactly zero, this operation will return either 659// PositiveInfinity or NegativeInfinity, depending on the sign of the 660// receiver value. For some use-cases the presence of infinities may be 661// undesirable, in which case the caller should check whether the 662// other value equals zero before calling and raise an error instead. 663// 664// This operation is primarily here for use with nonzero natural numbers. 665// Modulo with "other" as a non-natural number gets somewhat philosophical, 666// and this function takes a position on what that should mean, but callers 667// may wish to disallow such things outright or implement their own modulo 668// if they disagree with the interpretation used here. 669func (val Value) Modulo(other Value) Value { 670 if val.IsMarked() || other.IsMarked() { 671 val, valMarks := val.Unmark() 672 other, otherMarks := other.Unmark() 673 return val.Modulo(other).WithMarks(valMarks, otherMarks) 674 } 675 676 if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil { 677 shortCircuit = forceShortCircuitType(shortCircuit, Number) 678 return *shortCircuit 679 } 680 681 // We cheat a bit here with infinities, just abusing the Multiply operation 682 // to get an infinite result of the correct sign. 683 if val == PositiveInfinity || val == NegativeInfinity || other == PositiveInfinity || other == NegativeInfinity { 684 return val.Multiply(other) 685 } 686 687 if other.RawEquals(Zero) { 688 return val 689 } 690 691 // FIXME: This is a bit clumsy. Should come back later and see if there's a 692 // more straightforward way to do this. 693 rat := val.Divide(other) 694 ratFloorInt, _ := rat.v.(*big.Float).Int(nil) 695 696 // start with a copy of the original larger value so that we do not lose 697 // precision. 698 v := val.v.(*big.Float) 699 work := new(big.Float).Copy(v).SetInt(ratFloorInt) 700 work.Mul(other.v.(*big.Float), work) 701 work.Sub(v, work) 702 703 return NumberVal(work) 704} 705 706// Absolute returns the absolute (signless) value of the receiver, which must 707// be a number or this method will panic. 708func (val Value) Absolute() Value { 709 if val.IsMarked() { 710 val, valMarks := val.Unmark() 711 return val.Absolute().WithMarks(valMarks) 712 } 713 714 if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil { 715 shortCircuit = forceShortCircuitType(shortCircuit, Number) 716 return *shortCircuit 717 } 718 719 ret := (&big.Float{}).Abs(val.v.(*big.Float)) 720 return NumberVal(ret) 721} 722 723// GetAttr returns the value of the given attribute of the receiver, which 724// must be of an object type that has an attribute of the given name. 725// This method will panic if the receiver type is not compatible. 726// 727// The method will also panic if the given attribute name is not defined 728// for the value's type. Use the attribute-related methods on Type to 729// check for the validity of an attribute before trying to use it. 730// 731// This method may be called on a value whose type is DynamicPseudoType, 732// in which case the result will also be DynamicVal. 733func (val Value) GetAttr(name string) Value { 734 if val.IsMarked() { 735 val, valMarks := val.Unmark() 736 return val.GetAttr(name).WithMarks(valMarks) 737 } 738 739 if val.ty == DynamicPseudoType { 740 return DynamicVal 741 } 742 743 if !val.ty.IsObjectType() { 744 panic("value is not an object") 745 } 746 747 name = NormalizeString(name) 748 if !val.ty.HasAttribute(name) { 749 panic("value has no attribute of that name") 750 } 751 752 attrType := val.ty.AttributeType(name) 753 754 if !val.IsKnown() { 755 return UnknownVal(attrType) 756 } 757 758 return Value{ 759 ty: attrType, 760 v: val.v.(map[string]interface{})[name], 761 } 762} 763 764// Index returns the value of an element of the receiver, which must have 765// either a list, map or tuple type. This method will panic if the receiver 766// type is not compatible. 767// 768// The key value must be the correct type for the receving collection: a 769// number if the collection is a list or tuple, or a string if it is a map. 770// In the case of a list or tuple, the given number must be convertable to int 771// or this method will panic. The key may alternatively be of 772// DynamicPseudoType, in which case the result itself is an unknown of the 773// collection's element type. 774// 775// The result is of the receiver collection's element type, or in the case 776// of a tuple the type of the specific element index requested. 777// 778// This method may be called on a value whose type is DynamicPseudoType, 779// in which case the result will also be the DynamicValue. 780func (val Value) Index(key Value) Value { 781 if val.IsMarked() || key.IsMarked() { 782 val, valMarks := val.Unmark() 783 key, keyMarks := key.Unmark() 784 return val.Index(key).WithMarks(valMarks, keyMarks) 785 } 786 787 if val.ty == DynamicPseudoType { 788 return DynamicVal 789 } 790 791 switch { 792 case val.Type().IsListType(): 793 elty := val.Type().ElementType() 794 if key.Type() == DynamicPseudoType { 795 return UnknownVal(elty) 796 } 797 798 if key.Type() != Number { 799 panic("element key for list must be number") 800 } 801 if !key.IsKnown() { 802 return UnknownVal(elty) 803 } 804 805 if !val.IsKnown() { 806 return UnknownVal(elty) 807 } 808 809 index, accuracy := key.v.(*big.Float).Int64() 810 if accuracy != big.Exact || index < 0 { 811 panic("element key for list must be non-negative integer") 812 } 813 814 return Value{ 815 ty: elty, 816 v: val.v.([]interface{})[index], 817 } 818 case val.Type().IsMapType(): 819 elty := val.Type().ElementType() 820 if key.Type() == DynamicPseudoType { 821 return UnknownVal(elty) 822 } 823 824 if key.Type() != String { 825 panic("element key for map must be string") 826 } 827 if !key.IsKnown() { 828 return UnknownVal(elty) 829 } 830 831 if !val.IsKnown() { 832 return UnknownVal(elty) 833 } 834 835 keyStr := key.v.(string) 836 837 return Value{ 838 ty: elty, 839 v: val.v.(map[string]interface{})[keyStr], 840 } 841 case val.Type().IsTupleType(): 842 if key.Type() == DynamicPseudoType { 843 return DynamicVal 844 } 845 846 if key.Type() != Number { 847 panic("element key for tuple must be number") 848 } 849 if !key.IsKnown() { 850 return DynamicVal 851 } 852 853 index, accuracy := key.v.(*big.Float).Int64() 854 if accuracy != big.Exact || index < 0 { 855 panic("element key for list must be non-negative integer") 856 } 857 858 eltys := val.Type().TupleElementTypes() 859 860 if !val.IsKnown() { 861 return UnknownVal(eltys[index]) 862 } 863 864 return Value{ 865 ty: eltys[index], 866 v: val.v.([]interface{})[index], 867 } 868 default: 869 panic("not a list, map, or tuple type") 870 } 871} 872 873// HasIndex returns True if the receiver (which must be supported for Index) 874// has an element with the given index key, or False if it does not. 875// 876// The result will be UnknownVal(Bool) if either the collection or the 877// key value are unknown. 878// 879// This method will panic if the receiver is not indexable, but does not 880// impose any panic-causing type constraints on the key. 881func (val Value) HasIndex(key Value) Value { 882 if val.IsMarked() || key.IsMarked() { 883 val, valMarks := val.Unmark() 884 key, keyMarks := key.Unmark() 885 return val.HasIndex(key).WithMarks(valMarks, keyMarks) 886 } 887 888 if val.ty == DynamicPseudoType { 889 return UnknownVal(Bool) 890 } 891 892 switch { 893 case val.Type().IsListType(): 894 if key.Type() == DynamicPseudoType { 895 return UnknownVal(Bool) 896 } 897 898 if key.Type() != Number { 899 return False 900 } 901 if !key.IsKnown() { 902 return UnknownVal(Bool) 903 } 904 if !val.IsKnown() { 905 return UnknownVal(Bool) 906 } 907 908 index, accuracy := key.v.(*big.Float).Int64() 909 if accuracy != big.Exact || index < 0 { 910 return False 911 } 912 913 return BoolVal(int(index) < len(val.v.([]interface{})) && index >= 0) 914 case val.Type().IsMapType(): 915 if key.Type() == DynamicPseudoType { 916 return UnknownVal(Bool) 917 } 918 919 if key.Type() != String { 920 return False 921 } 922 if !key.IsKnown() { 923 return UnknownVal(Bool) 924 } 925 if !val.IsKnown() { 926 return UnknownVal(Bool) 927 } 928 929 keyStr := key.v.(string) 930 _, exists := val.v.(map[string]interface{})[keyStr] 931 932 return BoolVal(exists) 933 case val.Type().IsTupleType(): 934 if key.Type() == DynamicPseudoType { 935 return UnknownVal(Bool) 936 } 937 938 if key.Type() != Number { 939 return False 940 } 941 if !key.IsKnown() { 942 return UnknownVal(Bool) 943 } 944 945 index, accuracy := key.v.(*big.Float).Int64() 946 if accuracy != big.Exact || index < 0 { 947 return False 948 } 949 950 length := val.Type().Length() 951 return BoolVal(int(index) < length && index >= 0) 952 default: 953 panic("not a list, map, or tuple type") 954 } 955} 956 957// HasElement returns True if the receiver (which must be of a set type) 958// has the given value as an element, or False if it does not. 959// 960// The result will be UnknownVal(Bool) if either the set or the 961// given value are unknown. 962// 963// This method will panic if the receiver is not a set, or if it is a null set. 964func (val Value) HasElement(elem Value) Value { 965 if val.IsMarked() || elem.IsMarked() { 966 val, valMarks := val.Unmark() 967 elem, elemMarks := elem.Unmark() 968 return val.HasElement(elem).WithMarks(valMarks, elemMarks) 969 } 970 971 ty := val.Type() 972 973 if !ty.IsSetType() { 974 panic("not a set type") 975 } 976 if !val.IsKnown() || !elem.IsKnown() { 977 return UnknownVal(Bool) 978 } 979 if val.IsNull() { 980 panic("can't call HasElement on a nil value") 981 } 982 if !ty.ElementType().Equals(elem.Type()) { 983 return False 984 } 985 986 s := val.v.(set.Set) 987 return BoolVal(s.Has(elem.v)) 988} 989 990// Length returns the length of the receiver, which must be a collection type 991// or tuple type, as a number value. If the receiver is not a compatible type 992// then this method will panic. 993// 994// If the receiver is unknown then the result is also unknown. 995// 996// If the receiver is null then this function will panic. 997// 998// Note that Length is not supported for strings. To determine the length 999// of a string, use the Length function in funcs/stdlib. 1000func (val Value) Length() Value { 1001 if val.IsMarked() { 1002 val, valMarks := val.Unmark() 1003 return val.Length().WithMarks(valMarks) 1004 } 1005 1006 if val.Type().IsTupleType() { 1007 // For tuples, we can return the length even if the value is not known. 1008 return NumberIntVal(int64(val.Type().Length())) 1009 } 1010 1011 if !val.IsKnown() { 1012 return UnknownVal(Number) 1013 } 1014 if val.Type().IsSetType() { 1015 // The Length rules are a little different for sets because if any 1016 // unknown values are present then the values they are standing in for 1017 // may or may not be equal to other elements in the set, and thus they 1018 // may or may not coalesce with other elements and produce fewer 1019 // items in the resulting set. 1020 storeLength := int64(val.v.(set.Set).Length()) 1021 if storeLength == 1 || val.IsWhollyKnown() { 1022 // If our set is wholly known then we know its length. 1023 // 1024 // We also know the length if the physical store has only one 1025 // element, even if that element is unknown, because there's 1026 // nothing else in the set for it to coalesce with and a single 1027 // unknown value cannot represent more than one known value. 1028 return NumberIntVal(storeLength) 1029 } 1030 // Otherwise, we cannot predict the length. 1031 return UnknownVal(Number) 1032 } 1033 1034 return NumberIntVal(int64(val.LengthInt())) 1035} 1036 1037// LengthInt is like Length except it returns an int. It has the same behavior 1038// as Length except that it will panic if the receiver is unknown. 1039// 1040// This is an integration method provided for the convenience of code bridging 1041// into Go's type system. 1042// 1043// For backward compatibility with an earlier implementation error, LengthInt's 1044// result can disagree with Length's result for any set containing unknown 1045// values. Length can potentially indicate the set's length is unknown in that 1046// case, whereas LengthInt will return the maximum possible length as if the 1047// unknown values were each a placeholder for a value not equal to any other 1048// value in the set. 1049func (val Value) LengthInt() int { 1050 val.assertUnmarked() 1051 if val.Type().IsTupleType() { 1052 // For tuples, we can return the length even if the value is not known. 1053 return val.Type().Length() 1054 } 1055 if val.Type().IsObjectType() { 1056 // For objects, the length is the number of attributes associated with the type. 1057 return len(val.Type().AttributeTypes()) 1058 } 1059 if !val.IsKnown() { 1060 panic("value is not known") 1061 } 1062 if val.IsNull() { 1063 panic("value is null") 1064 } 1065 1066 switch { 1067 1068 case val.ty.IsListType(): 1069 return len(val.v.([]interface{})) 1070 1071 case val.ty.IsSetType(): 1072 // NOTE: This is technically not correct in cases where the set 1073 // contains unknown values, because in that case we can't know how 1074 // many known values those unknown values are standing in for -- they 1075 // might coalesce with other values once known. 1076 // 1077 // However, this incorrect behavior is preserved for backward 1078 // compatibility with callers that were relying on LengthInt rather 1079 // than calling Length. Instead of panicking when a set contains an 1080 // unknown value, LengthInt returns the largest possible length. 1081 return val.v.(set.Set).Length() 1082 1083 case val.ty.IsMapType(): 1084 return len(val.v.(map[string]interface{})) 1085 1086 default: 1087 panic("value is not a collection") 1088 } 1089} 1090 1091// ElementIterator returns an ElementIterator for iterating the elements 1092// of the receiver, which must be a collection type, a tuple type, or an object 1093// type. If called on a method of any other type, this method will panic. 1094// 1095// The value must be Known and non-Null, or this method will panic. 1096// 1097// If the receiver is of a list type, the returned keys will be of type Number 1098// and the values will be of the list's element type. 1099// 1100// If the receiver is of a map type, the returned keys will be of type String 1101// and the value will be of the map's element type. Elements are passed in 1102// ascending lexicographical order by key. 1103// 1104// If the receiver is of a set type, each element is returned as both the 1105// key and the value, since set members are their own identity. 1106// 1107// If the receiver is of a tuple type, the returned keys will be of type Number 1108// and the value will be of the corresponding element's type. 1109// 1110// If the receiver is of an object type, the returned keys will be of type 1111// String and the value will be of the corresponding attributes's type. 1112// 1113// ElementIterator is an integration method, so it cannot handle Unknown 1114// values. This method will panic if the receiver is Unknown. 1115func (val Value) ElementIterator() ElementIterator { 1116 val.assertUnmarked() 1117 if !val.IsKnown() { 1118 panic("can't use ElementIterator on unknown value") 1119 } 1120 if val.IsNull() { 1121 panic("can't use ElementIterator on null value") 1122 } 1123 return elementIterator(val) 1124} 1125 1126// CanIterateElements returns true if the receiver can support the 1127// ElementIterator method (and by extension, ForEachElement) without panic. 1128func (val Value) CanIterateElements() bool { 1129 return canElementIterator(val) 1130} 1131 1132// ForEachElement executes a given callback function for each element of 1133// the receiver, which must be a collection type or tuple type, or this method 1134// will panic. 1135// 1136// ForEachElement uses ElementIterator internally, and so the values passed 1137// to the callback are as described for ElementIterator. 1138// 1139// Returns true if the iteration exited early due to the callback function 1140// returning true, or false if the loop ran to completion. 1141// 1142// ForEachElement is an integration method, so it cannot handle Unknown 1143// values. This method will panic if the receiver is Unknown. 1144func (val Value) ForEachElement(cb ElementCallback) bool { 1145 val.assertUnmarked() 1146 it := val.ElementIterator() 1147 for it.Next() { 1148 key, val := it.Element() 1149 stop := cb(key, val) 1150 if stop { 1151 return true 1152 } 1153 } 1154 return false 1155} 1156 1157// Not returns the logical inverse of the receiver, which must be of type 1158// Bool or this method will panic. 1159func (val Value) Not() Value { 1160 if val.IsMarked() { 1161 val, valMarks := val.Unmark() 1162 return val.Not().WithMarks(valMarks) 1163 } 1164 1165 if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil { 1166 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1167 return *shortCircuit 1168 } 1169 1170 return BoolVal(!val.v.(bool)) 1171} 1172 1173// And returns the result of logical AND with the receiver and the other given 1174// value, which must both be of type Bool or this method will panic. 1175func (val Value) And(other Value) Value { 1176 if val.IsMarked() || other.IsMarked() { 1177 val, valMarks := val.Unmark() 1178 other, otherMarks := other.Unmark() 1179 return val.And(other).WithMarks(valMarks, otherMarks) 1180 } 1181 1182 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil { 1183 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1184 return *shortCircuit 1185 } 1186 1187 return BoolVal(val.v.(bool) && other.v.(bool)) 1188} 1189 1190// Or returns the result of logical OR with the receiver and the other given 1191// value, which must both be of type Bool or this method will panic. 1192func (val Value) Or(other Value) Value { 1193 if val.IsMarked() || other.IsMarked() { 1194 val, valMarks := val.Unmark() 1195 other, otherMarks := other.Unmark() 1196 return val.Or(other).WithMarks(valMarks, otherMarks) 1197 } 1198 1199 if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil { 1200 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1201 return *shortCircuit 1202 } 1203 1204 return BoolVal(val.v.(bool) || other.v.(bool)) 1205} 1206 1207// LessThan returns True if the receiver is less than the other given value, 1208// which must both be numbers or this method will panic. 1209func (val Value) LessThan(other Value) Value { 1210 if val.IsMarked() || other.IsMarked() { 1211 val, valMarks := val.Unmark() 1212 other, otherMarks := other.Unmark() 1213 return val.LessThan(other).WithMarks(valMarks, otherMarks) 1214 } 1215 1216 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil { 1217 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1218 return *shortCircuit 1219 } 1220 1221 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0) 1222} 1223 1224// GreaterThan returns True if the receiver is greater than the other given 1225// value, which must both be numbers or this method will panic. 1226func (val Value) GreaterThan(other Value) Value { 1227 if val.IsMarked() || other.IsMarked() { 1228 val, valMarks := val.Unmark() 1229 other, otherMarks := other.Unmark() 1230 return val.GreaterThan(other).WithMarks(valMarks, otherMarks) 1231 } 1232 1233 if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil { 1234 shortCircuit = forceShortCircuitType(shortCircuit, Bool) 1235 return *shortCircuit 1236 } 1237 1238 return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0) 1239} 1240 1241// LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or. 1242func (val Value) LessThanOrEqualTo(other Value) Value { 1243 return val.LessThan(other).Or(val.Equals(other)) 1244} 1245 1246// GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or. 1247func (val Value) GreaterThanOrEqualTo(other Value) Value { 1248 return val.GreaterThan(other).Or(val.Equals(other)) 1249} 1250 1251// AsString returns the native string from a non-null, non-unknown cty.String 1252// value, or panics if called on any other value. 1253func (val Value) AsString() string { 1254 val.assertUnmarked() 1255 if val.ty != String { 1256 panic("not a string") 1257 } 1258 if val.IsNull() { 1259 panic("value is null") 1260 } 1261 if !val.IsKnown() { 1262 panic("value is unknown") 1263 } 1264 1265 return val.v.(string) 1266} 1267 1268// AsBigFloat returns a big.Float representation of a non-null, non-unknown 1269// cty.Number value, or panics if called on any other value. 1270// 1271// For more convenient conversions to other native numeric types, use the 1272// "gocty" package. 1273func (val Value) AsBigFloat() *big.Float { 1274 val.assertUnmarked() 1275 if val.ty != Number { 1276 panic("not a number") 1277 } 1278 if val.IsNull() { 1279 panic("value is null") 1280 } 1281 if !val.IsKnown() { 1282 panic("value is unknown") 1283 } 1284 1285 // Copy the float so that callers can't mutate our internal state 1286 return new(big.Float).Copy(val.v.(*big.Float)) 1287} 1288 1289// AsValueSlice returns a []cty.Value representation of a non-null, non-unknown 1290// value of any type that CanIterateElements, or panics if called on 1291// any other value. 1292// 1293// For more convenient conversions to slices of more specific types, use 1294// the "gocty" package. 1295func (val Value) AsValueSlice() []Value { 1296 val.assertUnmarked() 1297 l := val.LengthInt() 1298 if l == 0 { 1299 return nil 1300 } 1301 1302 ret := make([]Value, 0, l) 1303 for it := val.ElementIterator(); it.Next(); { 1304 _, v := it.Element() 1305 ret = append(ret, v) 1306 } 1307 return ret 1308} 1309 1310// AsValueMap returns a map[string]cty.Value representation of a non-null, 1311// non-unknown value of any type that CanIterateElements, or panics if called 1312// on any other value. 1313// 1314// For more convenient conversions to maps of more specific types, use 1315// the "gocty" package. 1316func (val Value) AsValueMap() map[string]Value { 1317 val.assertUnmarked() 1318 l := val.LengthInt() 1319 if l == 0 { 1320 return nil 1321 } 1322 1323 ret := make(map[string]Value, l) 1324 for it := val.ElementIterator(); it.Next(); { 1325 k, v := it.Element() 1326 ret[k.AsString()] = v 1327 } 1328 return ret 1329} 1330 1331// AsValueSet returns a ValueSet representation of a non-null, 1332// non-unknown value of any collection type, or panics if called 1333// on any other value. 1334// 1335// Unlike AsValueSlice and AsValueMap, this method requires specifically a 1336// collection type (list, set or map) and does not allow structural types 1337// (tuple or object), because the ValueSet type requires homogenous 1338// element types. 1339// 1340// The returned ValueSet can store only values of the receiver's element type. 1341func (val Value) AsValueSet() ValueSet { 1342 val.assertUnmarked() 1343 if !val.Type().IsCollectionType() { 1344 panic("not a collection type") 1345 } 1346 1347 // We don't give the caller our own set.Set (assuming we're a cty.Set value) 1348 // because then the caller could mutate our internals, which is forbidden. 1349 // Instead, we will construct a new set and append our elements into it. 1350 ret := NewValueSet(val.Type().ElementType()) 1351 for it := val.ElementIterator(); it.Next(); { 1352 _, v := it.Element() 1353 ret.Add(v) 1354 } 1355 return ret 1356} 1357 1358// EncapsulatedValue returns the native value encapsulated in a non-null, 1359// non-unknown capsule-typed value, or panics if called on any other value. 1360// 1361// The result is the same pointer that was passed to CapsuleVal to create 1362// the value. Since cty considers values to be immutable, it is strongly 1363// recommended to treat the encapsulated value itself as immutable too. 1364func (val Value) EncapsulatedValue() interface{} { 1365 val.assertUnmarked() 1366 if !val.Type().IsCapsuleType() { 1367 panic("not a capsule-typed value") 1368 } 1369 1370 return val.v 1371} 1372