| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- package k_nearest_nodes
- import (
- "hash/maphash"
- "github.com/anacrolix/multiless"
- "github.com/benbjohnson/immutable"
- "github.com/anacrolix/dht/v2/int160"
- "github.com/anacrolix/dht/v2/krpc"
- )
- type Key = krpc.NodeInfo
- type Elem struct {
- Key
- Data interface{}
- }
- type Type struct {
- inner *immutable.SortedMap
- k int
- }
- func New(target int160.T, k int) Type {
- seed := maphash.MakeSeed()
- return Type{
- k: k,
- inner: immutable.NewSortedMap(lessComparer{less: func(_l, _r interface{}) bool {
- l := _l.(Key)
- r := _r.(Key)
- return multiless.New().Cmp(
- l.ID.Int160().Distance(target).Cmp(r.ID.Int160().Distance(target)),
- ).Lazy(func() multiless.Computation {
- var lh, rh maphash.Hash
- lh.SetSeed(seed)
- rh.SetSeed(seed)
- lh.WriteString(l.Addr.String())
- rh.WriteString(r.Addr.String())
- return multiless.New().Int64(int64(lh.Sum64()), int64(rh.Sum64()))
- }).Less()
- }}),
- }
- }
- func (me *Type) Range(f func(Elem)) {
- iter := me.inner.Iterator()
- for !iter.Done() {
- key, value := iter.Next()
- f(Elem{
- Key: key.(Key),
- Data: value,
- })
- }
- }
- func (me Type) Len() int {
- return me.inner.Len()
- }
- func (me Type) Push(elem Elem) Type {
- me.inner = me.inner.Set(elem.Key, elem.Data)
- for me.inner.Len() > me.k {
- iter := me.inner.Iterator()
- iter.Last()
- key, _ := iter.Next()
- me.inner = me.inner.Delete(key)
- }
- return me
- }
- func (me Type) Farthest() (elem Elem) {
- iter := me.inner.Iterator()
- iter.Last()
- if iter.Done() {
- panic(me.k)
- }
- key, value := iter.Next()
- return Elem{
- Key: key.(Key),
- Data: value,
- }
- }
- func (me Type) Full() bool {
- return me.Len() >= me.k
- }
- type lessFunc func(l, r interface{}) bool
- type lessComparer struct {
- less lessFunc
- }
- func (me lessComparer) Compare(i, j interface{}) int {
- if me.less(i, j) {
- return -1
- } else if me.less(j, i) {
- return 1
- } else {
- return 0
- }
- }
|