mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-29 21:49:33 +00:00
Batch anchor resolution, avoid cloning fragment ids when seeking
This commit is contained in:
parent
e9c385e7a6
commit
1ed1ec21dd
3 changed files with 73 additions and 12 deletions
|
@ -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>(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue