larc r14

81 lines ยท 1.8 KB Raw
1 package hash
2
3 import (
4 "fmt"
5 "io"
6 "os"
7
8 "github.com/cespare/xxhash/v2"
9 )
10
11 /* xxhash64 hasher for larc.
12 * xxhash64 is 10-20x faster than SHA-1/SHA-256.
13 * We don't need cryptographic security - revision numbers provide identity. */
14
15 const (
16 // HashSize is the size of xxhash64 output in hex (16 chars)
17 HashSize = 16
18 )
19
20 // Bytes computes xxhash64 of byte slice, returns 16-char hex string
21 func Bytes(data []byte) string {
22 h := xxhash.Sum64(data)
23 return fmt.Sprintf("%016x", h)
24 }
25
26 // String computes xxhash64 of string, returns 16-char hex string
27 func String(s string) string {
28 h := xxhash.Sum64String(s)
29 return fmt.Sprintf("%016x", h)
30 }
31
32 // Reader computes xxhash64 of reader content, returns 16-char hex string
33 func Reader(r io.Reader) (string, error) {
34 h := xxhash.New()
35 if _, err := io.Copy(h, r); err != nil {
36 return "", fmt.Errorf("hash reader: %w", err)
37 }
38 return fmt.Sprintf("%016x", h.Sum64()), nil
39 }
40
41 // File computes xxhash64 of file content, returns 16-char hex string
42 func File(path string) (string, error) {
43 f, err := os.Open(path)
44 if err != nil {
45 return "", fmt.Errorf("hash file open: %w", err)
46 }
47 defer f.Close()
48
49 return Reader(f)
50 }
51
52 // Hasher is an incremental hasher for streaming data
53 type Hasher struct {
54 h *xxhash.Digest
55 }
56
57 // New creates a new incremental hasher
58 func New() *Hasher {
59 return &Hasher{h: xxhash.New()}
60 }
61
62 // Write implements io.Writer
63 func (h *Hasher) Write(p []byte) (n int, err error) {
64 return h.h.Write(p)
65 }
66
67 // WriteString writes a string to the hasher
68 func (h *Hasher) WriteString(s string) (n int, err error) {
69 return h.h.WriteString(s)
70 }
71
72 // Sum returns the current hash as 16-char hex string
73 func (h *Hasher) Sum() string {
74 return fmt.Sprintf("%016x", h.h.Sum64())
75 }
76
77 // Reset resets the hasher to initial state
78 func (h *Hasher) Reset() {
79 h.h.Reset()
80 }
81