navidrome/utils/hasher/hasher.go

64 lines
1.2 KiB
Go

package hasher
import (
"hash/maphash"
"strconv"
"github.com/navidrome/navidrome/utils/random"
)
var instance = NewHasher()
func Reseed(id string) {
instance.Reseed(id)
}
func SetSeed(id string, seed string) {
instance.SetSeed(id, seed)
}
func HashFunc() func(id, str string) uint64 {
return instance.HashFunc()
}
type Hasher struct {
seeds map[string]string
hashSeed maphash.Seed
}
func NewHasher() *Hasher {
h := new(Hasher)
h.seeds = make(map[string]string)
h.hashSeed = maphash.MakeSeed()
return h
}
// SetSeed sets a seed for the given id
func (h *Hasher) SetSeed(id string, seed string) {
h.seeds[id] = seed
}
// Reseed generates a new random seed for the given id
func (h *Hasher) Reseed(id string) {
_ = h.reseed(id)
}
func (h *Hasher) reseed(id string) string {
seed := strconv.FormatUint(random.Uint64(), 36)
h.seeds[id] = seed
return seed
}
// HashFunc returns a function that hashes a string using the seed for the given id
func (h *Hasher) HashFunc() func(id, str string) uint64 {
return func(id, str string) uint64 {
var seed string
var ok bool
if seed, ok = h.seeds[id]; !ok {
seed = h.reseed(id)
}
return maphash.Bytes(h.hashSeed, []byte(seed+str))
}
}