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 buffer_id: Option<u64>,
 12    pub excerpt_id: ExcerptId,
 13    pub 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 cmp(&self, other: &Anchor, snapshot: &MultiBufferSnapshot) -> Ordering {
 34        let excerpt_id_cmp = self.excerpt_id.cmp(&other.excerpt_id, snapshot);
 35        if excerpt_id_cmp.is_eq() {
 36            if self.excerpt_id == ExcerptId::min() || self.excerpt_id == ExcerptId::max() {
 37                Ordering::Equal
 38            } else if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) {
 39                self.text_anchor.cmp(&other.text_anchor, &excerpt.buffer)
 40            } else {
 41                Ordering::Equal
 42            }
 43        } else {
 44            excerpt_id_cmp
 45        }
 46    }
 47
 48    pub fn bias(&self) -> Bias {
 49        self.text_anchor.bias
 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    pub fn is_valid(&self, snapshot: &MultiBufferSnapshot) -> bool {
 86        if *self == Anchor::min() || *self == Anchor::max() {
 87            true
 88        } else if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) {
 89            excerpt.contains(self)
 90                && (self.text_anchor == excerpt.range.context.start
 91                    || self.text_anchor == excerpt.range.context.end
 92                    || self.text_anchor.is_valid(&excerpt.buffer))
 93        } else {
 94            false
 95        }
 96    }
 97}
 98
 99impl ToOffset for Anchor {
100    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize {
101        self.summary(snapshot)
102    }
103}
104
105impl ToOffsetUtf16 for Anchor {
106    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
107        self.summary(snapshot)
108    }
109}
110
111impl ToPoint for Anchor {
112    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
113        self.summary(snapshot)
114    }
115}
116
117pub trait AnchorRangeExt {
118    fn cmp(&self, b: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Ordering;
119    fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize>;
120    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point>;
121}
122
123impl AnchorRangeExt for Range<Anchor> {
124    fn cmp(&self, other: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Ordering {
125        match self.start.cmp(&other.start, buffer) {
126            Ordering::Equal => other.end.cmp(&self.end, buffer),
127            ord => ord,
128        }
129    }
130
131    fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize> {
132        self.start.to_offset(content)..self.end.to_offset(content)
133    }
134
135    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point> {
136        self.start.to_point(content)..self.end.to_point(content)
137    }
138}