@@ -121,18 +121,24 @@ impl RangeSet {
121121 }
122122 Some ( _) | None => false ,
123123 } ;
124+
125+ let removed_end = self
126+ . 0
127+ . extract_if ( ( Excluded ( x. start ) , Excluded ( x. end ) ) , |_, _| true )
128+ . last ( )
129+ . map ( |( _start, end) | end) ;
130+
124131 let mut after = false ;
125- while let Some ( ( start, end) ) = self . succ ( x. start ) {
126- if start >= x. end {
127- break ;
128- }
132+
133+ if let Some ( removed_end) = removed_end {
129134 after = true ;
130- self . 0 . remove ( & start ) ;
131- if end > x. end {
132- self . 0 . insert ( x . end , end ) ;
133- break ;
135+
136+ let over_removed = removed_end > x. end ;
137+ if over_removed {
138+ self . 0 . insert ( x . end , removed_end ) ;
134139 }
135140 }
141+
136142 before || after
137143 }
138144
@@ -382,7 +388,21 @@ mod tests {
382388 }
383389
384390 #[ test]
385- fn insert_merges_abutting_range ( ) {
391+ fn insert_extends_prev_joint_range ( ) {
392+ // given
393+ let mut set = RangeSet :: new ( ) ;
394+ set. insert ( 0 ..10 ) ;
395+
396+ // when
397+ set. insert ( 10 ..20 ) ;
398+
399+ // then
400+ let expected_inner = BTreeMap :: from_iter ( [ ( 0 , 20 ) ] ) ;
401+ assert_eq ! ( set. 0 , expected_inner, "ranges should have merged" ) ;
402+ }
403+
404+ #[ test]
405+ fn insert_merges_touching_range ( ) {
386406 // given
387407 let mut set = RangeSet :: new ( ) ;
388408 set. insert ( 10 ..20 ) ;
@@ -392,7 +412,7 @@ mod tests {
392412
393413 // then
394414 let expected_inner = BTreeMap :: from_iter ( [ ( 5 , 20 ) ] ) ;
395- assert_eq ! ( set. 0 , expected_inner, "Ranges should have merged." ) ;
415+ assert_eq ! ( set. 0 , expected_inner, "ranges should have merged." ) ;
396416 }
397417
398418 #[ test]
@@ -406,7 +426,7 @@ mod tests {
406426
407427 // then
408428 let expected_inner = BTreeMap :: from_iter ( [ ( 10 , 25 ) ] ) ;
409- assert_eq ! ( set. 0 , expected_inner, "Ranges should have merged." ) ;
429+ assert_eq ! ( set. 0 , expected_inner, "ranges should have merged." ) ;
410430 }
411431
412432 #[ test]
@@ -416,11 +436,15 @@ mod tests {
416436 set. insert ( 10 ..20 ) ;
417437
418438 // when
419- set. insert ( 12 .. 15 ) ;
439+ let insert_result = set. insert ( 14 .. 16 ) ;
420440
421441 // then
422442 let expected_inner = BTreeMap :: from_iter ( [ ( 10 , 20 ) ] ) ;
423- assert_eq ! ( set. 0 , expected_inner, "Ranges should have merged." ) ;
443+ assert_eq ! ( set. 0 , expected_inner, "insertion should be ignored" ) ;
444+ assert ! (
445+ !insert_result,
446+ "insert should return false when inserting an already contained range"
447+ ) ;
424448 }
425449
426450 #[ test]
@@ -435,6 +459,158 @@ mod tests {
435459
436460 // then
437461 let expected_inner = BTreeMap :: from_iter ( [ ( 0 , 30 ) ] ) ;
438- assert_eq ! ( set. 0 , expected_inner, "Ranges should have merged." ) ;
462+ assert_eq ! ( set. 0 , expected_inner, "existing ranges should have merged" ) ;
463+ }
464+
465+ #[ test]
466+ fn remove_splits_contained_range ( ) {
467+ // given
468+ let mut set = RangeSet :: new ( ) ;
469+ set. insert ( 0 ..10 ) ;
470+
471+ // when
472+ let changed = set. remove ( 2 ..8 ) ;
473+
474+ // then
475+ assert ! ( changed) ;
476+ let expected_inner = BTreeMap :: from_iter ( [ ( 0 , 2 ) , ( 8 , 10 ) ] ) ;
477+ assert_eq ! ( set. 0 , expected_inner, "range should have split into two" ) ;
478+ }
479+
480+ #[ test]
481+ fn remove_trims_start_of_range ( ) {
482+ // given
483+ let mut set = RangeSet :: new ( ) ;
484+ set. insert ( 10 ..20 ) ;
485+
486+ // when
487+ let changed = set. remove ( 5 ..15 ) ;
488+
489+ // then
490+ assert ! ( changed) ;
491+ let expected_inner = BTreeMap :: from_iter ( [ ( 15 , 20 ) ] ) ;
492+ assert_eq ! (
493+ set. 0 , expected_inner,
494+ "start of range should have been trimmed"
495+ ) ;
496+ }
497+
498+ #[ test]
499+ fn remove_trims_end_of_range ( ) {
500+ // given
501+ let mut set = RangeSet :: new ( ) ;
502+ set. insert ( 0 ..10 ) ;
503+
504+ // when
505+ let changed = set. remove ( 5 ..15 ) ;
506+
507+ // then
508+ assert ! ( changed) ;
509+ let expected_inner = BTreeMap :: from_iter ( [ ( 0 , 5 ) ] ) ;
510+ assert_eq ! (
511+ set. 0 , expected_inner,
512+ "end of range should have been trimmed"
513+ ) ;
514+ }
515+
516+ #[ test]
517+ fn remove_swallows_multiple_ranges ( ) {
518+ // given
519+ let mut set = RangeSet :: new ( ) ;
520+ set. insert ( 0 ..5 ) ;
521+ set. insert ( 10 ..15 ) ;
522+ set. insert ( 20 ..25 ) ;
523+
524+ // when
525+ let changed = set. remove ( 0 ..25 ) ;
526+
527+ // then
528+ assert ! ( changed) ;
529+ let expected_inner = BTreeMap :: new ( ) ;
530+ assert_eq ! (
531+ set. 0 , expected_inner,
532+ "all ranges should be gone as the removal swallowed them"
533+ ) ;
534+ }
535+
536+ #[ test]
537+ fn remove_specific_range_in_set ( ) {
538+ // given
539+ let mut set = RangeSet :: new ( ) ;
540+ set. insert ( 10 ..20 ) ;
541+
542+ // when
543+ let changed = set. remove ( 10 ..20 ) ;
544+
545+ // then
546+ assert ! ( changed) ;
547+ let expected_inner = BTreeMap :: new ( ) ;
548+ assert_eq ! ( set. 0 , expected_inner, "set should be empty" ) ;
549+ }
550+
551+ #[ test]
552+ fn removing_range_touching_existing_ranges_is_ignored ( ) {
553+ // given
554+ let mut set = RangeSet :: new ( ) ;
555+ set. insert ( 10 ..20 ) ;
556+
557+ // when
558+ let changed_start = set. remove ( 0 ..10 ) ;
559+ let changed_end = set. remove ( 20 ..30 ) ;
560+
561+ // then
562+ assert ! ( !changed_start) ;
563+ assert ! ( !changed_end) ;
564+ let expected_inner = BTreeMap :: from_iter ( [ ( 10 , 20 ) ] ) ;
565+ assert_eq ! (
566+ set. 0 , expected_inner,
567+ "touching ranges should not remove anything."
568+ ) ;
569+ }
570+
571+ #[ test]
572+ fn removing_range_crossing_existing_ranges_that_should_be_trimmed ( ) {
573+ // given
574+ let mut set = RangeSet :: new ( ) ;
575+ set. insert ( 0 ..5 ) ;
576+ set. insert ( 10 ..15 ) ;
577+
578+ // when
579+ let changed = set. remove ( 4 ..11 ) ;
580+
581+ // then
582+ assert ! ( changed) ;
583+ let expected_inner = BTreeMap :: from_iter ( [ ( 0 , 4 ) , ( 11 , 15 ) ] ) ;
584+ assert_eq ! ( set. 0 , expected_inner, "existing ranges should be trimmed" ) ;
585+ }
586+
587+ #[ test]
588+ fn remove_crossing_range_trims_start ( ) {
589+ // given
590+ let mut set = RangeSet :: new ( ) ;
591+ set. insert ( 10 ..20 ) ;
592+
593+ // when
594+ let changed = set. remove ( 9 ..12 ) ;
595+
596+ // then
597+ assert ! ( changed) ;
598+ let expected_inner = BTreeMap :: from_iter ( [ ( 12 , 20 ) ] ) ;
599+ assert_eq ! ( set. 0 , expected_inner) ;
600+ }
601+
602+ #[ test]
603+ fn remove_no_overlap_before_and_after ( ) {
604+ // given
605+ let mut set = RangeSet :: new ( ) ;
606+ set. insert ( 10 ..20 ) ;
607+
608+ // when
609+ let changed = set. remove ( 0 ..5 ) ;
610+
611+ // then
612+ assert ! ( !changed) ;
613+ let expected_inner = BTreeMap :: from_iter ( [ ( 10 , 20 ) ] ) ;
614+ assert_eq ! ( set. 0 , expected_inner, "disjoint removals should be ignored" ) ;
439615 }
440616}
0 commit comments