Skip to content

Commit 728d646

Browse files
committed
fix(common): AsVector clears its internal state on Update::Clear.
This patch fixes a bug in `AsVector`: when an `Update::Clear` value is received, `AsVector`'s internal state must be cleared too, i.e. the `UpdateToVectorDiff::chunks` field should be reset to an initial value! This patch adds a test to ensure this works as expected.
1 parent ca397dc commit 728d646

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

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

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,12 @@ impl UpdateToVectorDiff {
302302
self.chunks.insert(next_chunk_index, (*new, 0));
303303
}
304304

305+
// First chunk!
306+
(None, None) if self.chunks.is_empty() => {
307+
self.chunks.push_back((*new, 0));
308+
}
309+
310+
// Impossible state.
305311
(None, None) => {
306312
unreachable!(
307313
"Inserting new chunk with no previous nor next chunk identifiers \
@@ -407,6 +413,9 @@ impl UpdateToVectorDiff {
407413
}
408414

409415
Update::Clear => {
416+
// Clean `self.chunks`.
417+
self.chunks.clear();
418+
410419
// Let's straightforwardly emit a `VectorDiff::Clear`.
411420
diffs.push(VectorDiff::Clear);
412421
}
@@ -455,10 +464,11 @@ impl UpdateToVectorDiff {
455464
mod tests {
456465
use std::fmt::Debug;
457466

467+
use assert_matches::assert_matches;
458468
use imbl::{vector, Vector};
459469

460470
use super::{
461-
super::{EmptyChunk, LinkedChunk},
471+
super::{ChunkIdentifierGenerator, EmptyChunk, LinkedChunk},
462472
VectorDiff,
463473
};
464474

@@ -708,6 +718,58 @@ mod tests {
708718
assert!(as_vector.take().is_empty());
709719
}
710720

721+
#[test]
722+
fn test_as_vector_with_update_clear() {
723+
let mut linked_chunk = LinkedChunk::<3, char, ()>::new_with_update_history();
724+
let mut as_vector = linked_chunk.as_vector().unwrap();
725+
726+
{
727+
// 1 initial chunk in the `UpdateToVectorDiff` mapper.
728+
let chunks = &as_vector.mapper.chunks;
729+
assert_eq!(chunks.len(), 1);
730+
assert_eq!(chunks[0].0, ChunkIdentifierGenerator::FIRST_IDENTIFIER);
731+
assert_eq!(chunks[0].1, 0);
732+
}
733+
734+
assert!(as_vector.take().is_empty());
735+
736+
linked_chunk.push_items_back(['a', 'b', 'c', 'd']);
737+
738+
{
739+
let diffs = as_vector.take();
740+
assert_eq!(diffs.len(), 2);
741+
assert_matches!(&diffs[0], VectorDiff::Append { .. });
742+
assert_matches!(&diffs[1], VectorDiff::Append { .. });
743+
744+
// 2 chunks in the `UpdateToVectorDiff` mapper.
745+
assert_eq!(as_vector.mapper.chunks.len(), 2);
746+
}
747+
748+
linked_chunk.clear();
749+
750+
{
751+
let diffs = as_vector.take();
752+
assert_eq!(diffs.len(), 1);
753+
assert_matches!(&diffs[0], VectorDiff::Clear);
754+
755+
// 1 chunk in the `UpdateToVectorDiff` mapper.
756+
let chunks = &as_vector.mapper.chunks;
757+
assert_eq!(chunks.len(), 1);
758+
assert_eq!(chunks[0].0, ChunkIdentifierGenerator::FIRST_IDENTIFIER);
759+
assert_eq!(chunks[0].1, 0);
760+
}
761+
762+
// And we can push again.
763+
linked_chunk.push_items_back(['a', 'b', 'c', 'd']);
764+
765+
{
766+
let diffs = as_vector.take();
767+
assert_eq!(diffs.len(), 2);
768+
assert_matches!(&diffs[0], VectorDiff::Append { .. });
769+
assert_matches!(&diffs[1], VectorDiff::Append { .. });
770+
}
771+
}
772+
711773
#[test]
712774
fn updates_are_drained_when_constructing_as_vector() {
713775
let mut linked_chunk = LinkedChunk::<10, char, ()>::new_with_update_history();

crates/matrix-sdk-common/src/linked_chunk/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ impl<const CAP: usize, Item, Gap> LinkedChunk<CAP, Item, Gap> {
304304
if let Some(updates) = self.updates.as_mut() {
305305
// TODO: Optimisation: Do we want to clear all pending `Update`s in `updates`?
306306
updates.push(Update::Clear);
307+
updates.push(Update::NewItemsChunk {
308+
previous: None,
309+
new: ChunkIdentifierGenerator::FIRST_IDENTIFIER,
310+
next: None,
311+
})
307312
}
308313
}
309314

@@ -2713,6 +2718,16 @@ mod tests {
27132718
let mut linked_chunk = LinkedChunk::<3, char, ()>::new_with_update_history();
27142719
linked_chunk.clear();
27152720

2716-
assert_eq!(linked_chunk.updates().unwrap().take(), &[Clear]);
2721+
assert_eq!(
2722+
linked_chunk.updates().unwrap().take(),
2723+
&[
2724+
Clear,
2725+
NewItemsChunk {
2726+
previous: None,
2727+
new: ChunkIdentifierGenerator::FIRST_IDENTIFIER,
2728+
next: None
2729+
}
2730+
]
2731+
);
27172732
}
27182733
}

0 commit comments

Comments
 (0)