diff --git a/gpui/src/elements/list.rs b/gpui/src/elements/list.rs index 9fecfd6e61..219c175168 100644 --- a/gpui/src/elements/list.rs +++ b/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::(); + let mut cursor = old_items.cursor::(); 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::(); + let mut cursor = old_items.cursor::(); 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::(); + let mut cursor = state.items.cursor::(); 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::(); + let mut old_heights = state.items.cursor::(); 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 { - let mut cursor = self.items.cursor::(); + let mut cursor = self.items.cursor::(); 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 + 'a { let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item); - let mut cursor = self.items.cursor::(); + let mut cursor = self.items.cursor::(); 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::(); + let mut cursor = self.items.cursor::(); 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::(); + let mut cursor = self.items.cursor::(); 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; diff --git a/gpui/src/sum_tree.rs b/gpui/src/sum_tree.rs index c250845b3e..e256a1f33b 100644 --- a/gpui/src/sum_tree.rs +++ b/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, T: Dimension<'a, S> + Ord> SeekDimension<'a, S> for T { - fn cmp(&self, other: &Self, _ctx: &S::Context) -> Ordering { - Ord::cmp(self, other) +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(PhantomData); + +impl End { + fn new() -> Self { + Self(PhantomData) + } +} + +impl<'a, S: Summary, D: Dimension<'a, S>> SeekTarget<'a, S, D> for End { + fn cmp(&self, _: &D, _: &S::Context) -> Ordering { + Ordering::Greater + } +} + +impl fmt::Debug for End { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("End").finish() } } @@ -99,7 +141,7 @@ impl SumTree { #[allow(unused)] pub fn items(&self, cx: &::Context) -> Vec { 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 SumTree { items } - pub fn cursor<'a, S, U>(&'a self) -> Cursor + pub fn cursor<'a, S>(&'a self) -> Cursor where S: Dimension<'a, T::Summary>, - U: Dimension<'a, T::Summary>, { Cursor::new(self) } @@ -230,7 +271,7 @@ impl SumTree { }) = leaf.as_mut() { let item_summary = item.summary(); - summary.add_summary(&item_summary, cx); + ::add_summary(summary, &item_summary, cx); items.push(item); item_summaries.push(item_summary); } else { @@ -281,7 +322,7 @@ impl SumTree { .. } => { let other_node = other.0.clone(); - summary.add_summary(other_node.summary(), cx); + ::add_summary(summary, other_node.summary(), cx); let height_delta = *height - other_node.height(); let mut summaries_to_append = ArrayVec::::new(); @@ -378,7 +419,7 @@ impl SumTree { item_summaries: right_summaries, }))) } else { - summary.add_summary(other_node.summary(), cx); + ::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 SumTree { pub fn insert_or_replace(&mut self, item: T, cx: &::Context) -> bool { let mut replaced = false; *self = { - let mut cursor = self.cursor::(); + let mut cursor = self.cursor::(); let mut new_tree = cursor.slice(&item.key(), Bias::Left, cx); if cursor .item() @@ -459,7 +500,7 @@ impl SumTree { edits.sort_unstable_by_key(|item| item.key()); *self = { - let mut cursor = self.cursor::(); + let mut cursor = self.cursor::(); let mut new_tree = SumTree::new(); let mut buffered_items = Vec::new(); @@ -502,7 +543,7 @@ impl SumTree { } pub fn get(&self, key: &T::Key, cx: &::Context) -> Option<&T> { - let mut cursor = self.cursor::(); + let mut cursor = self.cursor::(); 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::(); + let mut cursor = tree.cursor::(); 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::(&()).0 + 1); let mut before_start = false; - let mut cursor = tree.cursor::(); + let mut cursor = tree.cursor::(); 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::(); + let mut cursor = tree.cursor::(); cursor.seek(&Count(start), start_bias, &()); let slice = cursor.slice(&Count(end), end_bias, &()); cursor.seek(&Count(start), start_bias, &()); - let summary = cursor.summary::(&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::::new(); - let mut cursor = tree.cursor::(); + let mut cursor = tree.cursor::(); assert_eq!( cursor.slice(&Count(0), Bias::Right, &()).items(&()), Vec::::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::::new(); tree.extend(vec![1], &()); - let mut cursor = tree.cursor::(); + let mut cursor = tree.cursor::(); assert_eq!( cursor.slice(&Count(0), Bias::Right, &()).items(&()), Vec::::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::(); + let mut cursor = tree.cursor::(); 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::(); + let mut cursor = tree.cursor::(); 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::(); + let mut cursor = tree.cursor::(); assert_eq!( cursor .slice(&tree.extent::(&()), 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> SeekTarget<'a, IntegersSummary, IntegersSummary> for Count { + fn cmp(&self, cursor_location: &IntegersSummary, _: &()) -> Ordering { + self.0.cmp(&cursor_location.count) } } impl<'a> Dimension<'a, IntegersSummary> for Sum { fn add_summary(&mut self, summary: &IntegersSummary, _: &()) { - self.0 += summary.sum.0; - } - } - - impl<'a> Add<&'a Self> for Sum { - type Output = Self; - - fn add(mut self, other: &Self) -> Self { - self.0 += other.0; - self + self.0 += summary.sum; } } } diff --git a/gpui/src/sum_tree/cursor.rs b/gpui/src/sum_tree/cursor.rs index 8b529ca522..f6f6f9a599 100644 --- a/gpui/src/sum_tree/cursor.rs +++ b/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, 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, - stack: ArrayVec, 16>, - seek_dimension: S, - sum_dimension: U, + stack: ArrayVec, 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) -> 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(); + self.position = D::default(); } - pub fn seek_start(&self) -> &S { - &self.seek_dimension + pub fn start(&self) -> &D { + &self.position } - pub fn seek_end(&self, cx: &::Context) -> S { + pub fn end(&self, cx: &::Context) -> D { if let Some(item_summary) = self.item_summary() { - let mut end = self.seek_start().clone(); + let mut end = self.start().clone(); end.add_summary(item_summary, cx); end } else { - self.seek_start().clone() - } - } - - pub fn sum_start(&self) -> &U { - &self.sum_dimension - } - - pub fn sum_end(&self, cx: &::Context) -> U { - if let Some(item_summary) = self.item_summary() { - let mut end = self.sum_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: &::Context) -> bool { + pub fn seek( + &mut self, + pos: &Target, + bias: Bias, + cx: &::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( &mut self, - pos: &S, + pos: &Target, bias: Bias, cx: &::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( &mut self, - end: &S, + end: &Target, bias: Bias, cx: &::Context, - ) -> SumTree { + ) -> SumTree + 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: &::Context) -> SumTree { 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(&mut self, end: &S, bias: Bias, cx: &::Context) -> D + pub fn summary( + &mut self, + end: &Target, + bias: Bias, + cx: &::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( + fn seek_internal( &mut self, - target: Option<&S>, + target: &Target, bias: Bias, - aggregate: &mut SeekAggregate, + aggregate: &mut SeekAggregate, cx: &::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); + ::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, S: Summary, - 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, filter_node: F, cx: &::Context, ) -> Self { - let mut cursor = tree.cursor::<(), U>(); + let mut cursor = tree.cursor::(); 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> { diff --git a/server/src/rpc.rs b/server/src/rpc.rs index a9ffdad899..e3b91c37f1 100644 --- a/server/src/rpc.rs +++ b/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(), diff --git a/zed/src/channel.rs b/zed/src/channel.rs index f0e7a90c9a..40807cc585 100644 --- a/zed/src/channel.rs +++ b/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::(); + let mut cursor = self.messages.cursor::(); cursor.seek(&Count(ix), Bias::Right, &()); cursor.item().unwrap() } pub fn messages_in_range(&self, range: Range) -> impl Iterator { - let mut cursor = self.messages.cursor::(); + let mut cursor = self.messages.cursor::(); cursor.seek(&Count(range.start), Bias::Right, &()); cursor.take(range.len()) } pub fn pending_messages(&self) -> impl Iterator { - let mut cursor = self.messages.cursor::(); + let mut cursor = self.messages.cursor::(); cursor.seek(&ChannelMessageId::Pending(0), Bias::Left, &()); cursor } @@ -433,13 +433,13 @@ impl Channel { fn insert_messages(&mut self, messages: SumTree, cx: &mut ModelContext) { if let Some((first_message, last_message)) = messages.first().zip(messages.last()) { let nonces = messages - .cursor::<(), ()>() + .cursor::<()>() .map(|m| m.nonce) .collect::>(); - let mut old_cursor = self.messages.cursor::(); + 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::*; diff --git a/zed/src/editor/buffer.rs b/zed/src/editor/buffer.rs index 8186b422ae..99be7d4181 100644 --- a/zed/src/editor/buffer.rs +++ b/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::(); + let mut old_fragments = self.fragments.cursor::(); 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::(); + let mut old_fragments = self.fragments.cursor::(); 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::(); + 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::(); + 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) -> 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::(); + 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::(); + .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) -> cmp::Ordering { match (self, other) { (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b), diff --git a/zed/src/editor/buffer/operation_queue.rs b/zed/src/editor/buffer/operation_queue.rs index b6efc3fc9c..97ec360b8f 100644 --- a/zed/src/editor/buffer/operation_queue.rs +++ b/zed/src/editor/buffer/operation_queue.rs @@ -43,7 +43,7 @@ impl OperationQueue { clone } - pub fn cursor(&self) -> Cursor { + pub fn cursor(&self) -> Cursor { self.0.cursor() } } diff --git a/zed/src/editor/buffer/rope.rs b/zed/src/editor/buffer/rope.rs index e9732e92c2..a4fe867da6 100644 --- a/zed/src/editor/buffer/rope.rs +++ 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::(); + 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::(); + 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::(); + let mut cursor = self.chunks.cursor::(); 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::(); + let mut cursor = self.chunks.cursor::(); 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 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, } @@ -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 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 diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 8aa01495e8..1fa3a22e3f 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/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::(); + 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::(); + 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::(); + 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::(); + 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::(); 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::(); 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::(); + let mut cursor = transforms.cursor::(); 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::(); 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::(); - let mut new_transforms = new_transforms.cursor::(); + 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) -> TextSummary { let mut summary = TextSummary::default(); - let mut cursor = self.transforms.cursor::(); + 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::(&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::(); + let mut cursor = self.transforms.cursor::(); 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::(); + let mut cursor = self.transforms.cursor::(); 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::(); + 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) -> HighlightedChunks { - let mut transform_cursor = self.transforms.cursor::(); + 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::(); + 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::(); + 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); @@ -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 { - 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::(); + 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) } } diff --git a/zed/src/editor/display_map/wrap_map.rs b/zed/src/editor/display_map/wrap_map.rs index 86e01f7e56..4bc31785ff 100644 --- a/zed/src/editor/display_map/wrap_map.rs +++ b/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::(); + let mut old_cursor = self.transforms.cursor::(); 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::(); + let mut old_cursor = self.transforms.cursor::(); 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::(); + 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) -> HighlightedChunks { let output_start = WrapPoint::new(rows.start, 0); let output_end = WrapPoint::new(rows.end, 0); - let mut transforms = self.transforms.cursor::(); + 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 { - let mut cursor = self.transforms.cursor::<_, ()>(); + let mut cursor = self.transforms.cursor::(); 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::(); + 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::(); + 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::(); + 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::(); + let mut cursor = self.transforms.cursor::(); 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 { 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; diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index 15cfd29463..bc412cd995 100644 --- a/zed/src/worktree.rs +++ b/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> { 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) -> Option<&Entry> { - let mut cursor = self.entries_by_path.cursor::<_, ()>(); + let mut cursor = self.entries_by_path.cursor::(); 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::(); 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 { } 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::>(); 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)); }