-
Notifications
You must be signed in to change notification settings - Fork 28
/
data_key.go
59 lines (51 loc) · 1.58 KB
/
data_key.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package mmdbwriter
import (
"bytes"
"crypto/sha256"
"fmt"
"hash"
"github.com/maxmind/mmdbwriter/mmdbtype"
)
// KeyGenerator generates a unique key for record values being inserted into the
// Tree. This is used for deduplicating the values in memory. The default
// KeyGenerator will serialize and hash the whole datastructure. This handles
// the general case well but may be inefficient given the particulars of the
// data.
//
// Please be certain that any key you generate is unique. If there is a
// collision with two different values having the same key, one of the
// values will be overwritten.
//
// The returned byte slice is not stored. You may use the same backing
// array between calls.
type KeyGenerator interface {
Key(mmdbtype.DataType) ([]byte, error)
}
var _ KeyGenerator = &keyWriter{}
// keyWriter is similar to dataWriter but it will never use pointers. This
// will produce a unique key for the type.
type keyWriter struct {
*bytes.Buffer
sha256 hash.Hash
key [sha256.Size]byte
}
func newKeyWriter() *keyWriter {
return &keyWriter{Buffer: &bytes.Buffer{}, sha256: sha256.New()}
}
// This is just a quick hack. I am sure there is
// something better.
func (kw *keyWriter) Key(v mmdbtype.DataType) ([]byte, error) {
kw.Truncate(0)
kw.sha256.Reset()
_, err := v.WriteTo(kw)
if err != nil {
return nil, err
}
if _, err := kw.WriteTo(kw.sha256); err != nil {
return nil, fmt.Errorf("writing key to writer: %w", err)
}
return kw.sha256.Sum(kw.key[:0]), nil
}
func (kw *keyWriter) WriteOrWritePointer(t mmdbtype.DataType) (int64, error) {
return t.WriteTo(kw)
}