]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/zclconf/go-cty/cty/set_internals.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / zclconf / go-cty / cty / set_internals.go
index ce738dbe66e85035b01bc5280e5c981bc68c8f3a..3fd4fb2df637fe269d8187fc61ec4132b121f483 100644 (file)
@@ -6,6 +6,8 @@ import (
        "hash/crc32"
        "math/big"
        "sort"
+
+       "github.com/zclconf/go-cty/cty/set"
 )
 
 // setRules provides a Rules implementation for the ./set package that
@@ -19,12 +21,26 @@ type setRules struct {
        Type Type
 }
 
+var _ set.OrderedRules = setRules{}
+
+// Hash returns a hash value for the receiver that can be used for equality
+// checks where some inaccuracy is tolerable.
+//
+// The hash function is value-type-specific, so it is not meaningful to compare
+// hash results for values of different types.
+//
+// This function is not safe to use for security-related applications, since
+// the hash used is not strong enough.
+func (val Value) Hash() int {
+       hashBytes := makeSetHashBytes(val)
+       return int(crc32.ChecksumIEEE(hashBytes))
+}
+
 func (r setRules) Hash(v interface{}) int {
-       hashBytes := makeSetHashBytes(Value{
+       return Value{
                ty: r.Type,
                v:  v,
-       })
-       return int(crc32.ChecksumIEEE(hashBytes))
+       }.Hash()
 }
 
 func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool {
@@ -46,6 +62,60 @@ func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool {
        return eqv.v == true
 }
 
+// Less is an implementation of set.OrderedRules so that we can iterate over
+// set elements in a consistent order, where such an order is possible.
+func (r setRules) Less(v1, v2 interface{}) bool {
+       v1v := Value{
+               ty: r.Type,
+               v:  v1,
+       }
+       v2v := Value{
+               ty: r.Type,
+               v:  v2,
+       }
+
+       if v1v.RawEquals(v2v) { // Easy case: if they are equal then v1 can't be less
+               return false
+       }
+
+       // Null values always sort after non-null values
+       if v2v.IsNull() && !v1v.IsNull() {
+               return true
+       } else if v1v.IsNull() {
+               return false
+       }
+       // Unknown values always sort after known values
+       if v1v.IsKnown() && !v2v.IsKnown() {
+               return true
+       } else if !v1v.IsKnown() {
+               return false
+       }
+
+       switch r.Type {
+       case String:
+               // String values sort lexicographically
+               return v1v.AsString() < v2v.AsString()
+       case Bool:
+               // Weird to have a set of bools, but if we do then false sorts before true.
+               if v2v.True() || !v1v.True() {
+                       return true
+               }
+               return false
+       case Number:
+               v1f := v1v.AsBigFloat()
+               v2f := v2v.AsBigFloat()
+               return v1f.Cmp(v2f) < 0
+       default:
+               // No other types have a well-defined ordering, so we just produce a
+               // default consistent-but-undefined ordering then. This situation is
+               // not considered a compatibility constraint; callers should rely only
+               // on the ordering rules for primitive values.
+               v1h := makeSetHashBytes(v1v)
+               v2h := makeSetHashBytes(v2v)
+               return bytes.Compare(v1h, v2h) < 0
+       }
+}
+
 func makeSetHashBytes(val Value) []byte {
        var buf bytes.Buffer
        appendSetHashBytes(val, &buf)