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
|
where
|
||||||
D: 'a + TextDimension<'a>,
|
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>(
|
pub fn intersecting_selections<'a, D, I>(
|
||||||
|
|
|
@ -645,9 +645,9 @@ impl Buffer {
|
||||||
assert_eq!(insertion_fragment.fragment_id, fragment.id);
|
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::<()>() {
|
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();
|
let fragment = cursor.item().unwrap();
|
||||||
assert_eq!(insertion_fragment.fragment_id, fragment.id);
|
assert_eq!(insertion_fragment.fragment_id, fragment.id);
|
||||||
assert_eq!(insertion_fragment.split_offset, fragment.insertion_offset);
|
assert_eq!(insertion_fragment.split_offset, fragment.insertion_offset);
|
||||||
|
|
|
@ -1672,6 +1672,56 @@ impl Snapshot {
|
||||||
result
|
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
|
fn summary_for_anchor<'a, D>(&'a self, anchor: &Anchor) -> D
|
||||||
where
|
where
|
||||||
D: TextDimension<'a>,
|
D: TextDimension<'a>,
|
||||||
|
@ -1702,8 +1752,8 @@ impl Snapshot {
|
||||||
let insertion = insertion_cursor.item().expect("invalid insertion");
|
let insertion = insertion_cursor.item().expect("invalid insertion");
|
||||||
debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
|
debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
|
||||||
|
|
||||||
let mut fragment_cursor = self.fragments.cursor::<(Locator, usize)>();
|
let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, usize)>();
|
||||||
fragment_cursor.seek(&insertion.fragment_id, Bias::Left, &None);
|
fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left, &None);
|
||||||
let fragment = fragment_cursor.item().unwrap();
|
let fragment = fragment_cursor.item().unwrap();
|
||||||
let mut fragment_offset = fragment_cursor.start().1;
|
let mut fragment_offset = fragment_cursor.start().1;
|
||||||
if fragment.visible {
|
if fragment.visible {
|
||||||
|
@ -1741,8 +1791,8 @@ impl Snapshot {
|
||||||
let insertion = insertion_cursor.item().expect("invalid insertion");
|
let insertion = insertion_cursor.item().expect("invalid insertion");
|
||||||
debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
|
debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
|
||||||
|
|
||||||
let mut fragment_cursor = self.fragments.cursor::<(Locator, FullOffset)>();
|
let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, FullOffset)>();
|
||||||
fragment_cursor.seek(&insertion.fragment_id, Bias::Left, &None);
|
fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left, &None);
|
||||||
fragment_cursor.start().1 + (anchor.offset - insertion.split_offset)
|
fragment_cursor.start().1 + (anchor.offset - insertion.split_offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1771,10 +1821,10 @@ impl Snapshot {
|
||||||
} else if bias == Bias::Right && offset == self.len() {
|
} else if bias == Bias::Right && offset == self.len() {
|
||||||
Anchor::max()
|
Anchor::max()
|
||||||
} else {
|
} else {
|
||||||
let mut fragment_cursor = self.fragments.cursor::<(usize, Locator)>();
|
let mut fragment_cursor = self.fragments.cursor::<usize>();
|
||||||
fragment_cursor.seek(&offset, bias, &None);
|
fragment_cursor.seek(&offset, bias, &None);
|
||||||
let fragment = fragment_cursor.item().unwrap();
|
let fragment = fragment_cursor.item().unwrap();
|
||||||
let overshoot = offset - fragment_cursor.start().0;
|
let overshoot = offset - *fragment_cursor.start();
|
||||||
Anchor {
|
Anchor {
|
||||||
timestamp: fragment.insertion_timestamp.local(),
|
timestamp: fragment.insertion_timestamp.local(),
|
||||||
offset: fragment.insertion_offset + overshoot,
|
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 {
|
impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Option<&'a Locator> {
|
||||||
fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
|
fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<clock::Global>) {
|
||||||
self.assign(&summary.max_id);
|
*self = Some(&summary.max_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue