Skip to content

Commit b62661b

Browse files
committed
feat(sdk): Map Update::RemoveItem into VectorDiff::Remove in UpdateToVectorDiff.
This patch implements the support of `Update::RemoveItem` inside `UpdateToVectorDiff` to emit a `VectorDiff::Remove`.
1 parent e0be1e8 commit b62661b

File tree

1 file changed

+100
-7
lines changed

1 file changed

+100
-7
lines changed

crates/matrix-sdk/src/event_cache/linked_chunk/as_vector.rs

Lines changed: 100 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,19 @@ impl UpdateToVectorDiff {
356356
}
357357
}
358358

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 });
361372
}
362373

363374
Update::DetachLastItems { at: position } => {
@@ -456,6 +467,9 @@ mod tests {
456467
match diff {
457468
VectorDiff::Insert { index, value } => accumulator.insert(index, value),
458469
VectorDiff::Append { values } => accumulator.append(values),
470+
VectorDiff::Remove { index } => {
471+
accumulator.remove(index);
472+
}
459473
diff => unimplemented!("{diff:?}"),
460474
}
461475
}
@@ -599,15 +613,77 @@ mod tests {
599613
&[VectorDiff::Insert { index: 0, value: 'm' }],
600614
);
601615

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+
602680
drop(linked_chunk);
603681
assert!(as_vector.take().is_empty());
604682

605683
// Finally, ensure the “reconstitued” vector is the one expected.
606684
assert_eq!(
607685
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']
611687
);
612688
}
613689

@@ -643,6 +719,7 @@ mod tests {
643719
PushItems { items: Vec<char> },
644720
PushGap,
645721
ReplaceLastGap { items: Vec<char> },
722+
RemoveItem { item: char },
646723
}
647724

648725
fn as_vector_operation_strategy() -> impl Strategy<Value = AsVectorOperation> {
@@ -654,13 +731,16 @@ mod tests {
654731

655732
1 => prop::collection::vec(prop::char::ranges(vec!['a'..='z', 'A'..='Z'].into()), 0..=25)
656733
.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 }),
657737
]
658738
}
659739

660740
proptest! {
661741
#[test]
662742
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)
664744
) {
665745
let mut linked_chunk = LinkedChunk::<10, char, ()>::new_with_update_history();
666746
let mut as_vector = linked_chunk.as_vector().unwrap();
@@ -683,7 +763,17 @@ mod tests {
683763
continue;
684764
};
685765

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");
687777
}
688778
}
689779
}
@@ -699,6 +789,9 @@ mod tests {
699789

700790
vector_from_diffs.append(&mut values);
701791
}
792+
VectorDiff::Remove { index } => {
793+
vector_from_diffs.remove(index);
794+
}
702795
_ => unreachable!(),
703796
}
704797
}

0 commit comments

Comments
 (0)