multi_buffer: Reuse buffer chunks iterator when seeking across folds within an excerpt (#15532)

Piotr Osiewicz and Max Brunsfeld created

Release Notes:

- N/A

---------

Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>

Change summary

crates/multi_buffer/src/multi_buffer.rs | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)

Detailed changes

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -298,6 +298,7 @@ pub struct ReversedMultiBufferBytes<'a> {
 }
 
 struct ExcerptChunks<'a> {
+    excerpt_id: ExcerptId,
     content_chunks: BufferChunks<'a>,
     footer_height: usize,
 }
@@ -4145,11 +4146,18 @@ impl Excerpt {
         let content_chunks = self.buffer.chunks(chunks_start..chunks_end, language_aware);
 
         ExcerptChunks {
+            excerpt_id: self.id,
             content_chunks,
             footer_height,
         }
     }
 
+    fn seek_chunks(&self, excerpt_chunks: &mut ExcerptChunks, offset: usize) {
+        let content_start = self.range.context.start.to_offset(&self.buffer);
+        let chunks_start = content_start + offset;
+        excerpt_chunks.content_chunks.seek(chunks_start);
+    }
+
     fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
         let content_start = self.range.context.start.to_offset(&self.buffer);
         let bytes_start = content_start + range.start;
@@ -4488,10 +4496,19 @@ impl<'a> MultiBufferChunks<'a> {
         self.range.start = offset;
         self.excerpts.seek(&offset, Bias::Right, &());
         if let Some(excerpt) = self.excerpts.item() {
-            self.excerpt_chunks = Some(excerpt.chunks_in_range(
-                self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(),
-                self.language_aware,
-            ));
+            let excerpt_start = self.excerpts.start();
+            if let Some(excerpt_chunks) = self
+                .excerpt_chunks
+                .as_mut()
+                .filter(|chunks| excerpt.id == chunks.excerpt_id)
+            {
+                excerpt.seek_chunks(excerpt_chunks, self.range.start - excerpt_start);
+            } else {
+                self.excerpt_chunks = Some(excerpt.chunks_in_range(
+                    self.range.start - excerpt_start..self.range.end - excerpt_start,
+                    self.language_aware,
+                ));
+            }
         } else {
             self.excerpt_chunks = None;
         }