Batch anchor resolution, avoid cloning fragment ids when seeking

This commit is contained in:
Max Brunsfeld 2021-12-09 10:42:44 -08:00
parent e9c385e7a6
commit 1ed1ec21dd
3 changed files with 73 additions and 12 deletions

View file

@ -125,7 +125,18 @@ impl SelectionSet {
where
D: 'a + TextDimension<'a>,
{
self.selections.iter().map(|s| s.resolve(snapshot))
let anchors = self
.selections
.iter()
.flat_map(|selection| [&selection.start, &selection.end].into_iter());
let mut positions = snapshot.summaries_for_anchors::<D, _>(anchors);
self.selections.iter().map(move |selection| Selection {
start: positions.next().unwrap(),
end: positions.next().unwrap(),
goal: selection.goal,
reversed: selection.reversed,
id: selection.id,
})
}
pub fn intersecting_selections<'a, D, I>(

View file

@ -645,9 +645,9 @@ impl Buffer {
assert_eq!(insertion_fragment.fragment_id, fragment.id);
}
let mut cursor = self.snapshot.fragments.cursor::<Locator>();
let mut cursor = self.snapshot.fragments.cursor::<Option<&Locator>>();
for insertion_fragment in self.snapshot.insertions.cursor::<()>() {
cursor.seek(&insertion_fragment.fragment_id, Bias::Left, &None);
cursor.seek(&Some(&insertion_fragment.fragment_id), Bias::Left, &None);
let fragment = cursor.item().unwrap();
assert_eq!(insertion_fragment.fragment_id, fragment.id);
assert_eq!(insertion_fragment.split_offset, fragment.insertion_offset);

View file

@ -1672,6 +1672,56 @@ impl Snapshot {
result
}
pub fn summaries_for_anchors<'a, D, A>(&'a self, anchors: A) -> impl 'a + Iterator<Item = D>
where
D: 'a + TextDimension<'a>,
A: 'a + IntoIterator<Item = &'a Anchor>,
{
let anchors = anchors.into_iter();
let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, usize)>();
let mut text_cursor = self.visible_text.cursor(0);
let mut position = D::default();
anchors.map(move |anchor| {
if *anchor == Anchor::min() {
return D::default();
} else if *anchor == Anchor::max() {
return D::from_text_summary(&self.visible_text.summary());
}
let anchor_key = InsertionFragmentKey {
timestamp: anchor.timestamp,
split_offset: anchor.offset,
};
insertion_cursor.seek(&anchor_key, anchor.bias, &());
if let Some(insertion) = insertion_cursor.item() {
let comparison = sum_tree::KeyedItem::key(insertion).cmp(&anchor_key);
if comparison == Ordering::Greater
|| (anchor.bias == Bias::Left
&& comparison == Ordering::Equal
&& anchor.offset > 0)
{
insertion_cursor.prev(&());
}
} else {
insertion_cursor.prev(&());
}
let insertion = insertion_cursor.item().expect("invalid insertion");
debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
fragment_cursor.seek_forward(&Some(&insertion.fragment_id), Bias::Left, &None);
let fragment = fragment_cursor.item().unwrap();
let mut fragment_offset = fragment_cursor.start().1;
if fragment.visible {
fragment_offset += anchor.offset - insertion.split_offset;
}
position.add_assign(&text_cursor.summary(fragment_offset));
position.clone()
})
}
fn summary_for_anchor<'a, D>(&'a self, anchor: &Anchor) -> D
where
D: TextDimension<'a>,
@ -1702,8 +1752,8 @@ impl Snapshot {
let insertion = insertion_cursor.item().expect("invalid insertion");
debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
let mut fragment_cursor = self.fragments.cursor::<(Locator, usize)>();
fragment_cursor.seek(&insertion.fragment_id, Bias::Left, &None);
let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, usize)>();
fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left, &None);
let fragment = fragment_cursor.item().unwrap();
let mut fragment_offset = fragment_cursor.start().1;
if fragment.visible {
@ -1741,8 +1791,8 @@ impl Snapshot {
let insertion = insertion_cursor.item().expect("invalid insertion");
debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
let mut fragment_cursor = self.fragments.cursor::<(Locator, FullOffset)>();
fragment_cursor.seek(&insertion.fragment_id, Bias::Left, &None);
let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, FullOffset)>();
fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left, &None);
fragment_cursor.start().1 + (anchor.offset - insertion.split_offset)
}
}
@ -1771,10 +1821,10 @@ impl Snapshot {
} else if bias == Bias::Right && offset == self.len() {
Anchor::max()
} else {
let mut fragment_cursor = self.fragments.cursor::<(usize, Locator)>();
let mut fragment_cursor = self.fragments.cursor::<usize>();
fragment_cursor.seek(&offset, bias, &None);
let fragment = fragment_cursor.item().unwrap();
let overshoot = offset - fragment_cursor.start().0;
let overshoot = offset - *fragment_cursor.start();
Anchor {
timestamp: fragment.insertion_timestamp.local(),
offset: fragment.insertion_offset + overshoot,
@ -2111,9 +2161,9 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FullOffset {
}
}
impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Locator {
fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
self.assign(&summary.max_id);
impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Option<&'a Locator> {
fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<clock::Global>) {
*self = Some(&summary.max_id);
}
}