Skip to content

Commit

Permalink
fix(linked chunk): in LinkedChunk::ritems_from, skip as long as we're…
Browse files Browse the repository at this point in the history
… on the right chunk

The previous code would skip based on the position's index, but not the
position's chunk. It could be that the position's chunk is different
from the first items chunk, as shown in the example, where the linked
chunk ends with a gap; in this case, the position's index would be 0,
while the first chunk found while iterating backwards had 3 items. As a
result, items 'd' and 'e' would be skipped incorrectly.

The fix is to take into account the chunk id when skipping over items.
  • Loading branch information
bnjbvr committed Dec 17, 2024
1 parent 0ca35d6 commit 5d8ad3a
Showing 1 changed file with 23 additions and 2 deletions.
25 changes: 23 additions & 2 deletions crates/matrix-sdk-common/src/linked_chunk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,9 @@ impl<const CAP: usize, Item, Gap> LinkedChunk<CAP, Item, Gap> {
.skip_while({
let expected_index = position.index();

move |(Position(_chunk_identifier, item_index), _item)| {
*item_index != expected_index
move |(Position(chunk_identifier, item_index), _item)| {
*chunk_identifier == position.chunk_identifier()
&& *item_index != expected_index
}
}))
}
Expand Down Expand Up @@ -1813,6 +1814,26 @@ mod tests {
assert_matches!(iterator.next(), None);
}

#[test]
fn test_ritems_with_final_gap() -> Result<(), Error> {
let mut linked_chunk = LinkedChunk::<3, char, ()>::new();
linked_chunk.push_items_back(['a', 'b']);
linked_chunk.push_gap_back(());
linked_chunk.push_items_back(['c', 'd', 'e']);
linked_chunk.push_gap_back(());

let mut iterator = linked_chunk.ritems();

assert_matches!(iterator.next(), Some((Position(ChunkIdentifier(2), 2), 'e')));
assert_matches!(iterator.next(), Some((Position(ChunkIdentifier(2), 1), 'd')));
assert_matches!(iterator.next(), Some((Position(ChunkIdentifier(2), 0), 'c')));
assert_matches!(iterator.next(), Some((Position(ChunkIdentifier(0), 1), 'b')));
assert_matches!(iterator.next(), Some((Position(ChunkIdentifier(0), 0), 'a')));
assert_matches!(iterator.next(), None);

Ok(())
}

#[test]
fn test_ritems_empty() {
let linked_chunk = LinkedChunk::<2, char, ()>::new();
Expand Down

0 comments on commit 5d8ad3a

Please sign in to comment.