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(&self) -> Bias {
 53        self.text_anchor.bias
 54    }
 55
 56    pub fn bias_left(&self, snapshot: &MultiBufferSnapshot) -> Anchor {
 57        if self.text_anchor.bias != Bias::Left {
 58            if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) {
 59                return Self {
 60                    buffer_id: self.buffer_id,
 61                    excerpt_id: self.excerpt_id.clone(),
 62                    text_anchor: self.text_anchor.bias_left(&excerpt.buffer),
 63                };
 64            }
 65        }
 66        self.clone()
 67    }
 68
 69    pub fn bias_right(&self, snapshot: &MultiBufferSnapshot) -> Anchor {
 70        if self.text_anchor.bias != Bias::Right {
 71            if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) {
 72                return Self {
 73                    buffer_id: self.buffer_id,
 74                    excerpt_id: self.excerpt_id.clone(),
 75                    text_anchor: self.text_anchor.bias_right(&excerpt.buffer),
 76                };
 77            }
 78        }
 79        self.clone()
 80    }
 81
 82    pub fn summary<D>(&self, snapshot: &MultiBufferSnapshot) -> D
 83    where
 84        D: TextDimension + Ord + Sub<D, Output = D>,
 85    {
 86        snapshot.summary_for_anchor(self)
 87    }
 88
 89    pub fn is_valid(&self, snapshot: &MultiBufferSnapshot) -> bool {
 90        if *self == Anchor::min() || *self == Anchor::max() {
 91            true
 92        } else if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) {
 93            excerpt.contains(self)
 94                && (self.text_anchor == excerpt.range.context.start
 95                    || self.text_anchor == excerpt.range.context.end
 96                    || self.text_anchor.is_valid(&excerpt.buffer))
 97        } else {
 98            false
 99        }
100    }
101}
102
103impl ToOffset for Anchor {
104    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize {
105        self.summary(snapshot)
106    }
107}
108
109impl ToOffsetUtf16 for Anchor {
110    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
111        self.summary(snapshot)
112    }
113}
114
115impl ToPoint for Anchor {
116    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
117        self.summary(snapshot)
118    }
119}
120
121pub trait AnchorRangeExt {
122    fn cmp(&self, b: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Ordering;
123    fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize>;
124    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point>;
125}
126
127impl AnchorRangeExt for Range<Anchor> {
128    fn cmp(&self, other: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Ordering {
129        match self.start.cmp(&other.start, buffer) {
130            Ordering::Equal => other.end.cmp(&self.end, buffer),
131            ord => ord,
132        }
133    }
134
135    fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize> {
136        self.start.to_offset(content)..self.end.to_offset(content)
137    }
138
139    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point> {
140        self.start.to_point(content)..self.end.to_point(content)
141    }
142}