go-dht/kademlia/id.go
kademlia/id.goRaw
1package kademlia
2
3import (
4 "bytes"
5 "crypto/rand"
6 "crypto/sha256"
7 "encoding/hex"
8)
9
10type ID [B]byte
11
12func NewID() (ID, error) {
13 b := make([]byte, 32)
14 _, err := rand.Read(b)
15 if err != nil {
16 return ID{}, err
17 }
18 var id ID
19 copy(id[:], b[:B])
20 return id, nil
21}
22
23func (id ID) String() string {
24 return hex.EncodeToString(id[:])
25}
26
27func (id ID) MarshalText() ([]byte, error) {
28 return []byte(hex.EncodeToString(id[:])), nil
29}
30
31func (id *ID) UnmarshalText(data []byte) error {
32 var err error
33 var idFromStr ID
34 idFromStr, err = IDFromString(string(data))
35 if err != nil {
36 return err
37 }
38 copy(id[:], idFromStr[:])
39 return nil
40}
41
42func IDFromString(s string) (ID, error) {
43 b, err := hex.DecodeString(s)
44 if err != nil {
45 return ID{}, err
46 }
47 var id ID
48 copy(id[:], b[:B])
49 return id, nil
50}
51
52func (idA ID) Equal(idB ID) bool {
53 return bytes.Equal(idA[:], idB[:])
54}
55
56// Cmp returns true if idA > idB
57func (idA ID) Cmp(idB ID) bool {
58 for i := 0; i < len(idA); i++ {
59 if idA[i] != idB[i] {
60 return idA[i] > idB[i]
61 }
62 }
63 return false
64}
65
66func (idA ID) Distance(idB ID) ID {
67 var d ID
68 for i := 0; i < B; i++ {
69 d[i] = idA[i] ^ idB[i]
70 }
71 return d
72}
73
74func HashData(d []byte) ID {
75 h := sha256.Sum256(d)
76 var r ID
77 copy(r[:], h[:20])
78 return r
79}