anchor.rs

  1use super::{Point, ToOffset};
  2use crate::{rope::TextDimension, BufferSnapshot, PointUtf16, 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 AnchorRangeExt {
 78    fn cmp(&self, b: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering>;
 79    fn to_offset(&self, content: &BufferSnapshot) -> Range<usize>;
 80    fn to_point(&self, content: &BufferSnapshot) -> Range<Point>;
 81    fn to_point_utf16(&self, content: &BufferSnapshot) -> Range<PointUtf16>;
 82}
 83
 84impl AnchorRangeExt for Range<Anchor> {
 85    fn cmp(&self, other: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering> {
 86        Ok(match self.start.cmp(&other.start, buffer)? {
 87            Ordering::Equal => other.end.cmp(&self.end, buffer)?,
 88            ord @ _ => ord,
 89        })
 90    }
 91
 92    fn to_offset(&self, content: &BufferSnapshot) -> Range<usize> {
 93        self.start.to_offset(&content)..self.end.to_offset(&content)
 94    }
 95
 96    fn to_point(&self, content: &BufferSnapshot) -> Range<Point> {
 97        self.start.summary::<Point>(&content)..self.end.summary::<Point>(&content)
 98    }
 99
100    fn to_point_utf16(&self, content: &BufferSnapshot) -> Range<PointUtf16> {
101        self.start.to_point_utf16(content)..self.end.to_point_utf16(content)
102    }
103}