@@ -1,88 +1,57 @@
-use crate::{rope::TextDimension, Snapshot};
-
-use super::{Buffer, ToOffset};
+use super::{rope::TextDimension, Buffer, Point, Snapshot, ToOffset};
use anyhow::Result;
use std::{cmp::Ordering, fmt::Debug, ops::Range};
use sum_tree::Bias;
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
-pub enum Anchor {
- Min,
- Insertion {
- timestamp: clock::Local,
- offset: usize,
- bias: Bias,
- },
- Max,
+pub struct Anchor {
+ pub timestamp: clock::Local,
+ pub offset: usize,
+ pub bias: Bias,
}
impl Anchor {
pub fn min() -> Self {
- Self::Min
+ Self {
+ timestamp: clock::Local::MIN,
+ offset: usize::MIN,
+ bias: Bias::Left,
+ }
}
pub fn max() -> Self {
- Self::Max
+ Self {
+ timestamp: clock::Local::MAX,
+ offset: usize::MAX,
+ bias: Bias::Right,
+ }
}
pub fn cmp<'a>(&self, other: &Anchor, buffer: &Snapshot) -> Result<Ordering> {
- match (self, other) {
- (Self::Min, Self::Min) => Ok(Ordering::Equal),
- (Self::Min, _) => Ok(Ordering::Less),
- (_, Self::Min) => Ok(Ordering::Greater),
- (Self::Max, Self::Max) => Ok(Ordering::Equal),
- (Self::Max, _) => Ok(Ordering::Greater),
- (_, Self::Max) => Ok(Ordering::Less),
- (
- Self::Insertion {
- timestamp: lhs_id,
- bias: lhs_bias,
- offset: lhs_offset,
- },
- Self::Insertion {
- timestamp: rhs_id,
- bias: rhs_bias,
- offset: rhs_offset,
- },
- ) => {
- let offset_comparison = if lhs_id == rhs_id {
- lhs_offset.cmp(&rhs_offset)
- } else {
- buffer
- .full_offset_for_anchor(self)
- .cmp(&buffer.full_offset_for_anchor(other))
- };
+ let offset_comparison = if self.timestamp == other.timestamp {
+ self.offset.cmp(&other.offset)
+ } else {
+ buffer
+ .full_offset_for_anchor(self)
+ .cmp(&buffer.full_offset_for_anchor(other))
+ };
- Ok(offset_comparison.then_with(|| lhs_bias.cmp(&rhs_bias)))
- }
- }
+ Ok(offset_comparison.then_with(|| self.bias.cmp(&other.bias)))
}
pub fn bias_left(&self, buffer: &Buffer) -> Anchor {
- match self {
- Anchor::Min => Anchor::Min,
- Anchor::Insertion { bias, .. } => {
- if *bias == Bias::Left {
- self.clone()
- } else {
- buffer.anchor_before(self)
- }
- }
- Anchor::Max => buffer.anchor_before(self),
+ if self.bias == Bias::Left {
+ self.clone()
+ } else {
+ buffer.anchor_before(self)
}
}
pub fn bias_right(&self, buffer: &Buffer) -> Anchor {
- match self {
- Anchor::Min => buffer.anchor_after(self),
- Anchor::Insertion { bias, .. } => {
- if *bias == Bias::Right {
- self.clone()
- } else {
- buffer.anchor_after(self)
- }
- }
- Anchor::Max => Anchor::Max,
+ if self.bias == Bias::Right {
+ self.clone()
+ } else {
+ buffer.anchor_after(self)
}
}
@@ -97,6 +66,7 @@ impl Anchor {
pub trait AnchorRangeExt {
fn cmp(&self, b: &Range<Anchor>, buffer: &Snapshot) -> Result<Ordering>;
fn to_offset(&self, content: &Snapshot) -> Range<usize>;
+ fn to_point(&self, content: &Snapshot) -> Range<Point>;
}
impl AnchorRangeExt for Range<Anchor> {
@@ -110,4 +80,8 @@ impl AnchorRangeExt for Range<Anchor> {
fn to_offset(&self, content: &Snapshot) -> Range<usize> {
self.start.to_offset(&content)..self.end.to_offset(&content)
}
+
+ fn to_point(&self, content: &Snapshot) -> Range<Point> {
+ self.start.summary::<Point>(&content)..self.end.summary::<Point>(&content)
+ }
}
@@ -1136,11 +1136,9 @@ impl Buffer {
}
fn can_resolve(&self, anchor: &Anchor) -> bool {
- match anchor {
- Anchor::Min => true,
- Anchor::Insertion { timestamp, .. } => self.version.observed(*timestamp),
- Anchor::Max => true,
- }
+ *anchor == Anchor::min()
+ || *anchor == Anchor::max()
+ || self.version.observed(anchor.timestamp)
}
pub fn peek_undo_stack(&self) -> Option<&Transaction> {
@@ -1680,80 +1678,74 @@ impl Snapshot {
where
D: TextDimension<'a>,
{
- match anchor {
- Anchor::Min => D::default(),
- Anchor::Insertion {
- timestamp,
- offset,
- bias,
- } => {
- let anchor_key = InsertionFragmentKey {
- timestamp: *timestamp,
- split_offset: *offset,
- };
- let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
- insertion_cursor.seek(&anchor_key, *bias, &());
- if let Some(insertion) = insertion_cursor.item() {
- let comparison = sum_tree::KeyedItem::key(insertion).cmp(&anchor_key);
- if comparison == Ordering::Greater
- || (*bias == Bias::Left && comparison == Ordering::Equal && *offset > 0)
- {
- insertion_cursor.prev(&());
- }
- } else {
+ if *anchor == Anchor::min() {
+ D::default()
+ } else if *anchor == Anchor::max() {
+ D::from_text_summary(&self.visible_text.summary())
+ } else {
+ let anchor_key = InsertionFragmentKey {
+ timestamp: anchor.timestamp,
+ split_offset: anchor.offset,
+ };
+ let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
+ 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(&());
}
- let insertion = insertion_cursor.item().expect("invalid insertion");
- debug_assert_eq!(insertion.timestamp, *timestamp, "invalid insertion");
+ } else {
+ insertion_cursor.prev(&());
+ }
+ 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 fragment = fragment_cursor.item().unwrap();
- let mut fragment_offset = fragment_cursor.start().1;
- if fragment.visible {
- fragment_offset += *offset - insertion.split_offset;
- }
- self.text_summary_for_range(0..fragment_offset)
+ let mut fragment_cursor = self.fragments.cursor::<(Locator, usize)>();
+ fragment_cursor.seek(&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;
}
- Anchor::Max => D::from_text_summary(&self.visible_text.summary()),
+ self.text_summary_for_range(0..fragment_offset)
}
}
fn full_offset_for_anchor(&self, anchor: &Anchor) -> FullOffset {
- match anchor {
- Anchor::Min => Default::default(),
- Anchor::Insertion {
- timestamp,
- offset,
- bias,
- } => {
- let anchor_key = InsertionFragmentKey {
- timestamp: *timestamp,
- split_offset: *offset,
- };
- let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
- insertion_cursor.seek(&anchor_key, *bias, &());
- if let Some(insertion) = insertion_cursor.item() {
- let comparison = sum_tree::KeyedItem::key(insertion).cmp(&anchor_key);
- if comparison == Ordering::Greater
- || (*bias == Bias::Left && comparison == Ordering::Equal && *offset > 0)
- {
- insertion_cursor.prev(&());
- }
- } else {
+ if *anchor == Anchor::min() {
+ Default::default()
+ } else if *anchor == Anchor::max() {
+ let text = self.fragments.summary().text;
+ FullOffset(text.visible + text.deleted)
+ } else {
+ let anchor_key = InsertionFragmentKey {
+ timestamp: anchor.timestamp,
+ split_offset: anchor.offset,
+ };
+ let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
+ 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(&());
}
- let insertion = insertion_cursor.item().expect("invalid insertion");
- debug_assert_eq!(insertion.timestamp, *timestamp, "invalid insertion");
-
- let mut fragment_cursor = self.fragments.cursor::<(Locator, FullOffset)>();
- fragment_cursor.seek(&insertion.fragment_id, Bias::Left, &None);
- fragment_cursor.start().1 + (*offset - insertion.split_offset)
- }
- Anchor::Max => {
- let text = self.fragments.summary().text;
- FullOffset(text.visible + text.deleted)
+ } else {
+ insertion_cursor.prev(&());
}
+ 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);
+ fragment_cursor.start().1 + (anchor.offset - insertion.split_offset)
}
}
@@ -1777,15 +1769,15 @@ impl Snapshot {
pub fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
let offset = position.to_offset(self);
if bias == Bias::Left && offset == 0 {
- Anchor::Min
+ Anchor::min()
} else if bias == Bias::Right && offset == self.len() {
- Anchor::Max
+ Anchor::max()
} else {
let mut fragment_cursor = self.fragments.cursor::<(usize, Locator)>();
fragment_cursor.seek(&offset, bias, &None);
let fragment = fragment_cursor.item().unwrap();
let overshoot = offset - fragment_cursor.start().0;
- Anchor::Insertion {
+ Anchor {
timestamp: fragment.insertion_timestamp.local(),
offset: fragment.insertion_offset + overshoot,
bias,