package hash import ( "fmt" "io" "os" "github.com/cespare/xxhash/v2" ) /* xxhash64 hasher for larc. * xxhash64 is 10-20x faster than SHA-1/SHA-256. * We don't need cryptographic security - revision numbers provide identity. */ const ( // HashSize is the size of xxhash64 output in hex (16 chars) HashSize = 16 ) // Bytes computes xxhash64 of byte slice, returns 16-char hex string func Bytes(data []byte) string { h := xxhash.Sum64(data) return fmt.Sprintf("%016x", h) } // String computes xxhash64 of string, returns 16-char hex string func String(s string) string { h := xxhash.Sum64String(s) return fmt.Sprintf("%016x", h) } // Reader computes xxhash64 of reader content, returns 16-char hex string func Reader(r io.Reader) (string, error) { h := xxhash.New() if _, err := io.Copy(h, r); err != nil { return "", fmt.Errorf("hash reader: %w", err) } return fmt.Sprintf("%016x", h.Sum64()), nil } // File computes xxhash64 of file content, returns 16-char hex string func File(path string) (string, error) { f, err := os.Open(path) if err != nil { return "", fmt.Errorf("hash file open: %w", err) } defer f.Close() return Reader(f) } // Hasher is an incremental hasher for streaming data type Hasher struct { h *xxhash.Digest } // New creates a new incremental hasher func New() *Hasher { return &Hasher{h: xxhash.New()} } // Write implements io.Writer func (h *Hasher) Write(p []byte) (n int, err error) { return h.h.Write(p) } // WriteString writes a string to the hasher func (h *Hasher) WriteString(s string) (n int, err error) { return h.h.WriteString(s) } // Sum returns the current hash as 16-char hex string func (h *Hasher) Sum() string { return fmt.Sprintf("%016x", h.h.Sum64()) } // Reset resets the hasher to initial state func (h *Hasher) Reset() { h.h.Reset() }