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