@@ -348,6 +348,145 @@ func (n *node) forEachAt(ctx context.Context, bs cbor.IpldStore, bitWidth uint,
348
348
return nil
349
349
}
350
350
351
+ // Recursive implementation backing ForEach and ForEachAt. Performs a
352
+ // depth-first walk of the tree, beginning at the 'start' index. The 'offset'
353
+ // argument helps us locate the lateral position of the current node so we can
354
+ // figure out the appropriate 'index', since indexes are not stored with values
355
+ // and can only be determined by knowing how far a leaf node is removed from
356
+ // the left-most leaf node.
357
+ // This method also provides the trail of indices at each height/level in the way to the current node, which can be used to formulate a selector suffixes
358
+ func (n * node ) forEachAtTracked (ctx context.Context , bs cbor.IpldStore , trail []int , bitWidth uint , height int , start , offset uint64 , cb func (uint64 , * cbg.Deferred , []int ) error ) error {
359
+ if height == 0 {
360
+ // height=0 means we're at leaf nodes and get to use our callback
361
+ for i , v := range n .values {
362
+ if v != nil {
363
+ ix := offset + uint64 (i )
364
+ if ix < start {
365
+ // if we're here, 'start' is probably somewhere in the
366
+ // middle of this node's elements
367
+ continue
368
+ }
369
+
370
+ // use 'offset' to determine the actual index for this element, it
371
+ // tells us how distant we are from the left-most leaf node
372
+ if err := cb (ix , v , append (trail , i )); err != nil {
373
+ return err
374
+ }
375
+ }
376
+ }
377
+
378
+ return nil
379
+ }
380
+
381
+ subCount := nodesForHeight (bitWidth , height )
382
+ for i , ln := range n .links {
383
+ if ln == nil {
384
+ continue
385
+ }
386
+
387
+ // 'offs' tells us the index of the left-most element of the subtree defined
388
+ // by 'sub'
389
+ offs := offset + (uint64 (i ) * subCount )
390
+ nextOffs := offs + subCount
391
+ // nextOffs > offs checks for overflow at MaxIndex (where the next offset wraps back
392
+ // to 0).
393
+ if nextOffs >= offs && start >= nextOffs {
394
+ // if we're here, 'start' lets us skip this entire sub-tree
395
+ continue
396
+ }
397
+
398
+ subn , err := ln .load (ctx , bs , bitWidth , height - 1 )
399
+ if err != nil {
400
+ return err
401
+ }
402
+
403
+ // recurse into the child node, providing 'offs' to tell it where it's
404
+ // located in the tree
405
+ if err := subn .forEachAtTracked (ctx , bs , append (trail , i ), bitWidth , height - 1 , start , offs , cb ); err != nil {
406
+ return err
407
+ }
408
+ }
409
+ return nil
410
+ }
411
+
412
+ // b *bytes.Buffer, sink func(node ipld.Node) error
413
+ // Recursive implementation backing ForEach and ForEachAt. Performs a
414
+ // depth-first walk of the tree, beginning at the 'start' index. The 'offset'
415
+ // argument helps us locate the lateral position of the current node so we can
416
+ // figure out the appropriate 'index', since indexes are not stored with values
417
+ // and can only be determined by knowing how far a leaf node is removed from
418
+ // the left-most leaf node.
419
+ // This method also provides the trail of indices at each height/level in the way to the current node, which can be used to formulate a selector suffixes
420
+ func (n * node ) forEachAtTrackedWithNodeSink (ctx context.Context , bs cbor.IpldStore , trail []int , bitWidth uint , height int , start , offset uint64 , b * bytes.Buffer , sink cbg.CBORUnmarshaler , cb func (uint64 , * cbg.Deferred , []int ) error ) error {
421
+ if sink != nil {
422
+ if b == nil {
423
+ b = bytes .NewBuffer (nil )
424
+ }
425
+ b .Reset ()
426
+ internalNode , err := n .compact (ctx , bitWidth , height )
427
+ if err != nil {
428
+ return err
429
+ }
430
+ if err := internalNode .MarshalCBOR (b ); err != nil {
431
+ return err
432
+ }
433
+ if err := sink .UnmarshalCBOR (b ); err != nil {
434
+ return err
435
+ }
436
+ }
437
+ if height == 0 {
438
+ // height=0 means we're at leaf nodes and get to use our callback
439
+ for i , v := range n .values {
440
+ if v != nil {
441
+ ix := offset + uint64 (i )
442
+ if ix < start {
443
+ // if we're here, 'start' is probably somewhere in the
444
+ // middle of this node's elements
445
+ continue
446
+ }
447
+
448
+ // use 'offset' to determine the actual index for this element, it
449
+ // tells us how distant we are from the left-most leaf node
450
+ if err := cb (ix , v , append (trail , i )); err != nil {
451
+ return err
452
+ }
453
+ }
454
+ }
455
+
456
+ return nil
457
+ }
458
+
459
+ subCount := nodesForHeight (bitWidth , height )
460
+ for i , ln := range n .links {
461
+ if ln == nil {
462
+ continue
463
+ }
464
+
465
+ // 'offs' tells us the index of the left-most element of the subtree defined
466
+ // by 'sub'
467
+ offs := offset + (uint64 (i ) * subCount )
468
+ nextOffs := offs + subCount
469
+ // nextOffs > offs checks for overflow at MaxIndex (where the next offset wraps back
470
+ // to 0).
471
+ if nextOffs >= offs && start >= nextOffs {
472
+ // if we're here, 'start' lets us skip this entire sub-tree
473
+ continue
474
+ }
475
+
476
+ subn , err := ln .load (ctx , bs , bitWidth , height - 1 )
477
+ if err != nil {
478
+ return err
479
+ }
480
+
481
+ // recurse into the child node, providing 'offs' to tell it where it's
482
+ // located in the tree
483
+ if err := subn .forEachAtTracked (ctx , bs , append (trail , i ), bitWidth , height - 1 , start , offs , cb ); err != nil {
484
+ return err
485
+ }
486
+ }
487
+ return nil
488
+ }
489
+
351
490
var errNoVals = fmt .Errorf ("no values" )
352
491
353
492
// Recursive implementation of FirstSetIndex that's performed on the left-most
@@ -494,6 +633,37 @@ func (n *node) flush(ctx context.Context, bs cbor.IpldStore, bitWidth uint, heig
494
633
return nd , nil
495
634
}
496
635
636
+ // compact converts a node into its internal.Node representation
637
+ func (n * node ) compact (ctx context.Context , bitWidth uint , height int ) (* internal.Node , error ) {
638
+ nd := new (internal.Node )
639
+ nd .Bmap = make ([]byte , bmapBytes (bitWidth ))
640
+
641
+ if height == 0 {
642
+ // leaf node, we're storing values in this node
643
+ for i , val := range n .values {
644
+ if val == nil {
645
+ continue
646
+ }
647
+ nd .Values = append (nd .Values , val )
648
+ // set the bit in the bitmap for this position to indicate its presence
649
+ nd .Bmap [i / 8 ] |= 1 << (uint (i ) % 8 )
650
+ }
651
+ return nd , nil
652
+ }
653
+
654
+ // non-leaf node, we're only storing Links in this node
655
+ for i , ln := range n .links {
656
+ if ln == nil {
657
+ continue
658
+ }
659
+ nd .Links = append (nd .Links , ln .cid )
660
+ // set the bit in the bitmap for this position to indicate its presence
661
+ nd .Bmap [i / 8 ] |= 1 << (uint (i ) % 8 )
662
+ }
663
+
664
+ return nd , nil
665
+ }
666
+
497
667
func (n * node ) setLink (bitWidth uint , i uint64 , l * link ) {
498
668
if n .links == nil {
499
669
if l == nil {
0 commit comments