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