// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package fnv implements FNV-1 and FNV-1a, non-cryptographic hash functions // created by Glenn Fowler, Landon Curt Noll, and Phong Vo. // See // https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function. // // All the hash.Hash implementations returned by this package also // implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to // marshal and unmarshal the internal state of the hash. package fnv import ( "errors" "hash" "internal/byteorder" "math/bits" ) type ( sum32 uint32 sum32a uint32 sum64 uint64 sum64a uint64 sum128 [2]uint64 sum128a [2]uint64 ) const ( offset32 = 2166136261 offset64 = 14695981039346656037 offset128Lower = 0x62b821756295c58d offset128Higher = 0x6c62272e07bb0142 prime32 = 16777619 prime64 = 1099511628211 prime128Lower = 0x13b prime128Shift = 24 ) // New32 returns a new 32-bit FNV-1 [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func New32() hash.Hash32 { var s sum32 = offset32 return &s } // New32a returns a new 32-bit FNV-1a [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func New32a() hash.Hash32 { var s sum32a = offset32 return &s } // New64 returns a new 64-bit FNV-1 [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func New64() hash.Hash64 { var s sum64 = offset64 return &s } // New64a returns a new 64-bit FNV-1a [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func New64a() hash.Hash64 { var s sum64a = offset64 return &s } // New128 returns a new 128-bit FNV-1 [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func New128() hash.Hash { var s sum128 s[0] = offset128Higher s[1] = offset128Lower return &s } // New128a returns a new 128-bit FNV-1a [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func New128a() hash.Hash { var s sum128a s[0] = offset128Higher s[1] = offset128Lower return &s } func (s *sum32) Reset() { *s = offset32 } func (s *sum32a) Reset() { *s = offset32 } func (s *sum64) Reset() { *s = offset64 } func (s *sum64a) Reset() { *s = offset64 } func (s *sum128) Reset() { s[0] = offset128Higher; s[1] = offset128Lower } func (s *sum128a) Reset() { s[0] = offset128Higher; s[1] = offset128Lower } func (s *sum32) Sum32() uint32 { return uint32(*s) } func (s *sum32a) Sum32() uint32 { return uint32(*s) } func (s *sum64) Sum64() uint64 { return uint64(*s) } func (s *sum64a) Sum64() uint64 { return uint64(*s) } func (s *sum32) Write(data []byte) (int, error) { hash := *s for _, c := range data { hash *= prime32 hash ^= sum32(c) } *s = hash return len(data), nil } func (s *sum32a) Write(data []byte) (int, error) { hash := *s for _, c := range data { hash ^= sum32a(c) hash *= prime32 } *s = hash return len(data), nil } func (s *sum64) Write(data []byte) (int, error) { hash := *s for _, c := range data { hash *= prime64 hash ^= sum64(c) } *s = hash return len(data), nil } func (s *sum64a) Write(data []byte) (int, error) { hash := *s for _, c := range data { hash ^= sum64a(c) hash *= prime64 } *s = hash return len(data), nil } func (s *sum128) Write(data []byte) (int, error) { for _, c := range data { // Compute the multiplication s0, s1 := bits.Mul64(prime128Lower, s[1]) s0 += s[1]<