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
 90impl ToOffset for Anchor {
 91    fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize {
 92        self.summary(snapshot)
 93    }
 94}
 95
 96impl ToOffsetUtf16 for Anchor {
 97    fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
 98        self.summary(snapshot)
 99    }
100}
101
102impl ToPoint for Anchor {
103    fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
104        self.summary(snapshot)
105    }
106}
107
108pub trait AnchorRangeExt {
109    fn cmp(&self, b: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Ordering;
110    fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize>;
111    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point>;
112}
113
114impl AnchorRangeExt for Range<Anchor> {
115    fn cmp(&self, other: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Ordering {
116        match self.start.cmp(&other.start, buffer) {
117            Ordering::Equal => other.end.cmp(&self.end, buffer),
118            ord => ord,
119        }
120    }
121
122    fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize> {
123        self.start.to_offset(content)..self.end.to_offset(content)
124    }
125
126    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point> {
127        self.start.to_point(content)..self.end.to_point(content)
128    }
129}