@@ -13,6 +13,8 @@ import (
1313 "github.com/probe-lab/go-libdht/kad/trie"
1414)
1515
16+ var zeroKey = bit256 .ZeroKey ()
17+
1618// AllEntries returns all entries (key + value) stored in the trie `t` sorted
1719// by their keys in the supplied `order`.
1820func AllEntries [K0 kad.Key [K0 ], K1 kad.Key [K1 ], D any ](t * trie.Trie [K0 , D ], order K1 ) []* trie.Entry [K0 , D ] {
@@ -313,48 +315,51 @@ func AllocateToKClosest[K kad.Key[K], V0 any, V1 comparable](items *trie.Trie[K,
313315//
314316// Returns a map of destination values to their allocated items.
315317func allocateToKClosestAtDepth [K kad.Key [K ], V0 any , V1 comparable ](items * trie.Trie [K , V0 ], dests * trie.Trie [K , V1 ], k , depth int ) map [V1 ][]V0 {
316- m := make (map [V1 ][]V0 )
317318 if k == 0 {
318- return m
319+ return nil
320+ }
321+ destBranches := []* trie.Trie [K , V1 ]{
322+ dests .Branch (0 ),
323+ dests .Branch (1 ),
324+ }
325+ destValues := [][]V1 {
326+ AllValues (dests .Branch (0 ), zeroKey ),
327+ AllValues (dests .Branch (1 ), zeroKey ),
319328 }
320- for i := range 2 {
329+ if dests .IsLeaf () {
330+ if ! dests .HasKey () {
331+ return nil
332+ }
333+ b := int ((* dests .Key ()).Bit (depth ))
334+ destValues [b ] = []V1 {dests .Data ()}
335+ destValues [1 - b ] = nil
336+ destBranches [b ] = dests
337+ destBranches [1 - b ] = nil
338+ }
339+ m := make (map [V1 ][]V0 , len (destValues [0 ])+ len (destValues [1 ]))
340+ for i := range destValues {
321341 // Assign all items from branch i
322342
343+ matchingDestsBranch := destBranches [i ]
344+ otherDestsBranch := destBranches [1 - i ]
345+ matchingDests := destValues [i ]
346+ otherDests := destValues [1 - i ]
347+
323348 matchingItemsBranch := items .Branch (i )
324- matchingItems := AllValues ( matchingItemsBranch , bit256 . ZeroKey ())
325- if len ( matchingItems ) == 0 {
349+ if matchingItemsBranch == nil || matchingItemsBranch . IsEmptyLeaf () {
350+ // No matching items
326351 if ! items .IsNonEmptyLeaf () || int ((* items .Key ()).Bit (depth )) != i {
327352 // items' current branch is empty, skip it
328353 continue
329354 }
330355 // items' current branch contains a single leaf
331- matchingItems = []V0 {items .Data ()}
332356 matchingItemsBranch = items
333357 }
334-
335- matchingDestsBranch := dests .Branch (i )
336- otherDestsBranch := dests .Branch (1 - i )
337- matchingDests := AllValues (matchingDestsBranch , bit256 .ZeroKey ())
338- otherDests := AllValues (otherDestsBranch , bit256 .ZeroKey ())
339- if dests .IsLeaf () {
340- // Single key (leaf) in dests
341- if dests .IsNonEmptyLeaf () {
342- if int ((* dests .Key ()).Bit (depth )) == i {
343- // Leaf matches current branch
344- matchingDests = []V1 {dests .Data ()}
345- matchingDestsBranch = dests
346- } else {
347- // Leaf matches other branch
348- otherDests = []V1 {dests .Data ()}
349- otherDestsBranch = dests
350- }
351- } else {
352- // Empty leaf, no dests to allocate items.
353- return m
354- }
355- }
356-
357358 if nMatchingDests := len (matchingDests ); nMatchingDests <= k {
359+ matchingItems := AllValues (matchingItemsBranch , zeroKey )
360+ if len (matchingItems ) == 0 {
361+ matchingItems = []V0 {items .Data ()}
362+ }
358363 // Allocate matching items to the matching dests branch
359364 for _ , dest := range matchingDests {
360365 m [dest ] = append (m [dest ], matchingItems ... )
0 commit comments