Merge pull request #186 from zed-industries/sum-tree-seek-target

Nathan Sobo created

Allow seeking SumTree cursor by multiple seek types per dimension

Change summary

gpui/src/elements/list.rs                |  65 ++---
gpui/src/sum_tree.rs                     | 163 +++++++++-----
gpui/src/sum_tree/cursor.rs              | 284 +++++++++----------------
server/src/rpc.rs                        |   2 
zed/src/channel.rs                       |  22 -
zed/src/editor/buffer.rs                 |  66 +++---
zed/src/editor/buffer/operation_queue.rs |   2 
zed/src/editor/buffer/rope.rs            |  64 ++---
zed/src/editor/display_map/fold_map.rs   | 181 ++++++++--------
zed/src/editor/display_map/wrap_map.rs   |  78 +++---
zed/src/worktree.rs                      |  38 +-
11 files changed, 457 insertions(+), 508 deletions(-)

Detailed changes

gpui/src/elements/list.rs 🔗

@@ -128,7 +128,7 @@ impl Element for List {
             });
 
         // Render items after the scroll top, including those in the trailing overdraw.
-        let mut cursor = old_items.cursor::<Count, ()>();
+        let mut cursor = old_items.cursor::<Count>();
         cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
         for (ix, item) in cursor.by_ref().enumerate() {
             if rendered_height - scroll_top.offset_in_item >= size.y() + state.overdraw {
@@ -149,8 +149,7 @@ impl Element for List {
             while rendered_height < size.y() {
                 cursor.prev(&());
                 if let Some(item) = cursor.item() {
-                    let element =
-                        state.render_item(cursor.seek_start().0, item, item_constraint, cx);
+                    let element = state.render_item(cursor.start().0, item, item_constraint, cx);
                     rendered_height += element.size().y();
                     rendered_items.push_front(ListItem::Rendered(element));
                 } else {
@@ -159,7 +158,7 @@ impl Element for List {
             }
 
             scroll_top = ListOffset {
-                item_ix: cursor.seek_start().0,
+                item_ix: cursor.start().0,
                 offset_in_item: rendered_height - size.y(),
             };
 
@@ -170,7 +169,7 @@ impl Element for List {
                 }
                 Orientation::Bottom => {
                     scroll_top = ListOffset {
-                        item_ix: cursor.seek_start().0,
+                        item_ix: cursor.start().0,
                         offset_in_item: rendered_height - size.y(),
                     };
                     state.logical_scroll_top = None;
@@ -183,7 +182,7 @@ impl Element for List {
         while leading_overdraw < state.overdraw {
             cursor.prev(&());
             if let Some(item) = cursor.item() {
-                let element = state.render_item(cursor.seek_start().0, item, item_constraint, cx);
+                let element = state.render_item(cursor.start().0, item, item_constraint, cx);
                 leading_overdraw += element.size().y();
                 rendered_items.push_front(ListItem::Rendered(element));
             } else {
@@ -191,10 +190,9 @@ impl Element for List {
             }
         }
 
-        let new_rendered_range =
-            cursor.seek_start().0..(cursor.seek_start().0 + rendered_items.len());
+        let new_rendered_range = cursor.start().0..(cursor.start().0 + rendered_items.len());
 
-        let mut cursor = old_items.cursor::<Count, ()>();
+        let mut cursor = old_items.cursor::<Count>();
 
         if state.rendered_range.start < new_rendered_range.start {
             new_items.push_tree(
@@ -202,7 +200,7 @@ impl Element for List {
                 &(),
             );
             let remove_to = state.rendered_range.end.min(new_rendered_range.start);
-            while cursor.seek_start().0 < remove_to {
+            while cursor.start().0 < remove_to {
                 new_items.push(cursor.item().unwrap().remove(), &());
                 cursor.next(&());
             }
@@ -221,7 +219,7 @@ impl Element for List {
                 &(),
             );
         }
-        while cursor.seek_start().0 < state.rendered_range.end {
+        while cursor.start().0 < state.rendered_range.end {
             new_items.push(cursor.item().unwrap().remove(), &());
             cursor.next(&());
         }
@@ -263,7 +261,7 @@ impl Element for List {
 
         let mut state = self.state.0.borrow_mut();
         let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item);
-        let mut cursor = state.items.cursor::<Count, ()>();
+        let mut cursor = state.items.cursor::<Count>();
         let mut new_items = cursor.slice(&Count(scroll_top.item_ix), Bias::Right, &());
         while let Some(item) = cursor.item() {
             if item_origin.y() > bounds.max_y() {
@@ -390,7 +388,7 @@ impl ListState {
                 new_end + state.rendered_range.end.saturating_sub(old_range.end);
         }
 
-        let mut old_heights = state.items.cursor::<Count, ()>();
+        let mut old_heights = state.items.cursor::<Count>();
         let mut new_heights = old_heights.slice(&Count(old_range.start), Bias::Right, &());
         old_heights.seek_forward(&Count(old_range.end), Bias::Right, &());
 
@@ -426,12 +424,11 @@ impl StateInner {
     }
 
     fn visible_range(&self, height: f32, scroll_top: &ListOffset) -> Range<usize> {
-        let mut cursor = self.items.cursor::<Count, Height>();
+        let mut cursor = self.items.cursor::<ListItemSummary>();
         cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
-        let start_y = cursor.sum_start().0 + scroll_top.offset_in_item;
-        let mut cursor = cursor.swap_dimensions();
+        let start_y = cursor.start().height + scroll_top.offset_in_item;
         cursor.seek_forward(&Height(start_y + height), Bias::Left, &());
-        scroll_top.item_ix..cursor.sum_start().0 + 1
+        scroll_top.item_ix..cursor.start().count + 1
     }
 
     fn visible_elements<'a>(
@@ -440,7 +437,7 @@ impl StateInner {
         scroll_top: &ListOffset,
     ) -> impl Iterator<Item = (ElementRc, Vector2F)> + 'a {
         let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item);
-        let mut cursor = self.items.cursor::<Count, ()>();
+        let mut cursor = self.items.cursor::<Count>();
         cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
         std::iter::from_fn(move || {
             while let Some(item) = cursor.item() {
@@ -482,10 +479,10 @@ impl StateInner {
         if self.orientation == Orientation::Bottom && new_scroll_top == scroll_max {
             self.logical_scroll_top = None;
         } else {
-            let mut cursor = self.items.cursor::<Height, Count>();
+            let mut cursor = self.items.cursor::<ListItemSummary>();
             cursor.seek(&Height(new_scroll_top), Bias::Right, &());
-            let item_ix = cursor.sum_start().0;
-            let offset_in_item = new_scroll_top - cursor.seek_start().0;
+            let item_ix = cursor.start().count;
+            let offset_in_item = new_scroll_top - cursor.start().height;
             self.logical_scroll_top = Some(ListOffset {
                 item_ix,
                 offset_in_item,
@@ -502,9 +499,9 @@ impl StateInner {
     }
 
     fn scroll_top(&self, logical_scroll_top: &ListOffset) -> f32 {
-        let mut cursor = self.items.cursor::<Count, Height>();
+        let mut cursor = self.items.cursor::<ListItemSummary>();
         cursor.seek(&Count(logical_scroll_top.item_ix), Bias::Right, &());
-        cursor.sum_start().0 + logical_scroll_top.offset_in_item
+        cursor.start().height + logical_scroll_top.offset_in_item
     }
 }
 
@@ -556,12 +553,6 @@ impl sum_tree::Summary for ListItemSummary {
     }
 }
 
-impl<'a> sum_tree::Dimension<'a, ListItemSummary> for ListItemSummary {
-    fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
-        sum_tree::Summary::add_summary(self, summary, &());
-    }
-}
-
 impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Count {
     fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
         self.0 += summary.count;
@@ -586,9 +577,15 @@ impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Height {
     }
 }
 
-impl<'a> sum_tree::SeekDimension<'a, ListItemSummary> for Height {
-    fn cmp(&self, other: &Self, _: &()) -> std::cmp::Ordering {
-        self.0.partial_cmp(&other.0).unwrap()
+impl<'a> sum_tree::SeekTarget<'a, ListItemSummary, ListItemSummary> for Count {
+    fn cmp(&self, other: &ListItemSummary, _: &()) -> std::cmp::Ordering {
+        self.0.partial_cmp(&other.count).unwrap()
+    }
+}
+
+impl<'a> sum_tree::SeekTarget<'a, ListItemSummary, ListItemSummary> for Height {
+    fn cmp(&self, other: &ListItemSummary, _: &()) -> std::cmp::Ordering {
+        self.0.partial_cmp(&other.height).unwrap()
     }
 }
 
@@ -760,7 +757,7 @@ mod tests {
                     log::info!("splice({:?}, {:?})", start_ix..end_ix, new_elements);
                     state.splice(start_ix..end_ix, new_elements.len());
                     elements.splice(start_ix..end_ix, new_elements);
-                    for (ix, item) in state.0.borrow().items.cursor::<(), ()>().enumerate() {
+                    for (ix, item) in state.0.borrow().items.cursor::<()>().enumerate() {
                         if let ListItem::Rendered(element) = item {
                             let (expected_id, _) = elements[ix];
                             element.with_metadata(|metadata: Option<&usize>| {
@@ -797,7 +794,7 @@ mod tests {
             let mut first_rendered_element_top = None;
             let mut last_rendered_element_bottom = None;
             assert_eq!(state.items.summary().count, elements.borrow().len());
-            for (ix, item) in state.items.cursor::<(), ()>().enumerate() {
+            for (ix, item) in state.items.cursor::<()>().enumerate() {
                 match item {
                     ListItem::Unrendered => {
                         let item_bottom = item_top;

gpui/src/sum_tree.rs 🔗

@@ -3,6 +3,7 @@ mod cursor;
 use arrayvec::ArrayVec;
 pub use cursor::Cursor;
 pub use cursor::FilterCursor;
+use std::marker::PhantomData;
 use std::{cmp::Ordering, fmt, iter::FromIterator, sync::Arc};
 
 #[cfg(test)]
@@ -32,17 +33,58 @@ pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug + Default {
     fn add_summary(&mut self, _summary: &'a S, _: &S::Context);
 }
 
+impl<'a, T: Summary> Dimension<'a, T> for T {
+    fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
+        Summary::add_summary(self, summary, cx);
+    }
+}
+
+pub trait SeekTarget<'a, S: Summary, D: Dimension<'a, S>>: fmt::Debug {
+    fn cmp(&self, cursor_location: &D, cx: &S::Context) -> Ordering;
+}
+
+impl<'a, S: Summary, D: Dimension<'a, S> + Ord> SeekTarget<'a, S, D> for D {
+    fn cmp(&self, cursor_location: &Self, _: &S::Context) -> Ordering {
+        Ord::cmp(self, cursor_location)
+    }
+}
+
 impl<'a, T: Summary> Dimension<'a, T> for () {
     fn add_summary(&mut self, _: &'a T, _: &T::Context) {}
 }
 
-pub trait SeekDimension<'a, T: Summary>: Dimension<'a, T> {
-    fn cmp(&self, other: &Self, cx: &T::Context) -> Ordering;
+impl<'a, T: Summary, D1: Dimension<'a, T>, D2: Dimension<'a, T>> Dimension<'a, T> for (D1, D2) {
+    fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
+        self.0.add_summary(summary, cx);
+        self.1.add_summary(summary, cx);
+    }
+}
+
+impl<'a, S: Summary, D1: SeekTarget<'a, S, D1> + Dimension<'a, S>, D2: Dimension<'a, S>>
+    SeekTarget<'a, S, (D1, D2)> for D1
+{
+    fn cmp(&self, cursor_location: &(D1, D2), cx: &S::Context) -> Ordering {
+        self.cmp(&cursor_location.0, cx)
+    }
+}
+
+struct End<D>(PhantomData<D>);
+
+impl<D> End<D> {
+    fn new() -> Self {
+        Self(PhantomData)
+    }
+}
+
+impl<'a, S: Summary, D: Dimension<'a, S>> SeekTarget<'a, S, D> for End<D> {
+    fn cmp(&self, _: &D, _: &S::Context) -> Ordering {
+        Ordering::Greater
+    }
 }
 
-impl<'a, S: Summary, T: Dimension<'a, S> + Ord> SeekDimension<'a, S> for T {
-    fn cmp(&self, other: &Self, _ctx: &S::Context) -> Ordering {
-        Ord::cmp(self, other)
+impl<D> fmt::Debug for End<D> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("End").finish()
     }
 }
 
@@ -99,7 +141,7 @@ impl<T: Item> SumTree<T> {
     #[allow(unused)]
     pub fn items(&self, cx: &<T::Summary as Summary>::Context) -> Vec<T> {
         let mut items = Vec::new();
-        let mut cursor = self.cursor::<(), ()>();
+        let mut cursor = self.cursor::<()>();
         cursor.next(cx);
         while let Some(item) = cursor.item() {
             items.push(item.clone());
@@ -108,10 +150,9 @@ impl<T: Item> SumTree<T> {
         items
     }
 
-    pub fn cursor<'a, S, U>(&'a self) -> Cursor<T, S, U>
+    pub fn cursor<'a, S>(&'a self) -> Cursor<T, S>
     where
         S: Dimension<'a, T::Summary>,
-        U: Dimension<'a, T::Summary>,
     {
         Cursor::new(self)
     }
@@ -230,7 +271,7 @@ impl<T: Item> SumTree<T> {
             }) = leaf.as_mut()
             {
                 let item_summary = item.summary();
-                summary.add_summary(&item_summary, cx);
+                <T::Summary as Summary>::add_summary(summary, &item_summary, cx);
                 items.push(item);
                 item_summaries.push(item_summary);
             } else {
@@ -281,7 +322,7 @@ impl<T: Item> SumTree<T> {
                 ..
             } => {
                 let other_node = other.0.clone();
-                summary.add_summary(other_node.summary(), cx);
+                <T::Summary as Summary>::add_summary(summary, other_node.summary(), cx);
 
                 let height_delta = *height - other_node.height();
                 let mut summaries_to_append = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
@@ -378,7 +419,7 @@ impl<T: Item> SumTree<T> {
                         item_summaries: right_summaries,
                     })))
                 } else {
-                    summary.add_summary(other_node.summary(), cx);
+                    <T::Summary as Summary>::add_summary(summary, other_node.summary(), cx);
                     items.extend(other_node.items().iter().cloned());
                     item_summaries.extend(other_node.child_summaries().iter().cloned());
                     None
@@ -430,7 +471,7 @@ impl<T: KeyedItem> SumTree<T> {
     pub fn insert_or_replace(&mut self, item: T, cx: &<T::Summary as Summary>::Context) -> bool {
         let mut replaced = false;
         *self = {
-            let mut cursor = self.cursor::<T::Key, ()>();
+            let mut cursor = self.cursor::<T::Key>();
             let mut new_tree = cursor.slice(&item.key(), Bias::Left, cx);
             if cursor
                 .item()
@@ -459,7 +500,7 @@ impl<T: KeyedItem> SumTree<T> {
         edits.sort_unstable_by_key(|item| item.key());
 
         *self = {
-            let mut cursor = self.cursor::<T::Key, ()>();
+            let mut cursor = self.cursor::<T::Key>();
             let mut new_tree = SumTree::new();
             let mut buffered_items = Vec::new();
 
@@ -502,7 +543,7 @@ impl<T: KeyedItem> SumTree<T> {
     }
 
     pub fn get(&self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<&T> {
-        let mut cursor = self.cursor::<T::Key, ()>();
+        let mut cursor = self.cursor::<T::Key>();
         if cursor.seek(key, Bias::Left, cx) {
             cursor.item()
         } else {
@@ -617,7 +658,6 @@ mod tests {
     use super::*;
     use rand::{distributions, prelude::*};
     use std::cmp;
-    use std::ops::Add;
 
     #[test]
     fn test_extend_and_push_tree() {
@@ -655,7 +695,7 @@ mod tests {
             reference_items.splice(splice_start..splice_end, new_items.clone());
 
             tree = {
-                let mut cursor = tree.cursor::<Count, ()>();
+                let mut cursor = tree.cursor::<Count>();
                 let mut new_tree = cursor.slice(&Count(splice_start), Bias::Right, &());
                 new_tree.extend(new_items, &());
                 cursor.seek(&Count(splice_end), Bias::Right, &());
@@ -681,11 +721,11 @@ mod tests {
 
             let mut pos = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
             let mut before_start = false;
-            let mut cursor = tree.cursor::<Count, Count>();
+            let mut cursor = tree.cursor::<Count>();
             cursor.seek(&Count(pos), Bias::Right, &());
 
             for i in 0..10 {
-                assert_eq!(cursor.sum_start().0, pos);
+                assert_eq!(cursor.start().0, pos);
 
                 if pos > 0 {
                     assert_eq!(cursor.prev_item().unwrap(), &reference_items[pos - 1]);
@@ -721,14 +761,14 @@ mod tests {
             let start_bias = if rng.gen() { Bias::Left } else { Bias::Right };
             let end_bias = if rng.gen() { Bias::Left } else { Bias::Right };
 
-            let mut cursor = tree.cursor::<Count, ()>();
+            let mut cursor = tree.cursor::<Count>();
             cursor.seek(&Count(start), start_bias, &());
             let slice = cursor.slice(&Count(end), end_bias, &());
 
             cursor.seek(&Count(start), start_bias, &());
-            let summary = cursor.summary::<Sum>(&Count(end), end_bias, &());
+            let summary = cursor.summary::<_, Sum>(&Count(end), end_bias, &());
 
-            assert_eq!(summary, slice.summary().sum);
+            assert_eq!(summary.0, slice.summary().sum);
         }
     }
 
@@ -736,42 +776,42 @@ mod tests {
     fn test_cursor() {
         // Empty tree
         let tree = SumTree::<u8>::new();
-        let mut cursor = tree.cursor::<Count, Sum>();
+        let mut cursor = tree.cursor::<IntegersSummary>();
         assert_eq!(
             cursor.slice(&Count(0), Bias::Right, &()).items(&()),
             Vec::<u8>::new()
         );
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), None);
-        assert_eq!(cursor.sum_start(), &Sum(0));
+        assert_eq!(cursor.start().sum, 0);
 
         // Single-element tree
         let mut tree = SumTree::<u8>::new();
         tree.extend(vec![1], &());
-        let mut cursor = tree.cursor::<Count, Sum>();
+        let mut cursor = tree.cursor::<IntegersSummary>();
         assert_eq!(
             cursor.slice(&Count(0), Bias::Right, &()).items(&()),
             Vec::<u8>::new()
         );
         assert_eq!(cursor.item(), Some(&1));
         assert_eq!(cursor.prev_item(), None);
-        assert_eq!(cursor.sum_start(), &Sum(0));
+        assert_eq!(cursor.start().sum, 0);
 
         cursor.next(&());
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&1));
-        assert_eq!(cursor.sum_start(), &Sum(1));
+        assert_eq!(cursor.start().sum, 1);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), Some(&1));
         assert_eq!(cursor.prev_item(), None);
-        assert_eq!(cursor.sum_start(), &Sum(0));
+        assert_eq!(cursor.start().sum, 0);
 
-        let mut cursor = tree.cursor::<Count, Sum>();
+        let mut cursor = tree.cursor::<IntegersSummary>();
         assert_eq!(cursor.slice(&Count(1), Bias::Right, &()).items(&()), [1]);
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&1));
-        assert_eq!(cursor.sum_start(), &Sum(1));
+        assert_eq!(cursor.start().sum, 1);
 
         cursor.seek(&Count(0), Bias::Right, &());
         assert_eq!(
@@ -782,80 +822,80 @@ mod tests {
         );
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&1));
-        assert_eq!(cursor.sum_start(), &Sum(1));
+        assert_eq!(cursor.start().sum, 1);
 
         // Multiple-element tree
         let mut tree = SumTree::new();
         tree.extend(vec![1, 2, 3, 4, 5, 6], &());
-        let mut cursor = tree.cursor::<Count, Sum>();
+        let mut cursor = tree.cursor::<IntegersSummary>();
 
         assert_eq!(cursor.slice(&Count(2), Bias::Right, &()).items(&()), [1, 2]);
         assert_eq!(cursor.item(), Some(&3));
         assert_eq!(cursor.prev_item(), Some(&2));
-        assert_eq!(cursor.sum_start(), &Sum(3));
+        assert_eq!(cursor.start().sum, 3);
 
         cursor.next(&());
         assert_eq!(cursor.item(), Some(&4));
         assert_eq!(cursor.prev_item(), Some(&3));
-        assert_eq!(cursor.sum_start(), &Sum(6));
+        assert_eq!(cursor.start().sum, 6);
 
         cursor.next(&());
         assert_eq!(cursor.item(), Some(&5));
         assert_eq!(cursor.prev_item(), Some(&4));
-        assert_eq!(cursor.sum_start(), &Sum(10));
+        assert_eq!(cursor.start().sum, 10);
 
         cursor.next(&());
         assert_eq!(cursor.item(), Some(&6));
         assert_eq!(cursor.prev_item(), Some(&5));
-        assert_eq!(cursor.sum_start(), &Sum(15));
+        assert_eq!(cursor.start().sum, 15);
 
         cursor.next(&());
         cursor.next(&());
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&6));
-        assert_eq!(cursor.sum_start(), &Sum(21));
+        assert_eq!(cursor.start().sum, 21);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), Some(&6));
         assert_eq!(cursor.prev_item(), Some(&5));
-        assert_eq!(cursor.sum_start(), &Sum(15));
+        assert_eq!(cursor.start().sum, 15);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), Some(&5));
         assert_eq!(cursor.prev_item(), Some(&4));
-        assert_eq!(cursor.sum_start(), &Sum(10));
+        assert_eq!(cursor.start().sum, 10);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), Some(&4));
         assert_eq!(cursor.prev_item(), Some(&3));
-        assert_eq!(cursor.sum_start(), &Sum(6));
+        assert_eq!(cursor.start().sum, 6);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), Some(&3));
         assert_eq!(cursor.prev_item(), Some(&2));
-        assert_eq!(cursor.sum_start(), &Sum(3));
+        assert_eq!(cursor.start().sum, 3);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), Some(&2));
         assert_eq!(cursor.prev_item(), Some(&1));
-        assert_eq!(cursor.sum_start(), &Sum(1));
+        assert_eq!(cursor.start().sum, 1);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), Some(&1));
         assert_eq!(cursor.prev_item(), None);
-        assert_eq!(cursor.sum_start(), &Sum(0));
+        assert_eq!(cursor.start().sum, 0);
 
         cursor.prev(&());
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), None);
-        assert_eq!(cursor.sum_start(), &Sum(0));
+        assert_eq!(cursor.start().sum, 0);
 
         cursor.next(&());
         assert_eq!(cursor.item(), Some(&1));
         assert_eq!(cursor.prev_item(), None);
-        assert_eq!(cursor.sum_start(), &Sum(0));
+        assert_eq!(cursor.start().sum, 0);
 
-        let mut cursor = tree.cursor::<Count, Sum>();
+        let mut cursor = tree.cursor::<IntegersSummary>();
         assert_eq!(
             cursor
                 .slice(&tree.extent::<Count>(&()), Bias::Right, &())
@@ -864,7 +904,7 @@ mod tests {
         );
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&6));
-        assert_eq!(cursor.sum_start(), &Sum(21));
+        assert_eq!(cursor.start().sum, 21);
 
         cursor.seek(&Count(3), Bias::Right, &());
         assert_eq!(
@@ -875,7 +915,7 @@ mod tests {
         );
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&6));
-        assert_eq!(cursor.sum_start(), &Sum(21));
+        assert_eq!(cursor.start().sum, 21);
 
         // Seeking can bias left or right
         cursor.seek(&Count(1), Bias::Left, &());
@@ -922,8 +962,8 @@ mod tests {
 
     #[derive(Clone, Default, Debug)]
     pub struct IntegersSummary {
-        count: Count,
-        sum: Sum,
+        count: usize,
+        sum: usize,
         contains_even: bool,
         max: u8,
     }
@@ -939,8 +979,8 @@ mod tests {
 
         fn summary(&self) -> Self::Summary {
             IntegersSummary {
-                count: Count(1),
-                sum: Sum(*self as usize),
+                count: 1,
+                sum: *self as usize,
                 contains_even: (*self & 1) == 0,
                 max: *self,
             }
@@ -959,8 +999,8 @@ mod tests {
         type Context = ();
 
         fn add_summary(&mut self, other: &Self, _: &()) {
-            self.count.0 += &other.count.0;
-            self.sum.0 += &other.sum.0;
+            self.count += other.count;
+            self.sum += other.sum;
             self.contains_even |= other.contains_even;
             self.max = cmp::max(self.max, other.max);
         }
@@ -974,22 +1014,19 @@ mod tests {
 
     impl<'a> Dimension<'a, IntegersSummary> for Count {
         fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
-            self.0 += summary.count.0;
+            self.0 += summary.count;
         }
     }
 
-    impl<'a> Dimension<'a, IntegersSummary> for Sum {
-        fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
-            self.0 += summary.sum.0;
+    impl<'a> SeekTarget<'a, IntegersSummary, IntegersSummary> for Count {
+        fn cmp(&self, cursor_location: &IntegersSummary, _: &()) -> Ordering {
+            self.0.cmp(&cursor_location.count)
         }
     }
 
-    impl<'a> Add<&'a Self> for Sum {
-        type Output = Self;
-
-        fn add(mut self, other: &Self) -> Self {
-            self.0 += other.0;
-            self
+    impl<'a> Dimension<'a, IntegersSummary> for Sum {
+        fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
+            self.0 += summary.sum;
         }
     }
 }

gpui/src/sum_tree/cursor.rs 🔗

@@ -3,51 +3,31 @@ use arrayvec::ArrayVec;
 use std::{cmp::Ordering, sync::Arc};
 
 #[derive(Clone)]
-struct StackEntry<'a, T: Item, S, U> {
+struct StackEntry<'a, T: Item, D> {
     tree: &'a SumTree<T>,
     index: usize,
-    seek_dimension: S,
-    sum_dimension: U,
-}
-
-impl<'a, T, S, U> StackEntry<'a, T, S, U>
-where
-    T: Item,
-    S: SeekDimension<'a, T::Summary>,
-    U: SeekDimension<'a, T::Summary>,
-{
-    fn swap_dimensions(self) -> StackEntry<'a, T, U, S> {
-        StackEntry {
-            tree: self.tree,
-            index: self.index,
-            seek_dimension: self.sum_dimension,
-            sum_dimension: self.seek_dimension,
-        }
-    }
+    position: D,
 }
 
 #[derive(Clone)]
-pub struct Cursor<'a, T: Item, S, U> {
+pub struct Cursor<'a, T: Item, D> {
     tree: &'a SumTree<T>,
-    stack: ArrayVec<StackEntry<'a, T, S, U>, 16>,
-    seek_dimension: S,
-    sum_dimension: U,
+    stack: ArrayVec<StackEntry<'a, T, D>, 16>,
+    position: D,
     did_seek: bool,
     at_end: bool,
 }
 
-impl<'a, T, S, U> Cursor<'a, T, S, U>
+impl<'a, T, D> Cursor<'a, T, D>
 where
     T: Item,
-    S: Dimension<'a, T::Summary>,
-    U: Dimension<'a, T::Summary>,
+    D: Dimension<'a, T::Summary>,
 {
     pub fn new(tree: &'a SumTree<T>) -> Self {
         Self {
             tree,
             stack: ArrayVec::new(),
-            seek_dimension: S::default(),
-            sum_dimension: U::default(),
+            position: D::default(),
             did_seek: false,
             at_end: false,
         }
@@ -57,35 +37,20 @@ where
         self.did_seek = false;
         self.at_end = false;
         self.stack.truncate(0);
-        self.seek_dimension = S::default();
-        self.sum_dimension = U::default();
-    }
-
-    pub fn seek_start(&self) -> &S {
-        &self.seek_dimension
-    }
-
-    pub fn seek_end(&self, cx: &<T::Summary as Summary>::Context) -> S {
-        if let Some(item_summary) = self.item_summary() {
-            let mut end = self.seek_start().clone();
-            end.add_summary(item_summary, cx);
-            end
-        } else {
-            self.seek_start().clone()
-        }
+        self.position = D::default();
     }
 
-    pub fn sum_start(&self) -> &U {
-        &self.sum_dimension
+    pub fn start(&self) -> &D {
+        &self.position
     }
 
-    pub fn sum_end(&self, cx: &<T::Summary as Summary>::Context) -> U {
+    pub fn end(&self, cx: &<T::Summary as Summary>::Context) -> D {
         if let Some(item_summary) = self.item_summary() {
-            let mut end = self.sum_start().clone();
+            let mut end = self.start().clone();
             end.add_summary(item_summary, cx);
             end
         } else {
-            self.sum_start().clone()
+            self.start().clone()
         }
     }
 
@@ -167,8 +132,7 @@ where
         assert!(self.did_seek, "Must seek before calling this method");
 
         if self.at_end {
-            self.seek_dimension = S::default();
-            self.sum_dimension = U::default();
+            self.position = D::default();
             self.descend_to_last_item(self.tree, cx);
             self.at_end = false;
         } else {
@@ -176,17 +140,10 @@ where
                 if entry.index > 0 {
                     let new_index = entry.index - 1;
 
-                    if let Some(StackEntry {
-                        seek_dimension,
-                        sum_dimension,
-                        ..
-                    }) = self.stack.last()
-                    {
-                        self.seek_dimension = seek_dimension.clone();
-                        self.sum_dimension = sum_dimension.clone();
+                    if let Some(StackEntry { position, .. }) = self.stack.last() {
+                        self.position = position.clone();
                     } else {
-                        self.seek_dimension = S::default();
-                        self.sum_dimension = U::default();
+                        self.position = D::default();
                     }
 
                     match entry.tree.0.as_ref() {
@@ -196,27 +153,23 @@ where
                             ..
                         } => {
                             for summary in &child_summaries[0..new_index] {
-                                self.seek_dimension.add_summary(summary, cx);
-                                self.sum_dimension.add_summary(summary, cx);
+                                self.position.add_summary(summary, cx);
                             }
                             self.stack.push(StackEntry {
                                 tree: entry.tree,
                                 index: new_index,
-                                seek_dimension: self.seek_dimension.clone(),
-                                sum_dimension: self.sum_dimension.clone(),
+                                position: self.position.clone(),
                             });
                             self.descend_to_last_item(&child_trees[new_index], cx);
                         }
                         Node::Leaf { item_summaries, .. } => {
                             for item_summary in &item_summaries[0..new_index] {
-                                self.seek_dimension.add_summary(item_summary, cx);
-                                self.sum_dimension.add_summary(item_summary, cx);
+                                self.position.add_summary(item_summary, cx);
                             }
                             self.stack.push(StackEntry {
                                 tree: entry.tree,
                                 index: new_index,
-                                seek_dimension: self.seek_dimension.clone(),
-                                sum_dimension: self.sum_dimension.clone(),
+                                position: self.position.clone(),
                             });
                         }
                     }
@@ -241,8 +194,7 @@ where
             self.stack.push(StackEntry {
                 tree: self.tree,
                 index: 0,
-                seek_dimension: S::default(),
-                sum_dimension: U::default(),
+                position: D::default(),
             });
             descend = true;
             self.did_seek = true;
@@ -258,8 +210,7 @@ where
                         ..
                     } => {
                         if !descend {
-                            entry.seek_dimension = self.seek_dimension.clone();
-                            entry.sum_dimension = self.sum_dimension.clone();
+                            entry.position = self.position.clone();
                             entry.index += 1;
                         }
 
@@ -268,8 +219,7 @@ where
                             if filter_node(next_summary) {
                                 break;
                             } else {
-                                self.seek_dimension.add_summary(next_summary, cx);
-                                self.sum_dimension.add_summary(next_summary, cx);
+                                self.position.add_summary(next_summary, cx);
                             }
                             entry.index += 1;
                         }
@@ -279,10 +229,8 @@ where
                     Node::Leaf { item_summaries, .. } => {
                         if !descend {
                             let item_summary = &item_summaries[entry.index];
-                            self.seek_dimension.add_summary(item_summary, cx);
-                            entry.seek_dimension.add_summary(item_summary, cx);
-                            self.sum_dimension.add_summary(item_summary, cx);
-                            entry.sum_dimension.add_summary(item_summary, cx);
+                            self.position.add_summary(item_summary, cx);
+                            entry.position.add_summary(item_summary, cx);
                             entry.index += 1;
                         }
 
@@ -291,10 +239,8 @@ where
                                 if filter_node(next_item_summary) {
                                     return;
                                 } else {
-                                    self.seek_dimension.add_summary(next_item_summary, cx);
-                                    entry.seek_dimension.add_summary(next_item_summary, cx);
-                                    self.sum_dimension.add_summary(next_item_summary, cx);
-                                    entry.sum_dimension.add_summary(next_item_summary, cx);
+                                    self.position.add_summary(next_item_summary, cx);
+                                    entry.position.add_summary(next_item_summary, cx);
                                     entry.index += 1;
                                 }
                             } else {
@@ -310,8 +256,7 @@ where
                 self.stack.push(StackEntry {
                     tree: subtree,
                     index: 0,
-                    seek_dimension: self.seek_dimension.clone(),
-                    sum_dimension: self.sum_dimension.clone(),
+                    position: self.position.clone(),
                 });
             } else {
                 descend = false;
@@ -337,29 +282,25 @@ where
                     ..
                 } => {
                     for summary in &child_summaries[0..child_summaries.len() - 1] {
-                        self.seek_dimension.add_summary(summary, cx);
-                        self.sum_dimension.add_summary(summary, cx);
+                        self.position.add_summary(summary, cx);
                     }
 
                     self.stack.push(StackEntry {
                         tree: subtree,
                         index: child_trees.len() - 1,
-                        seek_dimension: self.seek_dimension.clone(),
-                        sum_dimension: self.sum_dimension.clone(),
+                        position: self.position.clone(),
                     });
                     subtree = child_trees.last().unwrap();
                 }
                 Node::Leaf { item_summaries, .. } => {
                     let last_index = item_summaries.len().saturating_sub(1);
                     for item_summary in &item_summaries[0..last_index] {
-                        self.seek_dimension.add_summary(item_summary, cx);
-                        self.sum_dimension.add_summary(item_summary, cx);
+                        self.position.add_summary(item_summary, cx);
                     }
                     self.stack.push(StackEntry {
                         tree: subtree,
                         index: last_index,
-                        seek_dimension: self.seek_dimension.clone(),
-                        sum_dimension: self.sum_dimension.clone(),
+                        position: self.position.clone(),
                     });
                     break;
                 }
@@ -368,34 +309,47 @@ where
     }
 }
 
-impl<'a, T, S, U> Cursor<'a, T, S, U>
+impl<'a, T, D> Cursor<'a, T, D>
 where
     T: Item,
-    S: SeekDimension<'a, T::Summary>,
-    U: Dimension<'a, T::Summary>,
+    D: Dimension<'a, T::Summary>,
 {
-    pub fn seek(&mut self, pos: &S, bias: Bias, cx: &<T::Summary as Summary>::Context) -> bool {
+    pub fn seek<Target>(
+        &mut self,
+        pos: &Target,
+        bias: Bias,
+        cx: &<T::Summary as Summary>::Context,
+    ) -> bool
+    where
+        Target: SeekTarget<'a, T::Summary, D>,
+    {
         self.reset();
-        self.seek_internal::<()>(Some(pos), bias, &mut SeekAggregate::None, cx)
+        self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
     }
 
-    pub fn seek_forward(
+    pub fn seek_forward<Target>(
         &mut self,
-        pos: &S,
+        pos: &Target,
         bias: Bias,
         cx: &<T::Summary as Summary>::Context,
-    ) -> bool {
-        self.seek_internal::<()>(Some(pos), bias, &mut SeekAggregate::None, cx)
+    ) -> bool
+    where
+        Target: SeekTarget<'a, T::Summary, D>,
+    {
+        self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
     }
 
-    pub fn slice(
+    pub fn slice<Target>(
         &mut self,
-        end: &S,
+        end: &Target,
         bias: Bias,
         cx: &<T::Summary as Summary>::Context,
-    ) -> SumTree<T> {
+    ) -> SumTree<T>
+    where
+        Target: SeekTarget<'a, T::Summary, D>,
+    {
         let mut slice = SeekAggregate::Slice(SumTree::new());
-        self.seek_internal::<()>(Some(end), bias, &mut slice, cx);
+        self.seek_internal::<_, ()>(end, bias, &mut slice, cx);
         if let SeekAggregate::Slice(slice) = slice {
             slice
         } else {
@@ -405,7 +359,7 @@ where
 
     pub fn suffix(&mut self, cx: &<T::Summary as Summary>::Context) -> SumTree<T> {
         let mut slice = SeekAggregate::Slice(SumTree::new());
-        self.seek_internal::<()>(None, Bias::Right, &mut slice, cx);
+        self.seek_internal::<_, ()>(&End::new(), Bias::Right, &mut slice, cx);
         if let SeekAggregate::Slice(slice) = slice {
             slice
         } else {
@@ -413,12 +367,18 @@ where
         }
     }
 
-    pub fn summary<D>(&mut self, end: &S, bias: Bias, cx: &<T::Summary as Summary>::Context) -> D
+    pub fn summary<Target, Output>(
+        &mut self,
+        end: &Target,
+        bias: Bias,
+        cx: &<T::Summary as Summary>::Context,
+    ) -> Output
     where
-        D: Dimension<'a, T::Summary>,
+        Target: SeekTarget<'a, T::Summary, D>,
+        Output: Dimension<'a, T::Summary>,
     {
-        let mut summary = SeekAggregate::Summary(D::default());
-        self.seek_internal(Some(end), bias, &mut summary, cx);
+        let mut summary = SeekAggregate::Summary(Output::default());
+        self.seek_internal(end, bias, &mut summary, cx);
         if let SeekAggregate::Summary(summary) = summary {
             summary
         } else {
@@ -426,32 +386,30 @@ where
         }
     }
 
-    fn seek_internal<D>(
+    fn seek_internal<Target, Output>(
         &mut self,
-        target: Option<&S>,
+        target: &Target,
         bias: Bias,
-        aggregate: &mut SeekAggregate<T, D>,
+        aggregate: &mut SeekAggregate<T, Output>,
         cx: &<T::Summary as Summary>::Context,
     ) -> bool
     where
-        D: Dimension<'a, T::Summary>,
+        Target: SeekTarget<'a, T::Summary, D>,
+        Output: Dimension<'a, T::Summary>,
     {
-        if let Some(target) = target {
-            debug_assert!(
-                target.cmp(&self.seek_dimension, cx) >= Ordering::Equal,
-                "cannot seek backward from {:?} to {:?}",
-                self.seek_dimension,
-                target
-            );
-        }
+        debug_assert!(
+            target.cmp(&self.position, cx) >= Ordering::Equal,
+            "cannot seek backward from {:?} to {:?}",
+            self.position,
+            target
+        );
 
         if !self.did_seek {
             self.did_seek = true;
             self.stack.push(StackEntry {
                 tree: self.tree,
                 index: 0,
-                seek_dimension: Default::default(),
-                sum_dimension: Default::default(),
+                position: Default::default(),
             });
         }
 
@@ -471,16 +429,14 @@ where
                         .iter()
                         .zip(&child_summaries[entry.index..])
                     {
-                        let mut child_end = self.seek_dimension.clone();
+                        let mut child_end = self.position.clone();
                         child_end.add_summary(&child_summary, cx);
 
-                        let comparison =
-                            target.map_or(Ordering::Greater, |t| t.cmp(&child_end, cx));
+                        let comparison = target.cmp(&child_end, cx);
                         if comparison == Ordering::Greater
                             || (comparison == Ordering::Equal && bias == Bias::Right)
                         {
-                            self.seek_dimension = child_end;
-                            self.sum_dimension.add_summary(child_summary, cx);
+                            self.position = child_end;
                             match aggregate {
                                 SeekAggregate::None => {}
                                 SeekAggregate::Slice(slice) => {
@@ -491,14 +447,12 @@ where
                                 }
                             }
                             entry.index += 1;
-                            entry.seek_dimension = self.seek_dimension.clone();
-                            entry.sum_dimension = self.sum_dimension.clone();
+                            entry.position = self.position.clone();
                         } else {
                             self.stack.push(StackEntry {
                                 tree: child_tree,
                                 index: 0,
-                                seek_dimension: self.seek_dimension.clone(),
-                                sum_dimension: self.sum_dimension.clone(),
+                                position: self.position.clone(),
                             });
                             ascending = false;
                             continue 'outer;
@@ -521,25 +475,24 @@ where
                         .iter()
                         .zip(&item_summaries[entry.index..])
                     {
-                        let mut child_end = self.seek_dimension.clone();
+                        let mut child_end = self.position.clone();
                         child_end.add_summary(item_summary, cx);
 
-                        let comparison =
-                            target.map_or(Ordering::Greater, |t| t.cmp(&child_end, cx));
+                        let comparison = target.cmp(&child_end, cx);
                         if comparison == Ordering::Greater
                             || (comparison == Ordering::Equal && bias == Bias::Right)
                         {
-                            self.seek_dimension = child_end;
-                            self.sum_dimension.add_summary(item_summary, cx);
+                            self.position = child_end;
                             match aggregate {
                                 SeekAggregate::None => {}
                                 SeekAggregate::Slice(_) => {
                                     slice_items.push(item.clone());
                                     slice_item_summaries.push(item_summary.clone());
-                                    slice_items_summary
-                                        .as_mut()
-                                        .unwrap()
-                                        .add_summary(item_summary, cx);
+                                    <T::Summary as Summary>::add_summary(
+                                        slice_items_summary.as_mut().unwrap(),
+                                        item_summary,
+                                        cx,
+                                    );
                                 }
                                 SeekAggregate::Summary(summary) => {
                                     summary.add_summary(item_summary, cx);
@@ -583,23 +536,22 @@ where
         self.at_end = self.stack.is_empty();
         debug_assert!(self.stack.is_empty() || self.stack.last().unwrap().tree.0.is_leaf());
 
-        let mut end = self.seek_dimension.clone();
+        let mut end = self.position.clone();
         if bias == Bias::Left {
             if let Some(summary) = self.item_summary() {
                 end.add_summary(summary, cx);
             }
         }
 
-        target.map_or(false, |t| t.cmp(&end, cx) == Ordering::Equal)
+        target.cmp(&end, cx) == Ordering::Equal
     }
 }
 
-impl<'a, T, S, Seek, Sum> Iterator for Cursor<'a, T, Seek, Sum>
+impl<'a, T, S, D> Iterator for Cursor<'a, T, D>
 where
     T: Item<Summary = S>,
     S: Summary<Context = ()>,
-    Seek: Dimension<'a, T::Summary>,
-    Sum: Dimension<'a, T::Summary>,
+    D: Dimension<'a, T::Summary>,
 {
     type Item = &'a T;
 
@@ -617,45 +569,23 @@ where
     }
 }
 
-impl<'a, T, S, U> Cursor<'a, T, S, U>
-where
-    T: Item,
-    S: SeekDimension<'a, T::Summary>,
-    U: SeekDimension<'a, T::Summary>,
-{
-    pub fn swap_dimensions(self) -> Cursor<'a, T, U, S> {
-        Cursor {
-            tree: self.tree,
-            stack: self
-                .stack
-                .into_iter()
-                .map(StackEntry::swap_dimensions)
-                .collect(),
-            seek_dimension: self.sum_dimension,
-            sum_dimension: self.seek_dimension,
-            did_seek: self.did_seek,
-            at_end: self.at_end,
-        }
-    }
-}
-
-pub struct FilterCursor<'a, F: Fn(&T::Summary) -> bool, T: Item, U> {
-    cursor: Cursor<'a, T, (), U>,
+pub struct FilterCursor<'a, F: Fn(&T::Summary) -> bool, T: Item, D> {
+    cursor: Cursor<'a, T, D>,
     filter_node: F,
 }
 
-impl<'a, F, T, U> FilterCursor<'a, F, T, U>
+impl<'a, F, T, D> FilterCursor<'a, F, T, D>
 where
     F: Fn(&T::Summary) -> bool,
     T: Item,
-    U: Dimension<'a, T::Summary>,
+    D: Dimension<'a, T::Summary>,
 {
     pub fn new(
         tree: &'a SumTree<T>,
         filter_node: F,
         cx: &<T::Summary as Summary>::Context,
     ) -> Self {
-        let mut cursor = tree.cursor::<(), U>();
+        let mut cursor = tree.cursor::<D>();
         cursor.next_internal(&filter_node, cx);
         Self {
             cursor,
@@ -663,8 +593,8 @@ where
         }
     }
 
-    pub fn start(&self) -> &U {
-        self.cursor.sum_start()
+    pub fn start(&self) -> &D {
+        self.cursor.start()
     }
 
     pub fn item(&self) -> Option<&'a T> {

server/src/rpc.rs 🔗

@@ -2271,7 +2271,7 @@ mod tests {
     fn channel_messages(channel: &Channel) -> Vec<(String, String, bool)> {
         channel
             .messages()
-            .cursor::<(), ()>()
+            .cursor::<()>()
             .map(|m| {
                 (
                     m.sender.github_login.clone(),

zed/src/channel.rs 🔗

@@ -68,7 +68,7 @@ pub struct ChannelMessageSummary {
     count: usize,
 }
 
-#[derive(Copy, Clone, Debug, Default)]
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
 struct Count(usize);
 
 pub enum ChannelListEvent {}
@@ -387,19 +387,19 @@ impl Channel {
     }
 
     pub fn message(&self, ix: usize) -> &ChannelMessage {
-        let mut cursor = self.messages.cursor::<Count, ()>();
+        let mut cursor = self.messages.cursor::<Count>();
         cursor.seek(&Count(ix), Bias::Right, &());
         cursor.item().unwrap()
     }
 
     pub fn messages_in_range(&self, range: Range<usize>) -> impl Iterator<Item = &ChannelMessage> {
-        let mut cursor = self.messages.cursor::<Count, ()>();
+        let mut cursor = self.messages.cursor::<Count>();
         cursor.seek(&Count(range.start), Bias::Right, &());
         cursor.take(range.len())
     }
 
     pub fn pending_messages(&self) -> impl Iterator<Item = &ChannelMessage> {
-        let mut cursor = self.messages.cursor::<ChannelMessageId, ()>();
+        let mut cursor = self.messages.cursor::<ChannelMessageId>();
         cursor.seek(&ChannelMessageId::Pending(0), Bias::Left, &());
         cursor
     }
@@ -433,13 +433,13 @@ impl Channel {
     fn insert_messages(&mut self, messages: SumTree<ChannelMessage>, cx: &mut ModelContext<Self>) {
         if let Some((first_message, last_message)) = messages.first().zip(messages.last()) {
             let nonces = messages
-                .cursor::<(), ()>()
+                .cursor::<()>()
                 .map(|m| m.nonce)
                 .collect::<HashSet<_>>();
 
-            let mut old_cursor = self.messages.cursor::<ChannelMessageId, Count>();
+            let mut old_cursor = self.messages.cursor::<(ChannelMessageId, Count)>();
             let mut new_messages = old_cursor.slice(&first_message.id, Bias::Left, &());
-            let start_ix = old_cursor.sum_start().0;
+            let start_ix = old_cursor.start().1 .0;
             let removed_messages = old_cursor.slice(&last_message.id, Bias::Right, &());
             let removed_count = removed_messages.summary().count;
             let new_count = messages.summary().count;
@@ -457,7 +457,7 @@ impl Channel {
                 );
 
                 while let Some(message) = old_cursor.item() {
-                    let message_ix = old_cursor.sum_start().0;
+                    let message_ix = old_cursor.start().1 .0;
                     if nonces.contains(&message.nonce) {
                         if ranges.last().map_or(false, |r| r.end == message_ix) {
                             ranges.last_mut().unwrap().end += 1;
@@ -591,12 +591,6 @@ impl<'a> sum_tree::Dimension<'a, ChannelMessageSummary> for Count {
     }
 }
 
-impl<'a> sum_tree::SeekDimension<'a, ChannelMessageSummary> for Count {
-    fn cmp(&self, other: &Self, _: &()) -> std::cmp::Ordering {
-        Ord::cmp(&self.0, &other.0)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;

zed/src/editor/buffer.rs 🔗

@@ -1455,21 +1455,21 @@ impl Buffer {
         let cx = Some(version.clone());
         let mut new_ropes =
             RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
-        let mut old_fragments = self.fragments.cursor::<VersionedOffset, VersionedOffset>();
+        let mut old_fragments = self.fragments.cursor::<VersionedOffset>();
         let mut new_fragments =
             old_fragments.slice(&VersionedOffset::Offset(ranges[0].start), Bias::Left, &cx);
         new_ropes.push_tree(new_fragments.summary().text);
 
-        let mut fragment_start = old_fragments.sum_start().offset();
+        let mut fragment_start = old_fragments.start().offset();
         for range in ranges {
-            let fragment_end = old_fragments.sum_end(&cx).offset();
+            let fragment_end = old_fragments.end(&cx).offset();
 
             // If the current fragment ends before this range, then jump ahead to the first fragment
             // that extends past the start of this range, reusing any intervening fragments.
             if fragment_end < range.start {
                 // If the current fragment has been partially consumed, then consume the rest of it
                 // and advance to the next fragment before slicing.
-                if fragment_start > old_fragments.sum_start().offset() {
+                if fragment_start > old_fragments.start().offset() {
                     if fragment_end > fragment_start {
                         let mut suffix = old_fragments.item().unwrap().clone();
                         suffix.len = fragment_end - fragment_start;
@@ -1483,18 +1483,18 @@ impl Buffer {
                     old_fragments.slice(&VersionedOffset::Offset(range.start), Bias::Left, &cx);
                 new_ropes.push_tree(slice.summary().text);
                 new_fragments.push_tree(slice, &None);
-                fragment_start = old_fragments.sum_start().offset();
+                fragment_start = old_fragments.start().offset();
             }
 
             // If we are at the end of a non-concurrent fragment, advance to the next one.
-            let fragment_end = old_fragments.sum_end(&cx).offset();
+            let fragment_end = old_fragments.end(&cx).offset();
             if fragment_end == range.start && fragment_end > fragment_start {
                 let mut fragment = old_fragments.item().unwrap().clone();
                 fragment.len = fragment_end - fragment_start;
                 new_ropes.push_fragment(&fragment, fragment.visible);
                 new_fragments.push(fragment, &None);
                 old_fragments.next(&cx);
-                fragment_start = old_fragments.sum_start().offset();
+                fragment_start = old_fragments.start().offset();
             }
 
             // Skip over insertions that are concurrent to this edit, but have a lower lamport
@@ -1541,7 +1541,7 @@ impl Buffer {
             // portions as deleted.
             while fragment_start < range.end {
                 let fragment = old_fragments.item().unwrap();
-                let fragment_end = old_fragments.sum_end(&cx).offset();
+                let fragment_end = old_fragments.end(&cx).offset();
                 let mut intersection = fragment.clone();
                 let intersection_end = cmp::min(range.end, fragment_end);
                 if fragment.was_visible(version, &self.undo_map) {
@@ -1562,8 +1562,8 @@ impl Buffer {
 
         // If the current fragment has been partially consumed, then consume the rest of it
         // and advance to the next fragment before slicing.
-        if fragment_start > old_fragments.sum_start().offset() {
-            let fragment_end = old_fragments.sum_end(&cx).offset();
+        if fragment_start > old_fragments.start().offset() {
+            let fragment_end = old_fragments.end(&cx).offset();
             if fragment_end > fragment_start {
                 let mut suffix = old_fragments.item().unwrap().clone();
                 suffix.len = fragment_end - fragment_start;
@@ -1679,7 +1679,7 @@ impl Buffer {
         }
         let cx = Some(cx);
 
-        let mut old_fragments = self.fragments.cursor::<VersionedOffset, VersionedOffset>();
+        let mut old_fragments = self.fragments.cursor::<VersionedOffset>();
         let mut new_fragments = old_fragments.slice(
             &VersionedOffset::Offset(undo.ranges[0].start),
             Bias::Right,
@@ -1690,7 +1690,7 @@ impl Buffer {
         new_ropes.push_tree(new_fragments.summary().text);
 
         for range in &undo.ranges {
-            let mut end_offset = old_fragments.sum_end(&cx).offset();
+            let mut end_offset = old_fragments.end(&cx).offset();
 
             if end_offset < range.start {
                 let preceding_fragments =
@@ -1714,7 +1714,7 @@ impl Buffer {
                     new_fragments.push(fragment, &None);
 
                     old_fragments.next(&cx);
-                    if end_offset == old_fragments.sum_end(&cx).offset() {
+                    if end_offset == old_fragments.end(&cx).offset() {
                         let unseen_fragments = old_fragments.slice(
                             &VersionedOffset::Offset(end_offset),
                             Bias::Right,
@@ -1723,7 +1723,7 @@ impl Buffer {
                         new_ropes.push_tree(unseen_fragments.summary().text);
                         new_fragments.push_tree(unseen_fragments, &None);
                     }
-                    end_offset = old_fragments.sum_end(&cx).offset();
+                    end_offset = old_fragments.end(&cx).offset();
                 } else {
                     break;
                 }
@@ -1799,20 +1799,20 @@ impl Buffer {
 
         let mut new_ropes =
             RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
-        let mut old_fragments = self.fragments.cursor::<usize, FragmentTextSummary>();
+        let mut old_fragments = self.fragments.cursor::<(usize, FragmentTextSummary)>();
         let mut new_fragments = old_fragments.slice(&ranges[0].start, Bias::Right, &None);
         new_ropes.push_tree(new_fragments.summary().text);
 
-        let mut fragment_start = old_fragments.sum_start().visible;
+        let mut fragment_start = old_fragments.start().1.visible;
         for range in ranges {
-            let fragment_end = old_fragments.sum_end(&None).visible;
+            let fragment_end = old_fragments.end(&None).1.visible;
 
             // If the current fragment ends before this range, then jump ahead to the first fragment
             // that extends past the start of this range, reusing any intervening fragments.
             if fragment_end < range.start {
                 // If the current fragment has been partially consumed, then consume the rest of it
                 // and advance to the next fragment before slicing.
-                if fragment_start > old_fragments.sum_start().visible {
+                if fragment_start > old_fragments.start().1.visible {
                     if fragment_end > fragment_start {
                         let mut suffix = old_fragments.item().unwrap().clone();
                         suffix.len = fragment_end - fragment_start;
@@ -1825,10 +1825,10 @@ impl Buffer {
                 let slice = old_fragments.slice(&range.start, Bias::Right, &None);
                 new_ropes.push_tree(slice.summary().text);
                 new_fragments.push_tree(slice, &None);
-                fragment_start = old_fragments.sum_start().visible;
+                fragment_start = old_fragments.start().1.visible;
             }
 
-            let full_range_start = range.start + old_fragments.sum_start().deleted;
+            let full_range_start = range.start + old_fragments.start().1.deleted;
 
             // Preserve any portion of the current fragment that precedes this range.
             if fragment_start < range.start {
@@ -1858,7 +1858,7 @@ impl Buffer {
             // portions as deleted.
             while fragment_start < range.end {
                 let fragment = old_fragments.item().unwrap();
-                let fragment_end = old_fragments.sum_end(&None).visible;
+                let fragment_end = old_fragments.end(&None).1.visible;
                 let mut intersection = fragment.clone();
                 let intersection_end = cmp::min(range.end, fragment_end);
                 if fragment.visible {
@@ -1876,14 +1876,14 @@ impl Buffer {
                 }
             }
 
-            let full_range_end = range.end + old_fragments.sum_start().deleted;
+            let full_range_end = range.end + old_fragments.start().1.deleted;
             edit.ranges.push(full_range_start..full_range_end);
         }
 
         // If the current fragment has been partially consumed, then consume the rest of it
         // and advance to the next fragment before slicing.
-        if fragment_start > old_fragments.sum_start().visible {
-            let fragment_end = old_fragments.sum_end(&None).visible;
+        if fragment_start > old_fragments.start().1.visible {
+            let fragment_end = old_fragments.end(&None).1.visible;
             if fragment_end > fragment_start {
                 let mut suffix = old_fragments.item().unwrap().clone();
                 suffix.len = fragment_end - fragment_start;
@@ -2156,14 +2156,14 @@ impl<'a> Content<'a> {
 
     fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
         let cx = Some(anchor.version.clone());
-        let mut cursor = self.fragments.cursor::<VersionedOffset, usize>();
+        let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>();
         cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
         let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
-            anchor.offset - cursor.seek_start().offset()
+            anchor.offset - cursor.start().0.offset()
         } else {
             0
         };
-        self.text_summary_for_range(0..*cursor.sum_start() + overshoot)
+        self.text_summary_for_range(0..cursor.start().1 + overshoot)
     }
 
     fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
@@ -2174,10 +2174,10 @@ impl<'a> Content<'a> {
         let offset = position.to_offset(self);
         let max_offset = self.len();
         assert!(offset <= max_offset, "offset is out of range");
-        let mut cursor = self.fragments.cursor::<usize, FragmentTextSummary>();
+        let mut cursor = self.fragments.cursor::<(usize, FragmentTextSummary)>();
         cursor.seek(&offset, bias, &None);
         Anchor {
-            offset: offset + cursor.sum_start().deleted,
+            offset: offset + cursor.start().1.deleted,
             bias,
             version: self.version.clone(),
         }
@@ -2187,14 +2187,14 @@ impl<'a> Content<'a> {
         let cx = Some(anchor.version.clone());
         let mut cursor = self
             .fragments
-            .cursor::<VersionedOffset, FragmentTextSummary>();
+            .cursor::<(VersionedOffset, FragmentTextSummary)>();
         cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
         let overshoot = if cursor.item().is_some() {
-            anchor.offset - cursor.seek_start().offset()
+            anchor.offset - cursor.start().0.offset()
         } else {
             0
         };
-        let summary = cursor.sum_start();
+        let summary = cursor.start().1;
         summary.visible + summary.deleted + overshoot
     }
 
@@ -2589,7 +2589,7 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset {
     }
 }
 
-impl<'a> sum_tree::SeekDimension<'a, FragmentSummary> for VersionedOffset {
+impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedOffset {
     fn cmp(&self, other: &Self, _: &Option<time::Global>) -> cmp::Ordering {
         match (self, other) {
             (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b),

zed/src/editor/buffer/rope.rs 🔗

@@ -22,7 +22,7 @@ impl Rope {
     }
 
     pub fn append(&mut self, rope: Rope) {
-        let mut chunks = rope.chunks.cursor::<(), ()>();
+        let mut chunks = rope.chunks.cursor::<()>();
         chunks.next(&());
         if let Some(chunk) = chunks.item() {
             if self.chunks.last().map_or(false, |c| c.0.len() < CHUNK_BASE)
@@ -83,7 +83,7 @@ impl Rope {
         {
             // Ensure all chunks except maybe the last one are not underflowing.
             // Allow some wiggle room for multibyte characters at chunk boundaries.
-            let mut chunks = self.chunks.cursor::<(), ()>().peekable();
+            let mut chunks = self.chunks.cursor::<()>().peekable();
             while let Some(chunk) = chunks.next() {
                 if chunks.peek().is_some() {
                     assert!(chunk.0.len() + 3 >= CHUNK_BASE);
@@ -126,10 +126,10 @@ impl Rope {
 
     pub fn to_point(&self, offset: usize) -> Point {
         assert!(offset <= self.summary().bytes);
-        let mut cursor = self.chunks.cursor::<usize, Point>();
+        let mut cursor = self.chunks.cursor::<(usize, Point)>();
         cursor.seek(&offset, Bias::Left, &());
-        let overshoot = offset - cursor.seek_start();
-        *cursor.sum_start()
+        let overshoot = offset - cursor.start().0;
+        cursor.start().1
             + cursor
                 .item()
                 .map_or(Point::zero(), |chunk| chunk.to_point(overshoot))
@@ -137,17 +137,17 @@ impl Rope {
 
     pub fn to_offset(&self, point: Point) -> usize {
         assert!(point <= self.summary().lines);
-        let mut cursor = self.chunks.cursor::<Point, usize>();
+        let mut cursor = self.chunks.cursor::<(Point, usize)>();
         cursor.seek(&point, Bias::Left, &());
-        let overshoot = point - cursor.seek_start();
-        cursor.sum_start() + cursor.item().map_or(0, |chunk| chunk.to_offset(overshoot))
+        let overshoot = point - cursor.start().0;
+        cursor.start().1 + cursor.item().map_or(0, |chunk| chunk.to_offset(overshoot))
     }
 
     pub fn clip_offset(&self, mut offset: usize, bias: Bias) -> usize {
-        let mut cursor = self.chunks.cursor::<usize, ()>();
+        let mut cursor = self.chunks.cursor::<usize>();
         cursor.seek(&offset, Bias::Left, &());
         if let Some(chunk) = cursor.item() {
-            let mut ix = offset - cursor.seek_start();
+            let mut ix = offset - cursor.start();
             while !chunk.0.is_char_boundary(ix) {
                 match bias {
                     Bias::Left => {
@@ -167,11 +167,11 @@ impl Rope {
     }
 
     pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
-        let mut cursor = self.chunks.cursor::<Point, ()>();
+        let mut cursor = self.chunks.cursor::<Point>();
         cursor.seek(&point, Bias::Right, &());
         if let Some(chunk) = cursor.item() {
-            let overshoot = point - cursor.seek_start();
-            *cursor.seek_start() + chunk.clip_point(overshoot, bias)
+            let overshoot = point - cursor.start();
+            *cursor.start() + chunk.clip_point(overshoot, bias)
         } else {
             self.summary().lines
         }
@@ -194,7 +194,7 @@ impl Into<String> for Rope {
 
 pub struct Cursor<'a> {
     rope: &'a Rope,
-    chunks: sum_tree::Cursor<'a, Chunk, usize, ()>,
+    chunks: sum_tree::Cursor<'a, Chunk, usize>,
     offset: usize,
 }
 
@@ -226,18 +226,18 @@ impl<'a> Cursor<'a> {
 
         let mut slice = Rope::new();
         if let Some(start_chunk) = self.chunks.item() {
-            let start_ix = self.offset - self.chunks.seek_start();
-            let end_ix = cmp::min(end_offset, self.chunks.seek_end(&())) - self.chunks.seek_start();
+            let start_ix = self.offset - self.chunks.start();
+            let end_ix = cmp::min(end_offset, self.chunks.end(&())) - self.chunks.start();
             slice.push(&start_chunk.0[start_ix..end_ix]);
         }
 
-        if end_offset > self.chunks.seek_end(&()) {
+        if end_offset > self.chunks.end(&()) {
             self.chunks.next(&());
             slice.append(Rope {
                 chunks: self.chunks.slice(&end_offset, Bias::Right, &()),
             });
             if let Some(end_chunk) = self.chunks.item() {
-                let end_ix = end_offset - self.chunks.seek_start();
+                let end_ix = end_offset - self.chunks.start();
                 slice.push(&end_chunk.0[..end_ix]);
             }
         }
@@ -251,16 +251,16 @@ impl<'a> Cursor<'a> {
 
         let mut summary = TextSummary::default();
         if let Some(start_chunk) = self.chunks.item() {
-            let start_ix = self.offset - self.chunks.seek_start();
-            let end_ix = cmp::min(end_offset, self.chunks.seek_end(&())) - self.chunks.seek_start();
+            let start_ix = self.offset - self.chunks.start();
+            let end_ix = cmp::min(end_offset, self.chunks.end(&())) - self.chunks.start();
             summary = TextSummary::from(&start_chunk.0[start_ix..end_ix]);
         }
 
-        if end_offset > self.chunks.seek_end(&()) {
+        if end_offset > self.chunks.end(&()) {
             self.chunks.next(&());
             summary += &self.chunks.summary(&end_offset, Bias::Right, &());
             if let Some(end_chunk) = self.chunks.item() {
-                let end_ix = end_offset - self.chunks.seek_start();
+                let end_ix = end_offset - self.chunks.start();
                 summary += TextSummary::from(&end_chunk.0[..end_ix]);
             }
         }
@@ -278,7 +278,7 @@ impl<'a> Cursor<'a> {
 }
 
 pub struct Chunks<'a> {
-    chunks: sum_tree::Cursor<'a, Chunk, usize, ()>,
+    chunks: sum_tree::Cursor<'a, Chunk, usize>,
     range: Range<usize>,
 }
 
@@ -290,11 +290,11 @@ impl<'a> Chunks<'a> {
     }
 
     pub fn offset(&self) -> usize {
-        self.range.start.max(*self.chunks.seek_start())
+        self.range.start.max(*self.chunks.start())
     }
 
     pub fn seek(&mut self, offset: usize) {
-        if offset >= self.chunks.seek_end(&()) {
+        if offset >= self.chunks.end(&()) {
             self.chunks.seek_forward(&offset, Bias::Right, &());
         } else {
             self.chunks.seek(&offset, Bias::Right, &());
@@ -304,10 +304,10 @@ impl<'a> Chunks<'a> {
 
     pub fn peek(&self) -> Option<&'a str> {
         if let Some(chunk) = self.chunks.item() {
-            let offset = *self.chunks.seek_start();
+            let offset = *self.chunks.start();
             if self.range.end > offset {
-                let start = self.range.start.saturating_sub(*self.chunks.seek_start());
-                let end = self.range.end - self.chunks.seek_start();
+                let start = self.range.start.saturating_sub(*self.chunks.start());
+                let end = self.range.end - self.chunks.start();
                 return Some(&chunk.0[start..chunk.0.len().min(end)]);
             }
         }
@@ -486,12 +486,6 @@ impl std::ops::AddAssign<Self> for TextSummary {
     }
 }
 
-impl<'a> sum_tree::Dimension<'a, TextSummary> for TextSummary {
-    fn add_summary(&mut self, summary: &'a TextSummary, _: &()) {
-        *self += summary;
-    }
-}
-
 impl<'a> sum_tree::Dimension<'a, TextSummary> for usize {
     fn add_summary(&mut self, summary: &'a TextSummary, _: &()) {
         *self += summary.bytes;
@@ -611,7 +605,7 @@ mod tests {
     impl Rope {
         fn text(&self) -> String {
             let mut text = String::new();
-            for chunk in self.chunks.cursor::<(), ()>() {
+            for chunk in self.chunks.cursor::<()>() {
                 text.push_str(&chunk.0);
             }
             text

zed/src/editor/display_map/fold_map.rs 🔗

@@ -41,33 +41,35 @@ impl FoldPoint {
     }
 
     pub fn to_buffer_point(&self, snapshot: &Snapshot) -> Point {
-        let mut cursor = snapshot.transforms.cursor::<FoldPoint, Point>();
+        let mut cursor = snapshot.transforms.cursor::<(FoldPoint, Point)>();
         cursor.seek(self, Bias::Right, &());
-        let overshoot = self.0 - cursor.seek_start().0;
-        *cursor.sum_start() + overshoot
+        let overshoot = self.0 - cursor.start().0 .0;
+        cursor.start().1 + overshoot
     }
 
     pub fn to_buffer_offset(&self, snapshot: &Snapshot) -> usize {
-        let mut cursor = snapshot.transforms.cursor::<FoldPoint, Point>();
+        let mut cursor = snapshot.transforms.cursor::<(FoldPoint, Point)>();
         cursor.seek(self, Bias::Right, &());
-        let overshoot = self.0 - cursor.seek_start().0;
+        let overshoot = self.0 - cursor.start().0 .0;
         snapshot
             .buffer_snapshot
-            .to_offset(*cursor.sum_start() + overshoot)
+            .to_offset(cursor.start().1 + overshoot)
     }
 
     pub fn to_offset(&self, snapshot: &Snapshot) -> FoldOffset {
-        let mut cursor = snapshot.transforms.cursor::<FoldPoint, TransformSummary>();
+        let mut cursor = snapshot
+            .transforms
+            .cursor::<(FoldPoint, TransformSummary)>();
         cursor.seek(self, Bias::Right, &());
-        let overshoot = self.0 - cursor.sum_start().output.lines;
-        let mut offset = cursor.sum_start().output.bytes;
+        let overshoot = self.0 - cursor.start().1.output.lines;
+        let mut offset = cursor.start().1.output.bytes;
         if !overshoot.is_zero() {
             let transform = cursor.item().expect("display point out of range");
             assert!(transform.output_text.is_none());
             let end_buffer_offset = snapshot
                 .buffer_snapshot
-                .to_offset(cursor.sum_start().input.lines + overshoot);
-            offset += end_buffer_offset - cursor.sum_start().input.bytes;
+                .to_offset(cursor.start().1.input.lines + overshoot);
+            offset += end_buffer_offset - cursor.start().1.input.bytes;
         }
         FoldOffset(offset)
     }
@@ -75,19 +77,19 @@ impl FoldPoint {
 
 impl Point {
     pub fn to_fold_point(&self, snapshot: &Snapshot, bias: Bias) -> FoldPoint {
-        let mut cursor = snapshot.transforms.cursor::<Point, FoldPoint>();
+        let mut cursor = snapshot.transforms.cursor::<(Point, FoldPoint)>();
         cursor.seek(self, Bias::Right, &());
         if cursor.item().map_or(false, |t| t.is_fold()) {
-            if bias == Bias::Left || *self == *cursor.seek_start() {
-                *cursor.sum_start()
+            if bias == Bias::Left || *self == cursor.start().0 {
+                cursor.start().1
             } else {
-                cursor.sum_end(&())
+                cursor.end(&()).1
             }
         } else {
-            let overshoot = *self - cursor.seek_start();
+            let overshoot = *self - cursor.start().0;
             FoldPoint(cmp::min(
-                cursor.sum_start().0 + overshoot,
-                cursor.sum_end(&()).0,
+                cursor.start().1 .0 + overshoot,
+                cursor.end(&()).1 .0,
             ))
         }
     }
@@ -117,11 +119,11 @@ impl<'a> FoldMapWriter<'a> {
             }
         }
 
-        folds.sort_unstable_by(|a, b| sum_tree::SeekDimension::cmp(a, b, &buffer));
+        folds.sort_unstable_by(|a, b| sum_tree::SeekTarget::cmp(a, b, &buffer));
 
         self.0.folds = {
             let mut new_tree = SumTree::new();
-            let mut cursor = self.0.folds.cursor::<_, ()>();
+            let mut cursor = self.0.folds.cursor::<Fold>();
             for fold in folds {
                 new_tree.push_tree(cursor.slice(&fold, Bias::Right, &buffer), &buffer);
                 new_tree.push(fold, &buffer);
@@ -168,7 +170,7 @@ impl<'a> FoldMapWriter<'a> {
         fold_ixs_to_delete.dedup();
 
         self.0.folds = {
-            let mut cursor = self.0.folds.cursor::<_, ()>();
+            let mut cursor = self.0.folds.cursor::<usize>();
             let mut folds = SumTree::new();
             for fold_ix in fold_ixs_to_delete {
                 folds.push_tree(cursor.slice(&fold_ix, Bias::Right, &buffer), &buffer);
@@ -287,20 +289,20 @@ impl FoldMap {
 
         let mut new_transforms = SumTree::new();
         let mut transforms = self.transforms.lock();
-        let mut cursor = transforms.cursor::<usize, ()>();
+        let mut cursor = transforms.cursor::<usize>();
         cursor.seek(&0, Bias::Right, &());
 
         while let Some(mut edit) = buffer_edits_iter.next() {
             new_transforms.push_tree(cursor.slice(&edit.old_bytes.start, Bias::Left, &()), &());
-            edit.new_bytes.start -= edit.old_bytes.start - cursor.seek_start();
-            edit.old_bytes.start = *cursor.seek_start();
+            edit.new_bytes.start -= edit.old_bytes.start - cursor.start();
+            edit.old_bytes.start = *cursor.start();
 
             cursor.seek(&edit.old_bytes.end, Bias::Right, &());
             cursor.next(&());
 
             let mut delta = edit.delta();
             loop {
-                edit.old_bytes.end = *cursor.seek_start();
+                edit.old_bytes.end = *cursor.start();
 
                 if let Some(next_edit) = buffer_edits_iter.peek() {
                     if next_edit.old_bytes.start > edit.old_bytes.end {
@@ -324,7 +326,7 @@ impl FoldMap {
                 ((edit.new_bytes.start + edit.deleted_bytes()) as isize + delta) as usize;
 
             let anchor = buffer.anchor_before(edit.new_bytes.start);
-            let mut folds_cursor = self.folds.cursor::<_, ()>();
+            let mut folds_cursor = self.folds.cursor::<Fold>();
             folds_cursor.seek(&Fold(anchor..Anchor::max()), Bias::Left, &buffer);
 
             let mut folds = iter::from_fn({
@@ -432,39 +434,39 @@ impl FoldMap {
 
         let mut fold_edits = Vec::with_capacity(buffer_edits.len());
         {
-            let mut old_transforms = transforms.cursor::<usize, FoldOffset>();
-            let mut new_transforms = new_transforms.cursor::<usize, FoldOffset>();
+            let mut old_transforms = transforms.cursor::<(usize, FoldOffset)>();
+            let mut new_transforms = new_transforms.cursor::<(usize, FoldOffset)>();
 
             for mut edit in buffer_edits {
                 old_transforms.seek(&edit.old_bytes.start, Bias::Left, &());
                 if old_transforms.item().map_or(false, |t| t.is_fold()) {
-                    edit.old_bytes.start = *old_transforms.seek_start();
+                    edit.old_bytes.start = old_transforms.start().0;
                 }
-                let old_start = old_transforms.sum_start().0
-                    + (edit.old_bytes.start - old_transforms.seek_start());
+                let old_start =
+                    old_transforms.start().1 .0 + (edit.old_bytes.start - old_transforms.start().0);
 
                 old_transforms.seek_forward(&edit.old_bytes.end, Bias::Right, &());
                 if old_transforms.item().map_or(false, |t| t.is_fold()) {
                     old_transforms.next(&());
-                    edit.old_bytes.end = *old_transforms.seek_start();
+                    edit.old_bytes.end = old_transforms.start().0;
                 }
-                let old_end = old_transforms.sum_start().0
-                    + (edit.old_bytes.end - old_transforms.seek_start());
+                let old_end =
+                    old_transforms.start().1 .0 + (edit.old_bytes.end - old_transforms.start().0);
 
                 new_transforms.seek(&edit.new_bytes.start, Bias::Left, &());
                 if new_transforms.item().map_or(false, |t| t.is_fold()) {
-                    edit.new_bytes.start = *new_transforms.seek_start();
+                    edit.new_bytes.start = new_transforms.start().0;
                 }
-                let new_start = new_transforms.sum_start().0
-                    + (edit.new_bytes.start - new_transforms.seek_start());
+                let new_start =
+                    new_transforms.start().1 .0 + (edit.new_bytes.start - new_transforms.start().0);
 
                 new_transforms.seek_forward(&edit.new_bytes.end, Bias::Right, &());
                 if new_transforms.item().map_or(false, |t| t.is_fold()) {
                     new_transforms.next(&());
-                    edit.new_bytes.end = *new_transforms.seek_start();
+                    edit.new_bytes.end = new_transforms.start().0;
                 }
-                let new_end = new_transforms.sum_start().0
-                    + (edit.new_bytes.end - new_transforms.seek_start());
+                let new_end =
+                    new_transforms.start().1 .0 + (edit.new_bytes.end - new_transforms.start().0);
 
                 fold_edits.push(FoldEdit {
                     old_bytes: FoldOffset(old_start)..FoldOffset(old_end),
@@ -503,38 +505,37 @@ impl Snapshot {
     pub fn text_summary_for_range(&self, range: Range<FoldPoint>) -> TextSummary {
         let mut summary = TextSummary::default();
 
-        let mut cursor = self.transforms.cursor::<FoldPoint, Point>();
+        let mut cursor = self.transforms.cursor::<(FoldPoint, Point)>();
         cursor.seek(&range.start, Bias::Right, &());
         if let Some(transform) = cursor.item() {
-            let start_in_transform = range.start.0 - cursor.seek_start().0;
-            let end_in_transform =
-                cmp::min(range.end, cursor.seek_end(&())).0 - cursor.seek_start().0;
+            let start_in_transform = range.start.0 - cursor.start().0 .0;
+            let end_in_transform = cmp::min(range.end, cursor.end(&()).0).0 - cursor.start().0 .0;
             if let Some(output_text) = transform.output_text {
                 summary = TextSummary::from(
                     &output_text
                         [start_in_transform.column as usize..end_in_transform.column as usize],
                 );
             } else {
-                let buffer_start = *cursor.sum_start() + start_in_transform;
-                let buffer_end = *cursor.sum_start() + end_in_transform;
+                let buffer_start = cursor.start().1 + start_in_transform;
+                let buffer_end = cursor.start().1 + end_in_transform;
                 summary = self
                     .buffer_snapshot
                     .text_summary_for_range(buffer_start..buffer_end);
             }
         }
 
-        if range.end > cursor.seek_end(&()) {
+        if range.end > cursor.end(&()).0 {
             cursor.next(&());
             summary += &cursor
-                .summary::<TransformSummary>(&range.end, Bias::Right, &())
+                .summary::<_, TransformSummary>(&range.end, Bias::Right, &())
                 .output;
             if let Some(transform) = cursor.item() {
-                let end_in_transform = range.end.0 - cursor.seek_start().0;
+                let end_in_transform = range.end.0 - cursor.start().0 .0;
                 if let Some(output_text) = transform.output_text {
                     summary += TextSummary::from(&output_text[..end_in_transform.column as usize]);
                 } else {
-                    let buffer_start = *cursor.sum_start();
-                    let buffer_end = *cursor.sum_start() + end_in_transform;
+                    let buffer_start = cursor.start().1;
+                    let buffer_end = cursor.start().1 + end_in_transform;
                     summary += self
                         .buffer_snapshot
                         .text_summary_for_range(buffer_start..buffer_end);
@@ -600,19 +601,19 @@ impl Snapshot {
         T: ToOffset,
     {
         let offset = offset.to_offset(&self.buffer_snapshot);
-        let mut cursor = self.transforms.cursor::<usize, ()>();
+        let mut cursor = self.transforms.cursor::<usize>();
         cursor.seek(&offset, Bias::Right, &());
         cursor.item().map_or(false, |t| t.output_text.is_some())
     }
 
     pub fn is_line_folded(&self, output_row: u32) -> bool {
-        let mut cursor = self.transforms.cursor::<FoldPoint, ()>();
+        let mut cursor = self.transforms.cursor::<FoldPoint>();
         cursor.seek(&FoldPoint::new(output_row, 0), Bias::Right, &());
         while let Some(transform) = cursor.item() {
             if transform.output_text.is_some() {
                 return true;
             }
-            if cursor.seek_end(&()).row() == output_row {
+            if cursor.end(&()).row() == output_row {
                 cursor.next(&())
             } else {
                 break;
@@ -622,10 +623,10 @@ impl Snapshot {
     }
 
     pub fn chunks_at(&self, offset: FoldOffset) -> Chunks {
-        let mut transform_cursor = self.transforms.cursor::<FoldOffset, usize>();
+        let mut transform_cursor = self.transforms.cursor::<(FoldOffset, usize)>();
         transform_cursor.seek(&offset, Bias::Right, &());
-        let overshoot = offset.0 - transform_cursor.seek_start().0;
-        let buffer_offset = transform_cursor.sum_start() + overshoot;
+        let overshoot = offset.0 - transform_cursor.start().0 .0;
+        let buffer_offset = transform_cursor.start().1 + overshoot;
         Chunks {
             transform_cursor,
             buffer_offset,
@@ -636,15 +637,15 @@ impl Snapshot {
     }
 
     pub fn highlighted_chunks(&mut self, range: Range<FoldOffset>) -> HighlightedChunks {
-        let mut transform_cursor = self.transforms.cursor::<FoldOffset, usize>();
+        let mut transform_cursor = self.transforms.cursor::<(FoldOffset, usize)>();
 
         transform_cursor.seek(&range.end, Bias::Right, &());
-        let overshoot = range.end.0 - transform_cursor.seek_start().0;
-        let buffer_end = transform_cursor.sum_start() + overshoot;
+        let overshoot = range.end.0 - transform_cursor.start().0 .0;
+        let buffer_end = transform_cursor.start().1 + overshoot;
 
         transform_cursor.seek(&range.start, Bias::Right, &());
-        let overshoot = range.start.0 - transform_cursor.seek_start().0;
-        let buffer_start = transform_cursor.sum_start() + overshoot;
+        let overshoot = range.start.0 - transform_cursor.start().0 .0;
+        let buffer_start = transform_cursor.start().1 + overshoot;
 
         HighlightedChunks {
             transform_cursor,
@@ -663,19 +664,19 @@ impl Snapshot {
 
     #[cfg(test)]
     pub fn clip_offset(&self, offset: FoldOffset, bias: Bias) -> FoldOffset {
-        let mut cursor = self.transforms.cursor::<FoldOffset, usize>();
+        let mut cursor = self.transforms.cursor::<(FoldOffset, usize)>();
         cursor.seek(&offset, Bias::Right, &());
         if let Some(transform) = cursor.item() {
-            let transform_start = cursor.seek_start().0;
+            let transform_start = cursor.start().0 .0;
             if transform.output_text.is_some() {
                 if offset.0 == transform_start || matches!(bias, Bias::Left) {
                     FoldOffset(transform_start)
                 } else {
-                    FoldOffset(cursor.seek_end(&()).0)
+                    FoldOffset(cursor.end(&()).0 .0)
                 }
             } else {
                 let overshoot = offset.0 - transform_start;
-                let buffer_offset = cursor.sum_start() + overshoot;
+                let buffer_offset = cursor.start().1 + overshoot;
                 let clipped_buffer_offset = self.buffer_snapshot.clip_offset(buffer_offset, bias);
                 FoldOffset(
                     (offset.0 as isize + (clipped_buffer_offset as isize - buffer_offset as isize))
@@ -688,19 +689,19 @@ impl Snapshot {
     }
 
     pub fn clip_point(&self, point: FoldPoint, bias: Bias) -> FoldPoint {
-        let mut cursor = self.transforms.cursor::<FoldPoint, Point>();
+        let mut cursor = self.transforms.cursor::<(FoldPoint, Point)>();
         cursor.seek(&point, Bias::Right, &());
         if let Some(transform) = cursor.item() {
-            let transform_start = cursor.seek_start().0;
+            let transform_start = cursor.start().0 .0;
             if transform.output_text.is_some() {
                 if point.0 == transform_start || matches!(bias, Bias::Left) {
                     FoldPoint(transform_start)
                 } else {
-                    FoldPoint(cursor.seek_end(&()).0)
+                    FoldPoint(cursor.end(&()).0 .0)
                 }
             } else {
                 let overshoot = point.0 - transform_start;
-                let buffer_position = *cursor.sum_start() + overshoot;
+                let buffer_position = cursor.start().1 + overshoot;
                 let clipped_buffer_position =
                     self.buffer_snapshot.clip_point(buffer_position, bias);
                 FoldPoint::new(
@@ -822,12 +823,6 @@ impl sum_tree::Summary for TransformSummary {
     }
 }
 
-impl<'a> sum_tree::Dimension<'a, TransformSummary> for TransformSummary {
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
-        sum_tree::Summary::add_summary(self, summary, &());
-    }
-}
-
 #[derive(Clone, Debug)]
 struct Fold(Range<Anchor>);
 
@@ -905,7 +900,7 @@ impl<'a> sum_tree::Dimension<'a, FoldSummary> for Fold {
     }
 }
 
-impl<'a> sum_tree::SeekDimension<'a, FoldSummary> for Fold {
+impl<'a> sum_tree::SeekTarget<'a, FoldSummary, Fold> for Fold {
     fn cmp(&self, other: &Self, buffer: &buffer::Snapshot) -> Ordering {
         self.0.cmp(&other.0, buffer).unwrap()
     }
@@ -918,7 +913,7 @@ impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize {
 }
 
 pub struct BufferRows<'a> {
-    cursor: Cursor<'a, Transform, FoldPoint, Point>,
+    cursor: Cursor<'a, Transform, (FoldPoint, Point)>,
     fold_point: FoldPoint,
 }
 
@@ -926,7 +921,7 @@ impl<'a> Iterator for BufferRows<'a> {
     type Item = u32;
 
     fn next(&mut self) -> Option<Self::Item> {
-        while self.fold_point > self.cursor.seek_end(&()) {
+        while self.fold_point > self.cursor.end(&()).0 {
             self.cursor.next(&());
             if self.cursor.item().is_none() {
                 // TODO: Return a bool from next?
@@ -935,8 +930,8 @@ impl<'a> Iterator for BufferRows<'a> {
         }
 
         if self.cursor.item().is_some() {
-            let overshoot = self.fold_point.0 - self.cursor.seek_start().0;
-            let buffer_point = *self.cursor.sum_start() + overshoot;
+            let overshoot = self.fold_point.0 - self.cursor.start().0 .0;
+            let buffer_point = self.cursor.start().1 + overshoot;
             *self.fold_point.row_mut() += 1;
             Some(buffer_point.row)
         } else {
@@ -946,7 +941,7 @@ impl<'a> Iterator for BufferRows<'a> {
 }
 
 pub struct Chunks<'a> {
-    transform_cursor: Cursor<'a, Transform, FoldOffset, usize>,
+    transform_cursor: Cursor<'a, Transform, (FoldOffset, usize)>,
     buffer_chunks: buffer::Chunks<'a>,
     buffer_offset: usize,
 }
@@ -967,7 +962,7 @@ impl<'a> Iterator for Chunks<'a> {
             self.buffer_offset += transform.summary.input.bytes;
             self.buffer_chunks.seek(self.buffer_offset);
 
-            while self.buffer_offset >= self.transform_cursor.sum_end(&())
+            while self.buffer_offset >= self.transform_cursor.end(&()).1
                 && self.transform_cursor.item().is_some()
             {
                 self.transform_cursor.next(&());
@@ -982,7 +977,7 @@ impl<'a> Iterator for Chunks<'a> {
             chunk = &chunk[offset_in_chunk..];
 
             // Truncate the chunk so that it ends at the next fold.
-            let region_end = self.transform_cursor.sum_end(&()) - self.buffer_offset;
+            let region_end = self.transform_cursor.end(&()).1 - self.buffer_offset;
             if chunk.len() >= region_end {
                 chunk = &chunk[0..region_end];
                 self.transform_cursor.next(&());
@@ -999,7 +994,7 @@ impl<'a> Iterator for Chunks<'a> {
 }
 
 pub struct HighlightedChunks<'a> {
-    transform_cursor: Cursor<'a, Transform, FoldOffset, usize>,
+    transform_cursor: Cursor<'a, Transform, (FoldOffset, usize)>,
     buffer_chunks: buffer::HighlightedChunks<'a>,
     buffer_chunk: Option<(usize, &'a str, HighlightId)>,
     buffer_offset: usize,
@@ -1022,7 +1017,7 @@ impl<'a> Iterator for HighlightedChunks<'a> {
             self.buffer_offset += transform.summary.input.bytes;
             self.buffer_chunks.seek(self.buffer_offset);
 
-            while self.buffer_offset >= self.transform_cursor.sum_end(&())
+            while self.buffer_offset >= self.transform_cursor.end(&()).1
                 && self.transform_cursor.item().is_some()
             {
                 self.transform_cursor.next(&());
@@ -1046,7 +1041,7 @@ impl<'a> Iterator for HighlightedChunks<'a> {
             chunk = &chunk[offset_in_chunk..];
 
             // Truncate the chunk so that it ends at the next fold.
-            let region_end = self.transform_cursor.sum_end(&()) - self.buffer_offset;
+            let region_end = self.transform_cursor.end(&()).1 - self.buffer_offset;
             if chunk.len() >= region_end {
                 chunk = &chunk[0..region_end];
                 self.transform_cursor.next(&());
@@ -1073,16 +1068,18 @@ pub struct FoldOffset(pub usize);
 
 impl FoldOffset {
     pub fn to_point(&self, snapshot: &Snapshot) -> FoldPoint {
-        let mut cursor = snapshot.transforms.cursor::<FoldOffset, TransformSummary>();
+        let mut cursor = snapshot
+            .transforms
+            .cursor::<(FoldOffset, TransformSummary)>();
         cursor.seek(self, Bias::Right, &());
         let overshoot = if cursor.item().map_or(true, |t| t.is_fold()) {
-            Point::new(0, (self.0 - cursor.seek_start().0) as u32)
+            Point::new(0, (self.0 - cursor.start().0 .0) as u32)
         } else {
-            let buffer_offset = cursor.sum_start().input.bytes + self.0 - cursor.seek_start().0;
+            let buffer_offset = cursor.start().1.input.bytes + self.0 - cursor.start().0 .0;
             let buffer_point = snapshot.buffer_snapshot.to_point(buffer_offset);
-            buffer_point - cursor.sum_start().input.lines
+            buffer_point - cursor.start().1.input.lines
         };
-        FoldPoint(cursor.sum_start().output.lines + overshoot)
+        FoldPoint(cursor.start().1.output.lines + overshoot)
     }
 }
 

zed/src/editor/display_map/wrap_map.rs 🔗

@@ -51,7 +51,7 @@ pub struct Chunks<'a> {
     input_chunks: tab_map::Chunks<'a>,
     input_chunk: &'a str,
     output_position: WrapPoint,
-    transforms: Cursor<'a, Transform, WrapPoint, TabPoint>,
+    transforms: Cursor<'a, Transform, (WrapPoint, TabPoint)>,
 }
 
 pub struct HighlightedChunks<'a> {
@@ -60,7 +60,7 @@ pub struct HighlightedChunks<'a> {
     style_id: HighlightId,
     output_position: WrapPoint,
     max_output_row: u32,
-    transforms: Cursor<'a, Transform, WrapPoint, TabPoint>,
+    transforms: Cursor<'a, Transform, (WrapPoint, TabPoint)>,
 }
 
 pub struct BufferRows<'a> {
@@ -69,7 +69,7 @@ pub struct BufferRows<'a> {
     output_row: u32,
     soft_wrapped: bool,
     max_output_row: u32,
-    transforms: Cursor<'a, Transform, WrapPoint, TabPoint>,
+    transforms: Cursor<'a, Transform, (WrapPoint, TabPoint)>,
 }
 
 impl WrapMap {
@@ -272,7 +272,7 @@ impl Snapshot {
         if edits.is_empty() {
             new_transforms = self.transforms.clone();
         } else {
-            let mut old_cursor = self.transforms.cursor::<TabPoint, ()>();
+            let mut old_cursor = self.transforms.cursor::<TabPoint>();
             let mut edits = edits.into_iter().peekable();
             new_transforms =
                 old_cursor.slice(&edits.peek().unwrap().old_lines.start, Bias::Right, &());
@@ -293,11 +293,11 @@ impl Snapshot {
 
                 old_cursor.seek_forward(&edit.old_lines.end, Bias::Right, &());
                 if let Some(next_edit) = edits.peek() {
-                    if next_edit.old_lines.start > old_cursor.seek_end(&()) {
-                        if old_cursor.seek_end(&()) > edit.old_lines.end {
-                            let summary = self.tab_snapshot.text_summary_for_range(
-                                edit.old_lines.end..old_cursor.seek_end(&()),
-                            );
+                    if next_edit.old_lines.start > old_cursor.end(&()) {
+                        if old_cursor.end(&()) > edit.old_lines.end {
+                            let summary = self
+                                .tab_snapshot
+                                .text_summary_for_range(edit.old_lines.end..old_cursor.end(&()));
                             new_transforms.push_or_extend(Transform::isomorphic(summary));
                         }
                         old_cursor.next(&());
@@ -307,10 +307,10 @@ impl Snapshot {
                         );
                     }
                 } else {
-                    if old_cursor.seek_end(&()) > edit.old_lines.end {
+                    if old_cursor.end(&()) > edit.old_lines.end {
                         let summary = self
                             .tab_snapshot
-                            .text_summary_for_range(edit.old_lines.end..old_cursor.seek_end(&()));
+                            .text_summary_for_range(edit.old_lines.end..old_cursor.end(&()));
                         new_transforms.push_or_extend(Transform::isomorphic(summary));
                     }
                     old_cursor.next(&());
@@ -364,7 +364,7 @@ impl Snapshot {
             new_transforms = self.transforms.clone();
         } else {
             let mut row_edits = row_edits.into_iter().peekable();
-            let mut old_cursor = self.transforms.cursor::<TabPoint, ()>();
+            let mut old_cursor = self.transforms.cursor::<TabPoint>();
 
             new_transforms = old_cursor.slice(
                 &TabPoint::new(row_edits.peek().unwrap().old_rows.start, 0),
@@ -427,10 +427,10 @@ impl Snapshot {
 
                 old_cursor.seek_forward(&TabPoint::new(edit.old_rows.end, 0), Bias::Right, &());
                 if let Some(next_edit) = row_edits.peek() {
-                    if next_edit.old_rows.start > old_cursor.seek_end(&()).row() {
-                        if old_cursor.seek_end(&()) > TabPoint::new(edit.old_rows.end, 0) {
+                    if next_edit.old_rows.start > old_cursor.end(&()).row() {
+                        if old_cursor.end(&()) > TabPoint::new(edit.old_rows.end, 0) {
                             let summary = self.tab_snapshot.text_summary_for_range(
-                                TabPoint::new(edit.old_rows.end, 0)..old_cursor.seek_end(&()),
+                                TabPoint::new(edit.old_rows.end, 0)..old_cursor.end(&()),
                             );
                             new_transforms.push_or_extend(Transform::isomorphic(summary));
                         }
@@ -445,9 +445,9 @@ impl Snapshot {
                         );
                     }
                 } else {
-                    if old_cursor.seek_end(&()) > TabPoint::new(edit.old_rows.end, 0) {
+                    if old_cursor.end(&()) > TabPoint::new(edit.old_rows.end, 0) {
                         let summary = self.tab_snapshot.text_summary_for_range(
-                            TabPoint::new(edit.old_rows.end, 0)..old_cursor.seek_end(&()),
+                            TabPoint::new(edit.old_rows.end, 0)..old_cursor.end(&()),
                         );
                         new_transforms.push_or_extend(Transform::isomorphic(summary));
                     }
@@ -465,11 +465,11 @@ impl Snapshot {
 
     pub fn chunks_at(&self, wrap_row: u32) -> Chunks {
         let point = WrapPoint::new(wrap_row, 0);
-        let mut transforms = self.transforms.cursor::<WrapPoint, TabPoint>();
+        let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>();
         transforms.seek(&point, Bias::Right, &());
-        let mut input_position = TabPoint(transforms.sum_start().0);
+        let mut input_position = TabPoint(transforms.start().1 .0);
         if transforms.item().map_or(false, |t| t.is_isomorphic()) {
-            input_position.0 += point.0 - transforms.seek_start().0;
+            input_position.0 += point.0 - transforms.start().0 .0;
         }
         let input_chunks = self.tab_snapshot.chunks_at(input_position);
         Chunks {
@@ -483,11 +483,11 @@ impl Snapshot {
     pub fn highlighted_chunks_for_rows(&mut self, rows: Range<u32>) -> HighlightedChunks {
         let output_start = WrapPoint::new(rows.start, 0);
         let output_end = WrapPoint::new(rows.end, 0);
-        let mut transforms = self.transforms.cursor::<WrapPoint, TabPoint>();
+        let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>();
         transforms.seek(&output_start, Bias::Right, &());
-        let mut input_start = TabPoint(transforms.sum_start().0);
+        let mut input_start = TabPoint(transforms.start().1 .0);
         if transforms.item().map_or(false, |t| t.is_isomorphic()) {
-            input_start.0 += output_start.0 - transforms.seek_start().0;
+            input_start.0 += output_start.0 - transforms.start().0 .0;
         }
         let input_end = self
             .to_tab_point(output_end)
@@ -520,7 +520,7 @@ impl Snapshot {
     }
 
     pub fn soft_wrap_indent(&self, row: u32) -> Option<u32> {
-        let mut cursor = self.transforms.cursor::<_, ()>();
+        let mut cursor = self.transforms.cursor::<WrapPoint>();
         cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Right, &());
         cursor.item().and_then(|transform| {
             if transform.is_isomorphic() {
@@ -536,11 +536,11 @@ impl Snapshot {
     }
 
     pub fn buffer_rows(&self, start_row: u32) -> BufferRows {
-        let mut transforms = self.transforms.cursor::<WrapPoint, TabPoint>();
+        let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>();
         transforms.seek(&WrapPoint::new(start_row, 0), Bias::Left, &());
-        let mut input_row = transforms.sum_start().row();
+        let mut input_row = transforms.start().1.row();
         if transforms.item().map_or(false, |t| t.is_isomorphic()) {
-            input_row += start_row - transforms.seek_start().row();
+            input_row += start_row - transforms.start().0.row();
         }
         let soft_wrapped = transforms.item().map_or(false, |t| !t.is_isomorphic());
         let mut input_buffer_rows = self.tab_snapshot.buffer_rows(input_row);
@@ -556,27 +556,27 @@ impl Snapshot {
     }
 
     pub fn to_tab_point(&self, point: WrapPoint) -> TabPoint {
-        let mut cursor = self.transforms.cursor::<WrapPoint, TabPoint>();
+        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>();
         cursor.seek(&point, Bias::Right, &());
-        let mut tab_point = cursor.sum_start().0;
+        let mut tab_point = cursor.start().1 .0;
         if cursor.item().map_or(false, |t| t.is_isomorphic()) {
-            tab_point += point.0 - cursor.seek_start().0;
+            tab_point += point.0 - cursor.start().0 .0;
         }
         TabPoint(tab_point)
     }
 
     pub fn to_wrap_point(&self, point: TabPoint) -> WrapPoint {
-        let mut cursor = self.transforms.cursor::<TabPoint, WrapPoint>();
+        let mut cursor = self.transforms.cursor::<(TabPoint, WrapPoint)>();
         cursor.seek(&point, Bias::Right, &());
-        WrapPoint(cursor.sum_start().0 + (point.0 - cursor.seek_start().0))
+        WrapPoint(cursor.start().1 .0 + (point.0 - cursor.start().0 .0))
     }
 
     pub fn clip_point(&self, mut point: WrapPoint, bias: Bias) -> WrapPoint {
         if bias == Bias::Left {
-            let mut cursor = self.transforms.cursor::<WrapPoint, ()>();
+            let mut cursor = self.transforms.cursor::<WrapPoint>();
             cursor.seek(&point, Bias::Right, &());
             if cursor.item().map_or(false, |t| !t.is_isomorphic()) {
-                point = *cursor.seek_start();
+                point = *cursor.start();
                 *point.column_mut() -= 1;
             }
         }
@@ -593,7 +593,7 @@ impl Snapshot {
             );
 
             {
-                let mut transforms = self.transforms.cursor::<(), ()>().peekable();
+                let mut transforms = self.transforms.cursor::<()>().peekable();
                 while let Some(transform) = transforms.next() {
                     if let Some(next_transform) = transforms.peek() {
                         assert!(transform.is_isomorphic() != next_transform.is_isomorphic());
@@ -638,7 +638,7 @@ impl<'a> Iterator for Chunks<'a> {
     fn next(&mut self) -> Option<Self::Item> {
         let transform = self.transforms.item()?;
         if let Some(display_text) = transform.display_text {
-            if self.output_position > *self.transforms.seek_start() {
+            if self.output_position > self.transforms.start().0 {
                 self.output_position.0.column += transform.summary.output.lines.column;
                 self.transforms.next(&());
                 return Some(&display_text[1..]);
@@ -654,7 +654,7 @@ impl<'a> Iterator for Chunks<'a> {
         }
 
         let mut input_len = 0;
-        let transform_end = self.transforms.seek_end(&());
+        let transform_end = self.transforms.end(&()).0;
         for c in self.input_chunk.chars() {
             let char_len = c.len_utf8();
             input_len += char_len;
@@ -691,7 +691,7 @@ impl<'a> Iterator for HighlightedChunks<'a> {
             let mut end_ix = display_text.len();
             let mut summary = transform.summary.output.lines;
 
-            if self.output_position > *self.transforms.seek_start() {
+            if self.output_position > self.transforms.start().0 {
                 // Exclude newline starting prior to the desired row.
                 start_ix = 1;
                 summary.row = 0;
@@ -713,7 +713,7 @@ impl<'a> Iterator for HighlightedChunks<'a> {
         }
 
         let mut input_len = 0;
-        let transform_end = self.transforms.seek_end(&());
+        let transform_end = self.transforms.end(&()).0;
         for c in self.input_chunk.chars() {
             let char_len = c.len_utf8();
             input_len += char_len;

zed/src/worktree.rs 🔗

@@ -1140,7 +1140,7 @@ impl LocalWorktree {
             remote_id.await.map(|id| {
                 let entries = snapshot
                     .entries_by_path
-                    .cursor::<(), ()>()
+                    .cursor::<()>()
                     .filter(|e| !e.is_ignored)
                     .map(Into::into)
                     .collect();
@@ -1385,12 +1385,12 @@ impl Snapshot {
         let mut removed_entries = Vec::new();
         let mut self_entries = self
             .entries_by_id
-            .cursor::<(), ()>()
+            .cursor::<()>()
             .filter(|e| include_ignored || !e.is_ignored)
             .peekable();
         let mut other_entries = other
             .entries_by_id
-            .cursor::<(), ()>()
+            .cursor::<()>()
             .filter(|e| include_ignored || !e.is_ignored)
             .peekable();
         loop {
@@ -1485,7 +1485,7 @@ impl Snapshot {
     pub fn paths(&self) -> impl Iterator<Item = &Arc<Path>> {
         let empty_path = Path::new("");
         self.entries_by_path
-            .cursor::<(), ()>()
+            .cursor::<()>()
             .filter(move |entry| entry.path.as_ref() != empty_path)
             .map(|entry| &entry.path)
     }
@@ -1507,7 +1507,7 @@ impl Snapshot {
     }
 
     fn entry_for_path(&self, path: impl AsRef<Path>) -> Option<&Entry> {
-        let mut cursor = self.entries_by_path.cursor::<_, ()>();
+        let mut cursor = self.entries_by_path.cursor::<PathSearch>();
         if cursor.seek(&PathSearch::Exact(path.as_ref()), Bias::Left, &()) {
             cursor.item()
         } else {
@@ -1600,7 +1600,7 @@ impl Snapshot {
         let mut new_entries;
         let removed_entry_ids;
         {
-            let mut cursor = self.entries_by_path.cursor::<_, ()>();
+            let mut cursor = self.entries_by_path.cursor::<PathSearch>();
             new_entries = cursor.slice(&PathSearch::Exact(path), Bias::Left, &());
             removed_entry_ids = cursor.slice(&PathSearch::Successor(path), Bias::Left, &());
             new_entries.push_tree(cursor.suffix(&()), &());
@@ -1608,7 +1608,7 @@ impl Snapshot {
         self.entries_by_path = new_entries;
 
         let mut entries_by_id_edits = Vec::new();
-        for entry in removed_entry_ids.cursor::<(), ()>() {
+        for entry in removed_entry_ids.cursor::<()>() {
             let removed_entry_id = self
                 .removed_entry_ids
                 .entry(entry.inode)
@@ -1655,7 +1655,7 @@ impl Snapshot {
 
 impl fmt::Debug for Snapshot {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        for entry in self.entries_by_path.cursor::<(), ()>() {
+        for entry in self.entries_by_path.cursor::<()>() {
             for _ in entry.path.ancestors().skip(1) {
                 write!(f, " ")?;
             }
@@ -2556,8 +2556,8 @@ impl WorktreeHandle for ModelHandle<Worktree> {
 }
 
 pub enum FileIter<'a> {
-    All(Cursor<'a, Entry, FileCount, ()>),
-    Visible(Cursor<'a, Entry, VisibleFileCount, ()>),
+    All(Cursor<'a, Entry, FileCount>),
+    Visible(Cursor<'a, Entry, VisibleFileCount>),
 }
 
 impl<'a> FileIter<'a> {
@@ -2576,12 +2576,12 @@ impl<'a> FileIter<'a> {
     fn next_internal(&mut self) {
         match self {
             Self::All(cursor) => {
-                let ix = *cursor.seek_start();
-                cursor.seek_forward(&FileCount(ix.0 + 1), Bias::Right, &());
+                let ix = cursor.start().0;
+                cursor.seek_forward(&FileCount(ix + 1), Bias::Right, &());
             }
             Self::Visible(cursor) => {
-                let ix = *cursor.seek_start();
-                cursor.seek_forward(&VisibleFileCount(ix.0 + 1), Bias::Right, &());
+                let ix = cursor.start().0;
+                cursor.seek_forward(&VisibleFileCount(ix + 1), Bias::Right, &());
             }
         }
     }
@@ -2609,7 +2609,7 @@ impl<'a> Iterator for FileIter<'a> {
 
 struct ChildEntriesIter<'a> {
     parent_path: &'a Path,
-    cursor: Cursor<'a, Entry, PathSearch<'a>, ()>,
+    cursor: Cursor<'a, Entry, PathSearch<'a>>,
 }
 
 impl<'a> ChildEntriesIter<'a> {
@@ -3244,7 +3244,7 @@ mod tests {
                 let mut entries_by_id_edits = Vec::new();
                 for entry in prev_snapshot
                     .entries_by_id
-                    .cursor::<(), ()>()
+                    .cursor::<()>()
                     .filter(|e| e.is_ignored)
                 {
                     entries_by_path_edits.push(Edit::Remove(PathKey(entry.path.clone())));
@@ -3419,7 +3419,7 @@ mod tests {
         fn check_invariants(&self) {
             let mut files = self.files(0);
             let mut visible_files = self.visible_files(0);
-            for entry in self.entries_by_path.cursor::<(), ()>() {
+            for entry in self.entries_by_path.cursor::<()>() {
                 if entry.is_file() {
                     assert_eq!(files.next().unwrap().inode, entry.inode);
                     if !entry.is_ignored {
@@ -3442,7 +3442,7 @@ mod tests {
 
             let dfs_paths = self
                 .entries_by_path
-                .cursor::<(), ()>()
+                .cursor::<()>()
                 .map(|e| e.path.as_ref())
                 .collect::<Vec<_>>();
             assert_eq!(bfs_paths, dfs_paths);
@@ -3457,7 +3457,7 @@ mod tests {
 
         fn to_vec(&self, include_ignored: bool) -> Vec<(&Path, u64, bool)> {
             let mut paths = Vec::new();
-            for entry in self.entries_by_path.cursor::<(), ()>() {
+            for entry in self.entries_by_path.cursor::<()>() {
                 if include_ignored || !entry.is_ignored {
                     paths.push((entry.path.as_ref(), entry.inode, entry.is_ignored));
                 }