github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/routing/keyspace/keyspace.go (about) 1 package keyspace 2 3 import ( 4 "sort" 5 6 "math/big" 7 ) 8 9 // Key represents an identifier in a KeySpace. It holds a reference to the 10 // associated KeySpace, as well references to both the Original identifier, 11 // as well as the new, KeySpace Bytes one. 12 type Key struct { 13 14 // Space is the KeySpace this Key is related to. 15 Space KeySpace 16 17 // Original is the original value of the identifier 18 Original []byte 19 20 // Bytes is the new value of the identifier, in the KeySpace. 21 Bytes []byte 22 } 23 24 // Equal returns whether this key is equal to another. 25 func (k1 Key) Equal(k2 Key) bool { 26 if k1.Space != k2.Space { 27 panic("k1 and k2 not in same key space.") 28 } 29 return k1.Space.Equal(k1, k2) 30 } 31 32 // Less returns whether this key comes before another. 33 func (k1 Key) Less(k2 Key) bool { 34 if k1.Space != k2.Space { 35 panic("k1 and k2 not in same key space.") 36 } 37 return k1.Space.Less(k1, k2) 38 } 39 40 // Distance returns this key's distance to another 41 func (k1 Key) Distance(k2 Key) *big.Int { 42 if k1.Space != k2.Space { 43 panic("k1 and k2 not in same key space.") 44 } 45 return k1.Space.Distance(k1, k2) 46 } 47 48 // KeySpace is an object used to do math on identifiers. Each keyspace has its 49 // own properties and rules. See XorKeySpace. 50 type KeySpace interface { 51 52 // Key converts an identifier into a Key in this space. 53 Key([]byte) Key 54 55 // Equal returns whether keys are equal in this key space 56 Equal(Key, Key) bool 57 58 // Distance returns the distance metric in this key space 59 Distance(Key, Key) *big.Int 60 61 // Less returns whether the first key is smaller than the second. 62 Less(Key, Key) bool 63 } 64 65 // byDistanceToCenter is a type used to sort Keys by proximity to a center. 66 type byDistanceToCenter struct { 67 Center Key 68 Keys []Key 69 } 70 71 func (s byDistanceToCenter) Len() int { 72 return len(s.Keys) 73 } 74 75 func (s byDistanceToCenter) Swap(i, j int) { 76 s.Keys[i], s.Keys[j] = s.Keys[j], s.Keys[i] 77 } 78 79 func (s byDistanceToCenter) Less(i, j int) bool { 80 a := s.Center.Distance(s.Keys[i]) 81 b := s.Center.Distance(s.Keys[j]) 82 return a.Cmp(b) == -1 83 } 84 85 // SortByDistance takes a KeySpace, a center Key, and a list of Keys toSort. 86 // It returns a new list, where the Keys toSort have been sorted by their 87 // distance to the center Key. 88 func SortByDistance(sp KeySpace, center Key, toSort []Key) []Key { 89 toSortCopy := make([]Key, len(toSort)) 90 copy(toSortCopy, toSort) 91 bdtc := &byDistanceToCenter{ 92 Center: center, 93 Keys: toSortCopy, // copy 94 } 95 sort.Sort(bdtc) 96 return bdtc.Keys 97 }