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  }