github.com/Jeffail/benthos/v3@v3.65.0/lib/util/hash/murmur2/murmur2.go (about) 1 package murmur2 2 3 import "hash" 4 5 type murmur2 struct { 6 data []byte 7 cached *uint32 8 } 9 10 // New32 creates a murmur 2 based hash.Hash32 implementation. 11 func New32() hash.Hash32 { 12 return &murmur2{ 13 data: make([]byte, 0), 14 } 15 } 16 17 // Write a slice of data to the hasher. 18 func (mur *murmur2) Write(p []byte) (n int, err error) { 19 mur.data = append(mur.data, p...) 20 mur.cached = nil 21 return len(p), nil 22 } 23 24 // Sum appends the current hash to b and returns the resulting slice. 25 // It does not change the underlying hash state. 26 func (mur *murmur2) Sum(b []byte) []byte { 27 v := mur.Sum32() 28 return append(b, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) 29 } 30 31 // Reset resets the Hash to its initial state. 32 func (mur *murmur2) Reset() { 33 mur.data = mur.data[0:0] 34 mur.cached = nil 35 } 36 37 // Size returns the number of bytes Sum will return. 38 func (mur *murmur2) Size() int { 39 return 4 40 } 41 42 // BlockSize returns the hash's underlying block size. 43 // The Write method must be able to accept any amount 44 // of data, but it may operate more efficiently if all writes 45 // are a multiple of the block size. 46 func (mur *murmur2) BlockSize() int { 47 return 4 48 } 49 50 const ( 51 seed uint32 = uint32(0x9747b28c) 52 m int32 = int32(0x5bd1e995) 53 r uint32 = uint32(24) 54 ) 55 56 func (mur *murmur2) Sum32() uint32 { 57 if mur.cached != nil { 58 return *mur.cached 59 } 60 61 length := int32(len(mur.data)) 62 63 h := int32(seed ^ uint32(length)) 64 length4 := length / 4 65 66 for i := int32(0); i < length4; i++ { 67 i4 := i * 4 68 k := int32(mur.data[i4+0]&0xff) + 69 (int32(mur.data[i4+1]&0xff) << 8) + 70 (int32(mur.data[i4+2]&0xff) << 16) + 71 (int32(mur.data[i4+3]&0xff) << 24) 72 k *= m 73 k ^= int32(uint32(k) >> r) 74 k *= m 75 h *= m 76 h ^= k 77 } 78 79 switch length % 4 { 80 case 3: 81 h ^= int32(mur.data[(length & ^3)+2]&0xff) << 16 82 fallthrough 83 case 2: 84 h ^= int32(mur.data[(length & ^3)+1]&0xff) << 8 85 fallthrough 86 case 1: 87 h ^= int32(mur.data[length & ^3] & 0xff) 88 h *= m 89 } 90 91 h ^= int32(uint32(h) >> 13) 92 h *= m 93 h ^= int32(uint32(h) >> 15) 94 95 cached := uint32(h) 96 mur.cached = &cached 97 return cached 98 }