// 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 ( ) 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 () hash.Hash32 { var sum32 = offset32 return & } // New32a returns a new 32-bit FNV-1a [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func () hash.Hash32 { var sum32a = offset32 return & } // New64 returns a new 64-bit FNV-1 [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func () hash.Hash64 { var sum64 = offset64 return & } // New64a returns a new 64-bit FNV-1a [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func () hash.Hash64 { var sum64a = offset64 return & } // New128 returns a new 128-bit FNV-1 [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func () hash.Hash { var sum128 [0] = offset128Higher [1] = offset128Lower return & } // New128a returns a new 128-bit FNV-1a [hash.Hash]. // Its Sum method will lay the value out in big-endian byte order. func () hash.Hash { var sum128a [0] = offset128Higher [1] = offset128Lower return & } func ( *sum32) () { * = offset32 } func ( *sum32a) () { * = offset32 } func ( *sum64) () { * = offset64 } func ( *sum64a) () { * = offset64 } func ( *sum128) () { [0] = offset128Higher; [1] = offset128Lower } func ( *sum128a) () { [0] = offset128Higher; [1] = offset128Lower } func ( *sum32) () uint32 { return uint32(*) } func ( *sum32a) () uint32 { return uint32(*) } func ( *sum64) () uint64 { return uint64(*) } func ( *sum64a) () uint64 { return uint64(*) } func ( *sum32) ( []byte) (int, error) { := * for , := range { *= prime32 ^= sum32() } * = return len(), nil } func ( *sum32a) ( []byte) (int, error) { := * for , := range { ^= sum32a() *= prime32 } * = return len(), nil } func ( *sum64) ( []byte) (int, error) { := * for , := range { *= prime64 ^= sum64() } * = return len(), nil } func ( *sum64a) ( []byte) (int, error) { := * for , := range { ^= sum64a() *= prime64 } * = return len(), nil } func ( *sum128) ( []byte) (int, error) { for , := range { // Compute the multiplication , := bits.Mul64(prime128Lower, [1]) += [1]<<prime128Shift + prime128Lower*[0] // Update the values [1] = [0] = [1] ^= uint64() } return len(), nil } func ( *sum128a) ( []byte) (int, error) { for , := range { [1] ^= uint64() // Compute the multiplication , := bits.Mul64(prime128Lower, [1]) += [1]<<prime128Shift + prime128Lower*[0] // Update the values [1] = [0] = } return len(), nil } func ( *sum32) () int { return 4 } func ( *sum32a) () int { return 4 } func ( *sum64) () int { return 8 } func ( *sum64a) () int { return 8 } func ( *sum128) () int { return 16 } func ( *sum128a) () int { return 16 } func ( *sum32) () int { return 1 } func ( *sum32a) () int { return 1 } func ( *sum64) () int { return 1 } func ( *sum64a) () int { return 1 } func ( *sum128) () int { return 1 } func ( *sum128a) () int { return 1 } func ( *sum32) ( []byte) []byte { := uint32(*) return append(, byte(>>24), byte(>>16), byte(>>8), byte()) } func ( *sum32a) ( []byte) []byte { := uint32(*) return append(, byte(>>24), byte(>>16), byte(>>8), byte()) } func ( *sum64) ( []byte) []byte { := uint64(*) return append(, byte(>>56), byte(>>48), byte(>>40), byte(>>32), byte(>>24), byte(>>16), byte(>>8), byte()) } func ( *sum64a) ( []byte) []byte { := uint64(*) return append(, byte(>>56), byte(>>48), byte(>>40), byte(>>32), byte(>>24), byte(>>16), byte(>>8), byte()) } func ( *sum128) ( []byte) []byte { return append(, byte([0]>>56), byte([0]>>48), byte([0]>>40), byte([0]>>32), byte([0]>>24), byte([0]>>16), byte([0]>>8), byte([0]), byte([1]>>56), byte([1]>>48), byte([1]>>40), byte([1]>>32), byte([1]>>24), byte([1]>>16), byte([1]>>8), byte([1]), ) } func ( *sum128a) ( []byte) []byte { return append(, byte([0]>>56), byte([0]>>48), byte([0]>>40), byte([0]>>32), byte([0]>>24), byte([0]>>16), byte([0]>>8), byte([0]), byte([1]>>56), byte([1]>>48), byte([1]>>40), byte([1]>>32), byte([1]>>24), byte([1]>>16), byte([1]>>8), byte([1]), ) } const ( magic32 = "fnv\x01" magic32a = "fnv\x02" magic64 = "fnv\x03" magic64a = "fnv\x04" magic128 = "fnv\x05" magic128a = "fnv\x06" marshaledSize32 = len(magic32) + 4 marshaledSize64 = len(magic64) + 8 marshaledSize128 = len(magic128) + 8*2 ) func ( *sum32) () ([]byte, error) { := make([]byte, 0, marshaledSize32) = append(, magic32...) = appendUint32(, uint32(*)) return , nil } func ( *sum32a) () ([]byte, error) { := make([]byte, 0, marshaledSize32) = append(, magic32a...) = appendUint32(, uint32(*)) return , nil } func ( *sum64) () ([]byte, error) { := make([]byte, 0, marshaledSize64) = append(, magic64...) = appendUint64(, uint64(*)) return , nil } func ( *sum64a) () ([]byte, error) { := make([]byte, 0, marshaledSize64) = append(, magic64a...) = appendUint64(, uint64(*)) return , nil } func ( *sum128) () ([]byte, error) { := make([]byte, 0, marshaledSize128) = append(, magic128...) = appendUint64(, [0]) = appendUint64(, [1]) return , nil } func ( *sum128a) () ([]byte, error) { := make([]byte, 0, marshaledSize128) = append(, magic128a...) = appendUint64(, [0]) = appendUint64(, [1]) return , nil } func ( *sum32) ( []byte) error { if len() < len(magic32) || string([:len(magic32)]) != magic32 { return errors.New("hash/fnv: invalid hash state identifier") } if len() != marshaledSize32 { return errors.New("hash/fnv: invalid hash state size") } * = sum32(readUint32([4:])) return nil } func ( *sum32a) ( []byte) error { if len() < len(magic32a) || string([:len(magic32a)]) != magic32a { return errors.New("hash/fnv: invalid hash state identifier") } if len() != marshaledSize32 { return errors.New("hash/fnv: invalid hash state size") } * = sum32a(readUint32([4:])) return nil } func ( *sum64) ( []byte) error { if len() < len(magic64) || string([:len(magic64)]) != magic64 { return errors.New("hash/fnv: invalid hash state identifier") } if len() != marshaledSize64 { return errors.New("hash/fnv: invalid hash state size") } * = sum64(readUint64([4:])) return nil } func ( *sum64a) ( []byte) error { if len() < len(magic64a) || string([:len(magic64a)]) != magic64a { return errors.New("hash/fnv: invalid hash state identifier") } if len() != marshaledSize64 { return errors.New("hash/fnv: invalid hash state size") } * = sum64a(readUint64([4:])) return nil } func ( *sum128) ( []byte) error { if len() < len(magic128) || string([:len(magic128)]) != magic128 { return errors.New("hash/fnv: invalid hash state identifier") } if len() != marshaledSize128 { return errors.New("hash/fnv: invalid hash state size") } [0] = readUint64([4:]) [1] = readUint64([12:]) return nil } func ( *sum128a) ( []byte) error { if len() < len(magic128a) || string([:len(magic128a)]) != magic128a { return errors.New("hash/fnv: invalid hash state identifier") } if len() != marshaledSize128 { return errors.New("hash/fnv: invalid hash state size") } [0] = readUint64([4:]) [1] = readUint64([12:]) return nil } // readUint32 is semantically the same as [binary.BigEndian.Uint32] // We copied this function because we can not import "encoding/binary" here. func readUint32( []byte) uint32 { _ = [3] return uint32([3]) | uint32([2])<<8 | uint32([1])<<16 | uint32([0])<<24 } // appendUint32 is semantically the same as [binary.BigEndian.AppendUint32] // We copied this function because we can not import "encoding/binary" here. func appendUint32( []byte, uint32) []byte { return append(, byte(>>24), byte(>>16), byte(>>8), byte(), ) } // appendUint64 is semantically the same as [binary.BigEndian.AppendUint64] // We copied this function because we can not import "encoding/binary" here. func appendUint64( []byte, uint64) []byte { return append(, byte(>>56), byte(>>48), byte(>>40), byte(>>32), byte(>>24), byte(>>16), byte(>>8), byte(), ) } // readUint64 is semantically the same as [binary.BigEndian.Uint64] // We copied this function because we can not import "encoding/binary" here. func readUint64( []byte) uint64 { _ = [7] return uint64([7]) | uint64([6])<<8 | uint64([5])<<16 | uint64([4])<<24 | uint64([3])<<32 | uint64([2])<<40 | uint64([1])<<48 | uint64([0])<<56 }