anchor.rs

  1use super::{Point, ToOffset};
  2use crate::{rope::TextDimension, BufferSnapshot, PointUtf16, ToPoint, ToPointUtf16};
  3use anyhow::Result;
  4use std::{cmp::Ordering, fmt::Debug, ops::Range};
  5use sum_tree::Bias;
  6
  7#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Default)]
  8pub struct Anchor {
  9    pub timestamp: clock::Local,
 10    pub offset: usize,
 11    pub bias: Bias,
 12    pub buffer_id: Option<u64>,
 13}
 14
 15impl Anchor {
 16    pub const MIN: Self = Self {
 17        timestamp: clock::Local::MIN,
 18        offset: usize::MIN,
 19        bias: Bias::Left,
 20        buffer_id: None,
 21    };
 22
 23    pub const MAX: Self = Self {
 24        timestamp: clock::Local::MAX,
 25        offset: usize::MAX,
 26        bias: Bias::Right,
 27        buffer_id: None,
 28    };
 29
 30    pub fn cmp(&self, other: &Anchor, buffer: &BufferSnapshot) -> Ordering {
 31        let fragment_id_comparison = if self.timestamp == other.timestamp {
 32            Ordering::Equal
 33        } else {
 34            buffer
 35                .fragment_id_for_anchor(self)
 36                .cmp(buffer.fragment_id_for_anchor(other))
 37        };
 38
 39        fragment_id_comparison
 40            .then_with(|| self.offset.cmp(&other.offset))
 41            .then_with(|| self.bias.cmp(&other.bias))
 42    }
 43
 44    pub fn min(&self, other: &Self, buffer: &BufferSnapshot) -> Self {
 45        if self.cmp(other, buffer).is_le() {
 46            *self
 47        } else {
 48            *other
 49        }
 50    }
 51
 52    pub fn max(&self, other: &Self, buffer: &BufferSnapshot) -> Self {
 53        if self.cmp(other, buffer).is_ge() {
 54            *self
 55        } else {
 56            *other
 57        }
 58    }
 59
 60    pub fn bias(&self, bias: Bias, buffer: &BufferSnapshot) -> Anchor {
 61        if bias == Bias::Left {
 62            self.bias_left(buffer)
 63        } else {
 64            self.bias_right(buffer)
 65        }
 66    }
 67
 68    pub fn bias_left(&self, buffer: &BufferSnapshot) -> Anchor {
 69        if self.bias == Bias::Left {
 70            *self
 71        } else {
 72            buffer.anchor_before(self)
 73        }
 74    }
 75
 76    pub fn bias_right(&self, buffer: &BufferSnapshot) -> Anchor {
 77        if self.bias == Bias::Right {
 78            *self
 79        } else {
 80            buffer.anchor_after(self)
 81        }
 82    }
 83
 84    pub fn summary<D>(&self, content: &BufferSnapshot) -> D
 85    where
 86        D: TextDimension,
 87    {
 88        content.summary_for_anchor(self)
 89    }
 90}
 91
 92pub trait OffsetRangeExt {
 93    fn to_offset(&self, snapshot: &BufferSnapshot) -> Range<usize>;
 94    fn to_point(&self, snapshot: &BufferSnapshot) -> Range<Point>;
 95    fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> Range<PointUtf16>;
 96}
 97
 98impl<T> OffsetRangeExt for Range<T>
 99where
100    T: ToOffset,
101{
102    fn to_offset(&self, snapshot: &BufferSnapshot) -> Range<usize> {
103        self.start.to_offset(snapshot)..self.end.to_offset(snapshot)
104    }
105
106    fn to_point(&self, snapshot: &BufferSnapshot) -> Range<Point> {
107        self.start.to_offset(snapshot).to_point(snapshot)
108            ..self.end.to_offset(snapshot).to_point(snapshot)
109    }
110
111    fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> Range<PointUtf16> {
112        self.start.to_offset(snapshot).to_point_utf16(snapshot)
113            ..self.end.to_offset(snapshot).to_point_utf16(snapshot)
114    }
115}
116
117pub trait AnchorRangeExt {
118    fn cmp(&self, b: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering>;
119}
120
121impl AnchorRangeExt for Range<Anchor> {
122    fn cmp(&self, other: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering> {
123        Ok(match self.start.cmp(&other.start, buffer) {
124            Ordering::Equal => other.end.cmp(&self.end, buffer),
125            ord => ord,
126        })
127    }
128}