go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/murmur3/murmur.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 // Copyright 2013, Sébastien Paolacci. All rights reserved. 9 // Use of this source code is governed by a BSD-style 10 // license that can be found in the LICENSE file. 11 12 /* 13 Package murmur3 implements Austin Appleby's non-cryptographic MurmurHash3. 14 15 Reference implementation: 16 http://code.google.com/p/smhasher/wiki/MurmurHash3 17 18 History, characteristics and (legacy) perfs: 19 https://sites.google.com/site/murmurhash/ 20 https://sites.google.com/site/murmurhash/statistics 21 */ 22 package murmur3 23 24 type bmixer interface { 25 bmix(p []byte) (tail []byte) 26 Size() (n int) 27 reset() 28 } 29 30 type digest struct { 31 clen int // Digested input cumulative length. 32 tail []byte // 0 to Size()-1 bytes view of `buf'. 33 buf [16]byte // Expected (but not required) to be Size() large. 34 seed uint32 // Seed for initializing the hash. 35 bmixer 36 } 37 38 func (d *digest) BlockSize() int { return 1 } 39 40 func (d *digest) Write(p []byte) (n int, err error) { 41 n = len(p) 42 d.clen += n 43 44 if len(d.tail) > 0 { 45 // Stick back pending bytes. 46 nfree := d.Size() - len(d.tail) // nfree ∈ [1, d.Size()-1]. 47 if nfree < len(p) { 48 // One full block can be formed. 49 block := append(d.tail, p[:nfree]...) 50 p = p[nfree:] 51 _ = d.bmix(block) // No tail. 52 } else { 53 // Tail's buf is large enough to prevent reallocs. 54 p = append(d.tail, p...) 55 } 56 } 57 58 d.tail = d.bmix(p) 59 60 // Keep own copy of the 0 to Size()-1 pending bytes. 61 nn := copy(d.buf[:], d.tail) 62 d.tail = d.buf[:nn] 63 64 return n, nil 65 } 66 67 func (d *digest) Reset() { 68 d.clen = 0 69 d.tail = nil 70 d.bmixer.reset() 71 }