Skip to content

Commit 8d43a86

Browse files
committed
task(common): LinkedChunkBuilder detects cycles.
1 parent 7d0958a commit 8d43a86

File tree

1 file changed

+32
-2
lines changed
  • crates/matrix-sdk-common/src/linked_chunk

1 file changed

+32
-2
lines changed

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ impl LinkedChunkBuilder {
101101
}
102102
}
103103

104+
// New chunk doesn't create a cycle.
105+
if let Some(previous_chunk) = new_first_chunk.previous {
106+
if linked_chunk.chunks().any(|chunk| chunk.identifier() == previous_chunk) {
107+
return Err(LinkedChunkBuilderError::Cycle {
108+
new_chunk: new_first_chunk.identifier,
109+
with_chunk: previous_chunk,
110+
});
111+
}
112+
}
113+
104114
let expected_next_chunk = linked_chunk.links.first_chunk().identifier();
105115

106116
// New chunk has a next chunk.
@@ -118,8 +128,7 @@ impl LinkedChunkBuilder {
118128
});
119129
}
120130

121-
// Alright. It's not possible to have a cycle within the chunks or
122-
// multiple connected components here. All checks are made.
131+
// Alright. All checks are made.
123132
}
124133

125134
// Insert the new first chunk.
@@ -208,6 +217,9 @@ pub enum LinkedChunkBuilderError {
208217
#[error("chunk with id {} has a next chunk, it is supposed to be the last chunk", id.index())]
209218
ChunkIsNotLast { id: ChunkIdentifier },
210219

220+
#[error("chunk with id {} forms a cycle with chunk with id {}", new_chunk.index(), with_chunk.index())]
221+
Cycle { new_chunk: ChunkIdentifier, with_chunk: ChunkIdentifier },
222+
211223
#[error("chunk with id {} is supposed to have a next chunk", id.index())]
212224
MissingNextChunk { id: ChunkIdentifier },
213225

@@ -343,6 +355,24 @@ mod tests {
343355
});
344356
}
345357

358+
#[test]
359+
fn test_insert_new_first_chunk_err_cycle() {
360+
let new_first_chunk = RawChunk {
361+
previous: Some(ChunkIdentifier::new(0)),
362+
identifier: ChunkIdentifier::new(1),
363+
next: Some(ChunkIdentifier(0)),
364+
content: ChunkContent::Gap(()),
365+
};
366+
367+
let mut linked_chunk = LinkedChunk::<2, char, ()>::new();
368+
let result = LinkedChunkBuilder::insert_new_first_chunk(&mut linked_chunk, new_first_chunk);
369+
370+
assert_matches!(result, Err(LinkedChunkBuilderError::Cycle { new_chunk, with_chunk }) => {
371+
assert_eq!(new_chunk, 1);
372+
assert_eq!(with_chunk, 0);
373+
});
374+
}
375+
346376
#[test]
347377
fn test_insert_new_first_chunk_err_missing_next_chunk() {
348378
let new_first_chunk = RawChunk {

0 commit comments

Comments
 (0)