@@ -386,6 +386,168 @@ fn for_each(factory: HamtFactory, stats: Option<BSStats>, mut cids: CidChecker)
386
386
}
387
387
}
388
388
389
+ fn for_each_ranged ( factory : HamtFactory , stats : Option < BSStats > , mut cids : CidChecker ) {
390
+ let mem = MemoryBlockstore :: default ( ) ;
391
+ let store = TrackingBlockstore :: new ( & mem) ;
392
+
393
+ let mut hamt: Hamt < _ , usize > = factory. new_with_bit_width ( & store, 5 ) ;
394
+
395
+ const RANGE : usize = 200 ;
396
+ for i in 0 ..RANGE {
397
+ hamt. set ( tstring ( i) , i) . unwrap ( ) ;
398
+ }
399
+
400
+ // collect all KV paris by iterating through the entire hamt
401
+ let mut kvs = Vec :: new ( ) ;
402
+ hamt. for_each ( |k, v| {
403
+ assert_eq ! ( k, & tstring( v) ) ;
404
+ kvs. push ( ( k. clone ( ) , * v) ) ;
405
+ Ok ( ( ) )
406
+ } )
407
+ . unwrap ( ) ;
408
+
409
+ // Iterate through the array, requesting pages of different sizes
410
+ for page_size in 0 ..RANGE {
411
+ let mut kvs_variable_page = Vec :: new ( ) ;
412
+ let ( num_traversed, next_key) = hamt
413
+ . for_each_ranged :: < BytesKey , _ > ( None , Some ( page_size) , |k, v| {
414
+ kvs_variable_page. push ( ( k. clone ( ) , * v) ) ;
415
+ Ok ( ( ) )
416
+ } )
417
+ . unwrap ( ) ;
418
+
419
+ assert_eq ! ( num_traversed, page_size) ;
420
+ assert_eq ! ( kvs_variable_page. len( ) , num_traversed) ;
421
+ assert_eq ! ( next_key. unwrap( ) , kvs[ page_size] . 0 ) ;
422
+
423
+ // Items iterated over should match the ordering of for_each
424
+ assert_eq ! ( kvs_variable_page, kvs[ ..page_size] ) ;
425
+ }
426
+
427
+ // Iterate through the array, requesting more items than are remaining
428
+ let ( num_traversed, next_key) = hamt
429
+ . for_each_ranged :: < BytesKey , _ > ( None , Some ( RANGE + 10 ) , |_k, _v| Ok ( ( ) ) )
430
+ . unwrap ( ) ;
431
+ assert_eq ! ( num_traversed, RANGE ) ;
432
+ assert_eq ! ( next_key, None ) ;
433
+
434
+ // Iterate through it again starting at a certain key
435
+ for start_at in 0 ..RANGE as usize {
436
+ let mut kvs_variable_start = Vec :: new ( ) ;
437
+ let ( num_traversed, next_key) = hamt
438
+ . for_each_ranged ( Some ( & kvs[ start_at] . 0 ) , None , |k, v| {
439
+ assert_eq ! ( k, & tstring( v) ) ;
440
+ kvs_variable_start. push ( ( k. clone ( ) , * v) ) ;
441
+
442
+ Ok ( ( ) )
443
+ } )
444
+ . unwrap ( ) ;
445
+
446
+ // No limit specified, iteration should be exhaustive
447
+ assert_eq ! ( next_key, None ) ;
448
+ assert_eq ! ( num_traversed, kvs_variable_start. len( ) ) ;
449
+ assert_eq ! ( kvs_variable_start. len( ) , kvs. len( ) - start_at, ) ;
450
+
451
+ // Items iterated over should match the ordering of for_each
452
+ assert_eq ! ( kvs_variable_start, kvs[ start_at..] ) ;
453
+ }
454
+
455
+ // Chain paginated requests to iterate over entire HAMT
456
+ {
457
+ let mut kvs_paginated_requests = Vec :: new ( ) ;
458
+ let mut iterations = 0 ;
459
+ let mut cursor: Option < BytesKey > = None ;
460
+
461
+ // Request all items in pages of 20 items each
462
+ const PAGE_SIZE : usize = 20 ;
463
+ loop {
464
+ let ( page_size, next) = match cursor {
465
+ Some ( ref start) => hamt
466
+ . for_each_ranged :: < BytesKey , _ > ( Some ( start) , Some ( PAGE_SIZE ) , |k, v| {
467
+ kvs_paginated_requests. push ( ( k. clone ( ) , * v) ) ;
468
+ Ok ( ( ) )
469
+ } )
470
+ . unwrap ( ) ,
471
+ None => hamt
472
+ . for_each_ranged :: < BytesKey , _ > ( None , Some ( PAGE_SIZE ) , |k, v| {
473
+ kvs_paginated_requests. push ( ( k. clone ( ) , * v) ) ;
474
+ Ok ( ( ) )
475
+ } )
476
+ . unwrap ( ) ,
477
+ } ;
478
+ iterations += 1 ;
479
+ assert_eq ! ( page_size, PAGE_SIZE ) ;
480
+ assert_eq ! ( kvs_paginated_requests. len( ) , iterations * PAGE_SIZE ) ;
481
+
482
+ if next. is_none ( ) {
483
+ break ;
484
+ } else {
485
+ assert_eq ! ( next. clone( ) . unwrap( ) , kvs[ ( iterations * PAGE_SIZE ) ] . 0 ) ;
486
+ cursor = next;
487
+ }
488
+ }
489
+
490
+ // should have retrieved all key value pairs in the same order
491
+ assert_eq ! ( kvs_paginated_requests. len( ) , kvs. len( ) , "{}" , iterations) ;
492
+ assert_eq ! ( kvs_paginated_requests, kvs) ;
493
+ // should have used the expected number of iterations
494
+ assert_eq ! ( iterations, RANGE / PAGE_SIZE ) ;
495
+ }
496
+
497
+ let c = hamt. flush ( ) . unwrap ( ) ;
498
+ cids. check_next ( c) ;
499
+
500
+ // Chain paginated requests over a HAMT with committed nodes
501
+ let mut hamt: Hamt < _ , usize > = factory. load_with_bit_width ( & c, & store, 5 ) . unwrap ( ) ;
502
+ {
503
+ let mut kvs_paginated_requests = Vec :: new ( ) ;
504
+ let mut iterations = 0 ;
505
+ let mut cursor: Option < BytesKey > = None ;
506
+
507
+ // Request all items in pages of 20 items each
508
+ const PAGE_SIZE : usize = 20 ;
509
+ loop {
510
+ let ( page_size, next) = match cursor {
511
+ Some ( ref start) => hamt
512
+ . for_each_ranged :: < BytesKey , _ > ( Some ( start) , Some ( PAGE_SIZE ) , |k, v| {
513
+ kvs_paginated_requests. push ( ( k. clone ( ) , * v) ) ;
514
+ Ok ( ( ) )
515
+ } )
516
+ . unwrap ( ) ,
517
+ None => hamt
518
+ . for_each_ranged :: < BytesKey , _ > ( None , Some ( PAGE_SIZE ) , |k, v| {
519
+ kvs_paginated_requests. push ( ( k. clone ( ) , * v) ) ;
520
+ Ok ( ( ) )
521
+ } )
522
+ . unwrap ( ) ,
523
+ } ;
524
+ iterations += 1 ;
525
+ assert_eq ! ( page_size, PAGE_SIZE ) ;
526
+ assert_eq ! ( kvs_paginated_requests. len( ) , iterations * PAGE_SIZE ) ;
527
+
528
+ if next. is_none ( ) {
529
+ break ;
530
+ } else {
531
+ assert_eq ! ( next. clone( ) . unwrap( ) , kvs[ ( iterations * PAGE_SIZE ) ] . 0 ) ;
532
+ cursor = next;
533
+ }
534
+ }
535
+
536
+ // should have retrieved all key value pairs in the same order
537
+ assert_eq ! ( kvs_paginated_requests. len( ) , kvs. len( ) , "{}" , iterations) ;
538
+ assert_eq ! ( kvs_paginated_requests, kvs) ;
539
+ // should have used the expected number of iterations
540
+ assert_eq ! ( iterations, RANGE / PAGE_SIZE ) ;
541
+ }
542
+
543
+ let c = hamt. flush ( ) . unwrap ( ) ;
544
+ cids. check_next ( c) ;
545
+
546
+ if let Some ( stats) = stats {
547
+ assert_eq ! ( * store. stats. borrow( ) , stats) ;
548
+ }
549
+ }
550
+
389
551
#[ cfg( feature = "identity" ) ]
390
552
fn add_and_remove_keys (
391
553
bit_width : u32 ,
@@ -823,6 +985,17 @@ mod test_default {
823
985
super :: for_each ( HamtFactory :: default ( ) , Some ( stats) , cids) ;
824
986
}
825
987
988
+ #[ test]
989
+ fn for_each_ranged ( ) {
990
+ #[ rustfmt:: skip]
991
+ let stats = BSStats { r : 30 , w : 30 , br : 2895 , bw : 2895 } ;
992
+ let cids = CidChecker :: new ( vec ! [
993
+ "bafy2bzacedy4ypl2vedhdqep3llnwko6vrtfiys5flciz2f3c55pl4whlhlqm" ,
994
+ "bafy2bzacedy4ypl2vedhdqep3llnwko6vrtfiys5flciz2f3c55pl4whlhlqm" ,
995
+ ] ) ;
996
+ super :: for_each_ranged ( HamtFactory :: default ( ) , Some ( stats) , cids) ;
997
+ }
998
+
826
999
#[ test]
827
1000
fn clean_child_ordering ( ) {
828
1001
#[ rustfmt:: skip]
0 commit comments