hasher.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package xxh3
  2. import (
  3. "encoding/binary"
  4. "hash"
  5. )
  6. // Hasher implements the hash.Hash interface
  7. type Hasher struct {
  8. acc [8]u64
  9. blk u64
  10. len u64
  11. key ptr
  12. buf [_block + _stripe]byte
  13. seed u64
  14. }
  15. var (
  16. _ hash.Hash = (*Hasher)(nil)
  17. _ hash.Hash64 = (*Hasher)(nil)
  18. )
  19. // New returns a new Hasher that implements the hash.Hash interface.
  20. func New() *Hasher {
  21. return new(Hasher)
  22. }
  23. // NewSeed returns a new Hasher that implements the hash.Hash interface.
  24. func NewSeed(seed uint64) *Hasher {
  25. var h Hasher
  26. h.Reset()
  27. h.seed = seed
  28. h.key = key
  29. // Only initiate once, not on reset.
  30. if seed != 0 {
  31. h.key = ptr(&[secretSize]byte{})
  32. initSecret(h.key, seed)
  33. }
  34. return &h
  35. }
  36. // Reset resets the Hash to its initial state.
  37. func (h *Hasher) Reset() {
  38. h.acc = [8]u64{
  39. prime32_3, prime64_1, prime64_2, prime64_3,
  40. prime64_4, prime32_2, prime64_5, prime32_1,
  41. }
  42. h.blk = 0
  43. h.len = 0
  44. }
  45. // BlockSize returns the hash's underlying block size.
  46. // The Write method will accept any amount of data, but
  47. // it may operate more efficiently if all writes are a
  48. // multiple of the block size.
  49. func (h *Hasher) BlockSize() int { return _stripe }
  50. // Size returns the number of bytes Sum will return.
  51. func (h *Hasher) Size() int { return 8 }
  52. // Sum appends the current hash to b and returns the resulting slice.
  53. // It does not change the underlying hash state.
  54. func (h *Hasher) Sum(b []byte) []byte {
  55. var tmp [8]byte
  56. binary.BigEndian.PutUint64(tmp[:], h.Sum64())
  57. return append(b, tmp[:]...)
  58. }
  59. // Write adds more data to the running hash.
  60. // It never returns an error.
  61. func (h *Hasher) Write(buf []byte) (int, error) {
  62. h.update(buf)
  63. return len(buf), nil
  64. }
  65. // WriteString adds more data to the running hash.
  66. // It never returns an error.
  67. func (h *Hasher) WriteString(buf string) (int, error) {
  68. h.updateString(buf)
  69. return len(buf), nil
  70. }
  71. func (h *Hasher) update(buf []byte) {
  72. // relies on the data pointer being the first word in the string header
  73. h.updateString(*(*string)(ptr(&buf)))
  74. }
  75. func (h *Hasher) updateString(buf string) {
  76. if h.key == nil {
  77. h.key = key
  78. h.Reset()
  79. }
  80. // On first write, if more than 1 block, process without copy.
  81. for h.len == 0 && len(buf) > len(h.buf) {
  82. if hasAVX2 {
  83. accumBlockAVX2(&h.acc, *(*ptr)(ptr(&buf)), h.key)
  84. } else if hasSSE2 {
  85. accumBlockSSE(&h.acc, *(*ptr)(ptr(&buf)), h.key)
  86. } else {
  87. accumBlockScalar(&h.acc, *(*ptr)(ptr(&buf)), h.key)
  88. }
  89. buf = buf[_block:]
  90. h.blk++
  91. }
  92. for len(buf) > 0 {
  93. if h.len < u64(len(h.buf)) {
  94. n := copy(h.buf[h.len:], buf)
  95. h.len += u64(n)
  96. buf = buf[n:]
  97. continue
  98. }
  99. if hasAVX2 {
  100. accumBlockAVX2(&h.acc, ptr(&h.buf), h.key)
  101. } else if hasSSE2 {
  102. accumBlockSSE(&h.acc, ptr(&h.buf), h.key)
  103. } else {
  104. accumBlockScalar(&h.acc, ptr(&h.buf), h.key)
  105. }
  106. h.blk++
  107. h.len = _stripe
  108. copy(h.buf[:_stripe], h.buf[_block:])
  109. }
  110. }
  111. // Sum64 returns the 64-bit hash of the written data.
  112. func (h *Hasher) Sum64() uint64 {
  113. if h.key == nil {
  114. h.key = key
  115. h.Reset()
  116. }
  117. if h.blk == 0 {
  118. if h.seed == 0 {
  119. return Hash(h.buf[:h.len])
  120. }
  121. return HashSeed(h.buf[:h.len], h.seed)
  122. }
  123. l := h.blk*_block + h.len
  124. acc := l * prime64_1
  125. accs := h.acc
  126. if h.len > 0 {
  127. // We are only ever doing 1 block here, so no avx512.
  128. if hasAVX2 {
  129. accumAVX2(&accs, ptr(&h.buf[0]), h.key, h.len)
  130. } else if hasSSE2 {
  131. accumSSE(&accs, ptr(&h.buf[0]), h.key, h.len)
  132. } else {
  133. accumScalar(&accs, ptr(&h.buf[0]), h.key, h.len)
  134. }
  135. }
  136. if h.seed == 0 {
  137. acc += mulFold64(accs[0]^key64_011, accs[1]^key64_019)
  138. acc += mulFold64(accs[2]^key64_027, accs[3]^key64_035)
  139. acc += mulFold64(accs[4]^key64_043, accs[5]^key64_051)
  140. acc += mulFold64(accs[6]^key64_059, accs[7]^key64_067)
  141. } else {
  142. secret := h.key
  143. acc += mulFold64(accs[0]^readU64(secret, 11), accs[1]^readU64(secret, 19))
  144. acc += mulFold64(accs[2]^readU64(secret, 27), accs[3]^readU64(secret, 35))
  145. acc += mulFold64(accs[4]^readU64(secret, 43), accs[5]^readU64(secret, 51))
  146. acc += mulFold64(accs[6]^readU64(secret, 59), accs[7]^readU64(secret, 67))
  147. }
  148. acc = xxh3Avalanche(acc)
  149. return acc
  150. }
  151. // Sum128 returns the 128-bit hash of the written data.
  152. func (h *Hasher) Sum128() Uint128 {
  153. if h.key == nil {
  154. h.key = key
  155. h.Reset()
  156. }
  157. if h.blk == 0 {
  158. if h.seed == 0 {
  159. return Hash128(h.buf[:h.len])
  160. }
  161. return Hash128Seed(h.buf[:h.len], h.seed)
  162. }
  163. l := h.blk*_block + h.len
  164. acc := Uint128{Lo: l * prime64_1, Hi: ^(l * prime64_2)}
  165. accs := h.acc
  166. if h.len > 0 {
  167. // We are only ever doing 1 block here, so no avx512.
  168. if hasAVX2 {
  169. accumAVX2(&accs, ptr(&h.buf[0]), h.key, h.len)
  170. } else if hasSSE2 {
  171. accumSSE(&accs, ptr(&h.buf[0]), h.key, h.len)
  172. } else {
  173. accumScalar(&accs, ptr(&h.buf[0]), h.key, h.len)
  174. }
  175. }
  176. if h.seed == 0 {
  177. acc.Lo += mulFold64(accs[0]^key64_011, accs[1]^key64_019)
  178. acc.Hi += mulFold64(accs[0]^key64_117, accs[1]^key64_125)
  179. acc.Lo += mulFold64(accs[2]^key64_027, accs[3]^key64_035)
  180. acc.Hi += mulFold64(accs[2]^key64_133, accs[3]^key64_141)
  181. acc.Lo += mulFold64(accs[4]^key64_043, accs[5]^key64_051)
  182. acc.Hi += mulFold64(accs[4]^key64_149, accs[5]^key64_157)
  183. acc.Lo += mulFold64(accs[6]^key64_059, accs[7]^key64_067)
  184. acc.Hi += mulFold64(accs[6]^key64_165, accs[7]^key64_173)
  185. } else {
  186. secret := h.key
  187. const hi_off = 117 - 11
  188. acc.Lo += mulFold64(accs[0]^readU64(secret, 11), accs[1]^readU64(secret, 19))
  189. acc.Hi += mulFold64(accs[0]^readU64(secret, 11+hi_off), accs[1]^readU64(secret, 19+hi_off))
  190. acc.Lo += mulFold64(accs[2]^readU64(secret, 27), accs[3]^readU64(secret, 35))
  191. acc.Hi += mulFold64(accs[2]^readU64(secret, 27+hi_off), accs[3]^readU64(secret, 35+hi_off))
  192. acc.Lo += mulFold64(accs[4]^readU64(secret, 43), accs[5]^readU64(secret, 51))
  193. acc.Hi += mulFold64(accs[4]^readU64(secret, 43+hi_off), accs[5]^readU64(secret, 51+hi_off))
  194. acc.Lo += mulFold64(accs[6]^readU64(secret, 59), accs[7]^readU64(secret, 67))
  195. acc.Hi += mulFold64(accs[6]^readU64(secret, 59+hi_off), accs[7]^readU64(secret, 67+hi_off))
  196. }
  197. acc.Lo = xxh3Avalanche(acc.Lo)
  198. acc.Hi = xxh3Avalanche(acc.Hi)
  199. return acc
  200. }