github.com/elves/elvish@v0.15.0/pkg/eval/vals/hash.go (about) 1 package vals 2 3 import ( 4 "math" 5 "reflect" 6 7 "github.com/xiaq/persistent/hash" 8 ) 9 10 // Hasher wraps the Hash method. 11 type Hasher interface { 12 // Hash computes the hash code of the receiver. 13 Hash() uint32 14 } 15 16 // Hash returns the 32-bit hash of a value. It is implemented for the builtin 17 // types bool and string, the File, List, Map types, StructMap types, and types 18 // satisfying the Hasher interface. For other values, it returns 0 (which is OK 19 // in terms of correctness). 20 func Hash(v interface{}) uint32 { 21 switch v := v.(type) { 22 case bool: 23 if v { 24 return 1 25 } 26 return 0 27 case float64: 28 return hash.UInt64(math.Float64bits(v)) 29 case string: 30 return hash.String(v) 31 case Hasher: 32 return v.Hash() 33 case File: 34 return hash.UIntPtr(v.Fd()) 35 case List: 36 h := hash.DJBInit 37 for it := v.Iterator(); it.HasElem(); it.Next() { 38 h = hash.DJBCombine(h, Hash(it.Elem())) 39 } 40 return h 41 case Map: 42 h := hash.DJBInit 43 for it := v.Iterator(); it.HasElem(); it.Next() { 44 k, v := it.Elem() 45 h = hash.DJBCombine(h, Hash(k)) 46 h = hash.DJBCombine(h, Hash(v)) 47 } 48 return h 49 case StructMap: 50 h := hash.DJBInit 51 it := iterateStructMap(reflect.TypeOf(v)) 52 vValue := reflect.ValueOf(v) 53 for it.Next() { 54 _, field := it.Get(vValue) 55 h = hash.DJBCombine(h, Hash(field)) 56 } 57 return h 58 } 59 return 0 60 }