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