Commit b5fb6f1fd41a
tarball1 file changed+56-2
@@ -146,6 +146,15 @@ impl EventLinkedChunk {
146146
Ok(next_pos)147147
}148148
149
+ /// Replace the gap identified by `gap_identifier` by another gap, keeping150
+ /// its place even when the next chunk is a gap too.151
+ fn rewrite_gap_at(&mut self, gap_identifier: ChunkIdentifier, gap: Gap) -> Result<(), Error> {152
+ let placeholder = self.chunks.replace_gap_at(Vec::new(), gap_identifier)?.identifier();153
+ self.chunks.insert_gap_at(gap, Position::new(placeholder, 0))?;154
+ self.chunks.remove_empty_chunk_at(placeholder)?;155
+ Ok(())156
+ }157
+149158
/// Remove some events from the linked chunk.150159
///151160
/// If a chunk becomes empty, it's going to be removed.@@ -361,9 +370,21 @@ impl EventLinkedChunk {
361370
events: &[Event],362371
) -> bool {363372
let first_event_pos = self.events().next().map(|(item_pos, _)| item_pos);373
+ let has_new_gap = new_gap.is_some();374
+ let mut new_gap = new_gap;364375
365376
// First, insert events.366
- let insert_new_gap_pos = if let Some(gap_id) = prev_gap_id {377
+ let insert_new_gap_pos = if let Some(gap_id) = prev_gap_id378
+ && events.is_empty()379
+ && let Some(gap) = new_gap.take()380
+ {381
+ trace!("rewriting the previous gap in place");382
+383
+ self.rewrite_gap_at(gap_id, gap)384
+ .expect("gap_identifier is a valid gap chunk id we read previously");385
+386
+ None387
+ } else if let Some(gap_id) = prev_gap_id {367388
// There is a prior gap, let's replace it with the new events!368389
trace!("replacing previous gap with the back-paginated events");369390
@@ -397,7 +418,6 @@ impl EventLinkedChunk {
397418
// We only do this when at least one new, non-duplicated event, has been added398419
// to the chunk. Otherwise it means we've back-paginated all the399420
// known events.400
- let has_new_gap = new_gap.is_some();401421
if let Some(new_gap) = new_gap {402422
if let Some(new_pos) = insert_new_gap_pos {403423
self.chunks@@ -748,6 +768,40 @@ mod tests {
748768
}749769
750770
#[test]771
+ fn test_empty_backwards_page_before_another_gap_keeps_both_gaps() {772
+ let (_, event_0) = new_event("$ev0");773
+ let (_, event_1) = new_event("$ev1");774
+775
+ let mut linked_chunk = EventLinkedChunk::new();776
+777
+ linked_chunk.chunks.push_items_back([event_0]);778
+ linked_chunk.chunks.push_gap_back(Gap { token: "older".to_owned(), history: None });779
+ linked_chunk.chunks.push_gap_back(Gap { token: "newer".to_owned(), history: None });780
+ linked_chunk.chunks.push_items_back([event_1]);781
+782
+ let older_gap_id = linked_chunk783
+ .chunks()784
+ .find_map(|chunk| chunk.is_gap().then_some(chunk.identifier()))785
+ .unwrap();786
+787
+ linked_chunk.push_backwards_pagination_events(788
+ Some(older_gap_id),789
+ Some(Gap { token: "next".to_owned(), history: None }),790
+ &[],791
+ );792
+793
+ let tokens: Vec<_> = linked_chunk794
+ .chunks()795
+ .filter_map(|chunk| match chunk.content() {796
+ ChunkContent::Gap(gap) => Some(gap.token.clone()),797
+ ChunkContent::Items(_) => None,798
+ })799
+ .collect();800
+ assert_eq!(tokens, ["next", "newer"]);801
+ assert_eq!(linked_chunk.events().count(), 2);802
+ }803
+804
+ #[test]751805
fn test_replace_gap_at_with_no_new_events() {752806
let (_, event_0) = new_event("$ev0");753807
let (_, event_1) = new_event("$ev1");