sum_tree: Store context on cursor (#34904)

This gets rid of the need to pass context to all cursor functions. In
practice context is always immutable when interacting with cursors.

A nicety of this is in the follow-up PR we will be able to implement
Iterator for all Cursors/filter cursors (hell, we may be able to get rid
of filter cursor altogether, as it is just a custom `filter` impl on
iterator trait).
Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2025-07-22 18:20:48 +02:00 committed by GitHub
parent fa3e1ccc37
commit 64d0fec699
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 749 additions and 876 deletions

View file

@ -524,10 +524,10 @@ impl BlockMap {
// * Isomorphic transforms that end *at* the start of the edit
// * Below blocks that end at the start of the edit
// However, if we hit a replace block that ends at the start of the edit we want to reconstruct it.
new_transforms.append(cursor.slice(&old_start, Bias::Left, &()), &());
new_transforms.append(cursor.slice(&old_start, Bias::Left), &());
if let Some(transform) = cursor.item() {
if transform.summary.input_rows > 0
&& cursor.end(&()) == old_start
&& cursor.end() == old_start
&& transform
.block
.as_ref()
@ -535,13 +535,13 @@ impl BlockMap {
{
// Preserve the transform (push and next)
new_transforms.push(transform.clone(), &());
cursor.next(&());
cursor.next();
// Preserve below blocks at end of edit
while let Some(transform) = cursor.item() {
if transform.block.as_ref().map_or(false, |b| b.place_below()) {
new_transforms.push(transform.clone(), &());
cursor.next(&());
cursor.next();
} else {
break;
}
@ -579,8 +579,8 @@ impl BlockMap {
let mut new_end = WrapRow(edit.new.end);
loop {
// Seek to the transform starting at or after the end of the edit
cursor.seek(&old_end, Bias::Left, &());
cursor.next(&());
cursor.seek(&old_end, Bias::Left);
cursor.next();
// Extend edit to the end of the discarded transform so it is reconstructed in full
let transform_rows_after_edit = cursor.start().0 - old_end.0;
@ -592,8 +592,8 @@ impl BlockMap {
if next_edit.old.start <= cursor.start().0 {
old_end = WrapRow(next_edit.old.end);
new_end = WrapRow(next_edit.new.end);
cursor.seek(&old_end, Bias::Left, &());
cursor.next(&());
cursor.seek(&old_end, Bias::Left);
cursor.next();
edits.next();
} else {
break;
@ -608,7 +608,7 @@ impl BlockMap {
// Discard below blocks at the end of the edit. They'll be reconstructed.
while let Some(transform) = cursor.item() {
if transform.block.as_ref().map_or(false, |b| b.place_below()) {
cursor.next(&());
cursor.next();
} else {
break;
}
@ -720,7 +720,7 @@ impl BlockMap {
push_isomorphic(&mut new_transforms, rows_after_last_block, wrap_snapshot);
}
new_transforms.append(cursor.suffix(&()), &());
new_transforms.append(cursor.suffix(), &());
debug_assert_eq!(
new_transforms.summary().input_rows,
wrap_snapshot.max_point().row() + 1
@ -971,7 +971,7 @@ impl BlockMapReader<'_> {
);
let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>(&());
cursor.seek(&start_wrap_row, Bias::Left, &());
cursor.seek(&start_wrap_row, Bias::Left);
while let Some(transform) = cursor.item() {
if cursor.start().0 > end_wrap_row {
break;
@ -982,7 +982,7 @@ impl BlockMapReader<'_> {
return Some(cursor.start().1);
}
}
cursor.next(&());
cursor.next();
}
None
@ -1293,7 +1293,7 @@ impl BlockSnapshot {
let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&BlockRow(rows.start), Bias::Right, &());
cursor.seek(&BlockRow(rows.start), Bias::Right);
let transform_output_start = cursor.start().0.0;
let transform_input_start = cursor.start().1.0;
@ -1325,7 +1325,7 @@ impl BlockSnapshot {
pub(super) fn row_infos(&self, start_row: BlockRow) -> BlockRows<'_> {
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&start_row, Bias::Right, &());
cursor.seek(&start_row, Bias::Right);
let (output_start, input_start) = cursor.start();
let overshoot = if cursor
.item()
@ -1346,9 +1346,9 @@ impl BlockSnapshot {
pub fn blocks_in_range(&self, rows: Range<u32>) -> impl Iterator<Item = (u32, &Block)> {
let mut cursor = self.transforms.cursor::<BlockRow>(&());
cursor.seek(&BlockRow(rows.start), Bias::Left, &());
while cursor.start().0 < rows.start && cursor.end(&()).0 <= rows.start {
cursor.next(&());
cursor.seek(&BlockRow(rows.start), Bias::Left);
while cursor.start().0 < rows.start && cursor.end().0 <= rows.start {
cursor.next();
}
std::iter::from_fn(move || {
@ -1364,10 +1364,10 @@ impl BlockSnapshot {
break;
}
if let Some(block) = &transform.block {
cursor.next(&());
cursor.next();
return Some((start_row, block));
} else {
cursor.next(&());
cursor.next();
}
}
None
@ -1377,7 +1377,7 @@ impl BlockSnapshot {
pub fn sticky_header_excerpt(&self, position: f32) -> Option<StickyHeaderExcerpt<'_>> {
let top_row = position as u32;
let mut cursor = self.transforms.cursor::<BlockRow>(&());
cursor.seek(&BlockRow(top_row), Bias::Right, &());
cursor.seek(&BlockRow(top_row), Bias::Right);
while let Some(transform) = cursor.item() {
match &transform.block {
@ -1386,7 +1386,7 @@ impl BlockSnapshot {
}
Some(block) if block.is_buffer_header() => return None,
_ => {
cursor.prev(&());
cursor.prev();
continue;
}
}
@ -1414,7 +1414,7 @@ impl BlockSnapshot {
let wrap_row = WrapRow(wrap_point.row());
let mut cursor = self.transforms.cursor::<WrapRow>(&());
cursor.seek(&wrap_row, Bias::Left, &());
cursor.seek(&wrap_row, Bias::Left);
while let Some(transform) = cursor.item() {
if let Some(block) = transform.block.as_ref() {
@ -1425,7 +1425,7 @@ impl BlockSnapshot {
break;
}
cursor.next(&());
cursor.next();
}
None
@ -1442,7 +1442,7 @@ impl BlockSnapshot {
pub fn longest_row_in_range(&self, range: Range<BlockRow>) -> BlockRow {
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&range.start, Bias::Right, &());
cursor.seek(&range.start, Bias::Right);
let mut longest_row = range.start;
let mut longest_row_chars = 0;
@ -1453,7 +1453,7 @@ impl BlockSnapshot {
let wrap_start_row = input_start.0 + overshoot;
let wrap_end_row = cmp::min(
input_start.0 + (range.end.0 - output_start.0),
cursor.end(&()).1.0,
cursor.end().1.0,
);
let summary = self
.wrap_snapshot
@ -1461,12 +1461,12 @@ impl BlockSnapshot {
longest_row = BlockRow(range.start.0 + summary.longest_row);
longest_row_chars = summary.longest_row_chars;
}
cursor.next(&());
cursor.next();
}
let cursor_start_row = cursor.start().0;
if range.end > cursor_start_row {
let summary = cursor.summary::<_, TransformSummary>(&range.end, Bias::Right, &());
let summary = cursor.summary::<_, TransformSummary>(&range.end, Bias::Right);
if summary.longest_row_chars > longest_row_chars {
longest_row = BlockRow(cursor_start_row.0 + summary.longest_row);
longest_row_chars = summary.longest_row_chars;
@ -1493,7 +1493,7 @@ impl BlockSnapshot {
pub(super) fn line_len(&self, row: BlockRow) -> u32 {
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&BlockRow(row.0), Bias::Right, &());
cursor.seek(&BlockRow(row.0), Bias::Right);
if let Some(transform) = cursor.item() {
let (output_start, input_start) = cursor.start();
let overshoot = row.0 - output_start.0;
@ -1511,13 +1511,13 @@ impl BlockSnapshot {
pub(super) fn is_block_line(&self, row: BlockRow) -> bool {
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&row, Bias::Right, &());
cursor.seek(&row, Bias::Right);
cursor.item().map_or(false, |t| t.block.is_some())
}
pub(super) fn is_folded_buffer_header(&self, row: BlockRow) -> bool {
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&row, Bias::Right, &());
cursor.seek(&row, Bias::Right);
let Some(transform) = cursor.item() else {
return false;
};
@ -1529,7 +1529,7 @@ impl BlockSnapshot {
.wrap_snapshot
.make_wrap_point(Point::new(row.0, 0), Bias::Left);
let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>(&());
cursor.seek(&WrapRow(wrap_point.row()), Bias::Right, &());
cursor.seek(&WrapRow(wrap_point.row()), Bias::Right);
cursor.item().map_or(false, |transform| {
transform
.block
@ -1540,17 +1540,17 @@ impl BlockSnapshot {
pub fn clip_point(&self, point: BlockPoint, bias: Bias) -> BlockPoint {
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&BlockRow(point.row), Bias::Right, &());
cursor.seek(&BlockRow(point.row), Bias::Right);
let max_input_row = WrapRow(self.transforms.summary().input_rows);
let mut search_left =
(bias == Bias::Left && cursor.start().1.0 > 0) || cursor.end(&()).1 == max_input_row;
(bias == Bias::Left && cursor.start().1.0 > 0) || cursor.end().1 == max_input_row;
let mut reversed = false;
loop {
if let Some(transform) = cursor.item() {
let (output_start_row, input_start_row) = cursor.start();
let (output_end_row, input_end_row) = cursor.end(&());
let (output_end_row, input_end_row) = cursor.end();
let output_start = Point::new(output_start_row.0, 0);
let input_start = Point::new(input_start_row.0, 0);
let input_end = Point::new(input_end_row.0, 0);
@ -1584,23 +1584,23 @@ impl BlockSnapshot {
}
if search_left {
cursor.prev(&());
cursor.prev();
} else {
cursor.next(&());
cursor.next();
}
} else if reversed {
return self.max_point();
} else {
reversed = true;
search_left = !search_left;
cursor.seek(&BlockRow(point.row), Bias::Right, &());
cursor.seek(&BlockRow(point.row), Bias::Right);
}
}
}
pub fn to_block_point(&self, wrap_point: WrapPoint) -> BlockPoint {
let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>(&());
cursor.seek(&WrapRow(wrap_point.row()), Bias::Right, &());
cursor.seek(&WrapRow(wrap_point.row()), Bias::Right);
if let Some(transform) = cursor.item() {
if transform.block.is_some() {
BlockPoint::new(cursor.start().1.0, 0)
@ -1618,7 +1618,7 @@ impl BlockSnapshot {
pub fn to_wrap_point(&self, block_point: BlockPoint, bias: Bias) -> WrapPoint {
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
cursor.seek(&BlockRow(block_point.row), Bias::Right, &());
cursor.seek(&BlockRow(block_point.row), Bias::Right);
if let Some(transform) = cursor.item() {
match transform.block.as_ref() {
Some(block) => {
@ -1630,7 +1630,7 @@ impl BlockSnapshot {
} else if bias == Bias::Left {
WrapPoint::new(cursor.start().1.0, 0)
} else {
let wrap_row = cursor.end(&()).1.0 - 1;
let wrap_row = cursor.end().1.0 - 1;
WrapPoint::new(wrap_row, self.wrap_snapshot.line_len(wrap_row))
}
}
@ -1650,14 +1650,14 @@ impl BlockChunks<'_> {
/// Go to the next transform
fn advance(&mut self) {
self.input_chunk = Chunk::default();
self.transforms.next(&());
self.transforms.next();
while let Some(transform) = self.transforms.item() {
if transform
.block
.as_ref()
.map_or(false, |block| block.height() == 0)
{
self.transforms.next(&());
self.transforms.next();
} else {
break;
}
@ -1672,7 +1672,7 @@ impl BlockChunks<'_> {
let start_output_row = self.transforms.start().0.0;
if start_output_row < self.max_output_row {
let end_input_row = cmp::min(
self.transforms.end(&()).1.0,
self.transforms.end().1.0,
start_input_row + (self.max_output_row - start_output_row),
);
self.input_chunks.seek(start_input_row..end_input_row);
@ -1696,7 +1696,7 @@ impl<'a> Iterator for BlockChunks<'a> {
let transform = self.transforms.item()?;
if transform.block.is_some() {
let block_start = self.transforms.start().0.0;
let mut block_end = self.transforms.end(&()).0.0;
let mut block_end = self.transforms.end().0.0;
self.advance();
if self.transforms.item().is_none() {
block_end -= 1;
@ -1731,7 +1731,7 @@ impl<'a> Iterator for BlockChunks<'a> {
}
}
let transform_end = self.transforms.end(&()).0.0;
let transform_end = self.transforms.end().0.0;
let (prefix_rows, prefix_bytes) =
offset_for_row(self.input_chunk.text, transform_end - self.output_row);
self.output_row += prefix_rows;
@ -1770,15 +1770,15 @@ impl Iterator for BlockRows<'_> {
self.started = true;
}
if self.output_row.0 >= self.transforms.end(&()).0.0 {
self.transforms.next(&());
if self.output_row.0 >= self.transforms.end().0.0 {
self.transforms.next();
while let Some(transform) = self.transforms.item() {
if transform
.block
.as_ref()
.map_or(false, |block| block.height() == 0)
{
self.transforms.next(&());
self.transforms.next();
} else {
break;
}