@@ -356,8 +356,19 @@ impl UpdateToVectorDiff {
356
356
}
357
357
}
358
358
359
- Update :: RemoveItem { at } => {
360
- todo ! ( )
359
+ Update :: RemoveItem { at : position } => {
360
+ let ( offset, ( _chunk_index, chunk_length) ) = self . map_to_offset ( position) ;
361
+
362
+ // Remove one item to the chunk in `self.chunks`.
363
+ * chunk_length -= 1 ;
364
+
365
+ // See `reattaching` to learn more.
366
+ if reattaching {
367
+ continue ;
368
+ }
369
+
370
+ // Let's emit a `VectorDiff::Remove`.
371
+ diffs. push ( VectorDiff :: Remove { index : offset } ) ;
361
372
}
362
373
363
374
Update :: DetachLastItems { at : position } => {
@@ -456,6 +467,9 @@ mod tests {
456
467
match diff {
457
468
VectorDiff :: Insert { index, value } => accumulator. insert ( index, value) ,
458
469
VectorDiff :: Append { values } => accumulator. append ( values) ,
470
+ VectorDiff :: Remove { index } => {
471
+ accumulator. remove ( index) ;
472
+ }
459
473
diff => unimplemented ! ( "{diff:?}" ) ,
460
474
}
461
475
}
@@ -599,15 +613,77 @@ mod tests {
599
613
& [ VectorDiff :: Insert { index : 0 , value : 'm' } ] ,
600
614
) ;
601
615
616
+ let removed_item = linked_chunk
617
+ . remove_item_at ( linked_chunk. item_position ( |item| * item == 'c' ) . unwrap ( ) )
618
+ . unwrap ( ) ;
619
+ assert_eq ! ( removed_item, 'c' ) ;
620
+ assert_items_eq ! (
621
+ linked_chunk,
622
+ [ 'm' , 'a' , 'w' ] [ 'x' ] [ 'y' , 'z' , 'b' ] [ 'd' ] [ 'i' , 'j' , 'k' ] [ 'l' ] [ 'e' , 'f' , 'g' ] [ 'h' ]
623
+ ) ;
624
+
625
+ // From an `ObservableVector` point of view, it would look like:
626
+ //
627
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
628
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
629
+ // | m | a | w | x | y | z | b | d | i | j | k | l | e | f | g | h |
630
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
631
+ // ^
632
+ // |
633
+ // `c` has been removed
634
+ apply_and_assert_eq ( & mut accumulator, as_vector. take ( ) , & [ VectorDiff :: Remove { index : 7 } ] ) ;
635
+
636
+ let removed_item = linked_chunk
637
+ . remove_item_at ( linked_chunk. item_position ( |item| * item == 'z' ) . unwrap ( ) )
638
+ . unwrap ( ) ;
639
+ assert_eq ! ( removed_item, 'z' ) ;
640
+ assert_items_eq ! (
641
+ linked_chunk,
642
+ [ 'm' , 'a' , 'w' ] [ 'x' ] [ 'y' , 'b' ] [ 'd' ] [ 'i' , 'j' , 'k' ] [ 'l' ] [ 'e' , 'f' , 'g' ] [ 'h' ]
643
+ ) ;
644
+
645
+ // From an `ObservableVector` point of view, it would look like:
646
+ //
647
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
648
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
649
+ // | m | a | w | x | y | b | d | i | j | k | l | e | f | g | h |
650
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
651
+ // ^
652
+ // |
653
+ // `z` has been removed
654
+ apply_and_assert_eq ( & mut accumulator, as_vector. take ( ) , & [ VectorDiff :: Remove { index : 5 } ] ) ;
655
+
656
+ linked_chunk
657
+ . insert_items_at ( [ 'z' ] , linked_chunk. item_position ( |item| * item == 'h' ) . unwrap ( ) )
658
+ . unwrap ( ) ;
659
+
660
+ assert_items_eq ! (
661
+ linked_chunk,
662
+ [ 'm' , 'a' , 'w' ] [ 'x' ] [ 'y' , 'b' ] [ 'd' ] [ 'i' , 'j' , 'k' ] [ 'l' ] [ 'e' , 'f' , 'g' ] [ 'z' , 'h' ]
663
+ ) ;
664
+
665
+ // From an `ObservableVector` point of view, it would look like:
666
+ //
667
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
668
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
669
+ // | m | a | w | x | y | b | d | i | j | k | l | e | f | g | z | h |
670
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
671
+ // ^^^^
672
+ // |
673
+ // new!
674
+ apply_and_assert_eq (
675
+ & mut accumulator,
676
+ as_vector. take ( ) ,
677
+ & [ VectorDiff :: Insert { index : 14 , value : 'z' } ] ,
678
+ ) ;
679
+
602
680
drop ( linked_chunk) ;
603
681
assert ! ( as_vector. take( ) . is_empty( ) ) ;
604
682
605
683
// Finally, ensure the “reconstitued” vector is the one expected.
606
684
assert_eq ! (
607
685
accumulator,
608
- vector![
609
- 'm' , 'a' , 'w' , 'x' , 'y' , 'z' , 'b' , 'c' , 'd' , 'i' , 'j' , 'k' , 'l' , 'e' , 'f' , 'g' , 'h'
610
- ]
686
+ vector![ 'm' , 'a' , 'w' , 'x' , 'y' , 'b' , 'd' , 'i' , 'j' , 'k' , 'l' , 'e' , 'f' , 'g' , 'z' , 'h' ]
611
687
) ;
612
688
}
613
689
@@ -643,6 +719,7 @@ mod tests {
643
719
PushItems { items : Vec < char > } ,
644
720
PushGap ,
645
721
ReplaceLastGap { items : Vec < char > } ,
722
+ RemoveItem { item : char } ,
646
723
}
647
724
648
725
fn as_vector_operation_strategy ( ) -> impl Strategy < Value = AsVectorOperation > {
@@ -654,13 +731,16 @@ mod tests {
654
731
655
732
1 => prop:: collection:: vec( prop:: char :: ranges( vec![ 'a' ..='z' , 'A' ..='Z' ] . into( ) ) , 0 ..=25 )
656
733
. prop_map( |items| AsVectorOperation :: ReplaceLastGap { items } ) ,
734
+
735
+ 1 => prop:: char :: ranges( vec![ 'a' ..='z' , 'A' ..='Z' ] . into( ) )
736
+ . prop_map( |item| AsVectorOperation :: RemoveItem { item } ) ,
657
737
]
658
738
}
659
739
660
740
proptest ! {
661
741
#[ test]
662
742
fn as_vector_is_correct(
663
- operations in prop:: collection:: vec( as_vector_operation_strategy( ) , 10 ..=50 )
743
+ operations in prop:: collection:: vec( as_vector_operation_strategy( ) , 50 ..=200 )
664
744
) {
665
745
let mut linked_chunk = LinkedChunk :: <10 , char , ( ) >:: new_with_update_history( ) ;
666
746
let mut as_vector = linked_chunk. as_vector( ) . unwrap( ) ;
@@ -683,7 +763,17 @@ mod tests {
683
763
continue ;
684
764
} ;
685
765
686
- linked_chunk. replace_gap_at( items, gap_identifier) . unwrap( ) ;
766
+ linked_chunk. replace_gap_at( items, gap_identifier) . expect( "Failed to replace a gap" ) ;
767
+ }
768
+
769
+ AsVectorOperation :: RemoveItem { item: expected_item } => {
770
+ let Some ( position) = linked_chunk
771
+ . items( ) . find_map( |( position, item) | ( * item == expected_item) . then_some( position) )
772
+ else {
773
+ continue ;
774
+ } ;
775
+
776
+ linked_chunk. remove_item_at( position) . expect( "Failed to remove an item" ) ;
687
777
}
688
778
}
689
779
}
@@ -699,6 +789,9 @@ mod tests {
699
789
700
790
vector_from_diffs. append( & mut values) ;
701
791
}
792
+ VectorDiff :: Remove { index } => {
793
+ vector_from_diffs. remove( index) ;
794
+ }
702
795
_ => unreachable!( ) ,
703
796
}
704
797
}
0 commit comments