anchor.rs

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