Allow seeking SumTree cursor by multiple seek types per dimension

Also, remove the cursor's sum_dimension. Replace it with a
blanket implementation of Dimension for two-element tuples
of dimensions.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2021-09-24 18:04:43 -07:00
parent 39fbf7d4d1
commit ab31ddfc31
11 changed files with 458 additions and 509 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -43,7 +43,7 @@ impl OperationQueue {
clone clone
} }
pub fn cursor(&self) -> Cursor<Operation, (), ()> { pub fn cursor(&self) -> Cursor<Operation, ()> {
self.0.cursor() self.0.cursor()
} }
} }

View file

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

View file

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

View file

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

View file

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