anchor.rs

  1use crate::Point;
  2
  3use super::{Buffer, Content};
  4use anyhow::Result;
  5use std::{
  6    cmp::Ordering,
  7    fmt::{Debug, Formatter},
  8    ops::Range,
  9};
 10use sum_tree::Bias;
 11
 12#[derive(Clone, Eq, PartialEq, Debug, Hash)]
 13pub struct Anchor {
 14    pub offset: usize,
 15    pub bias: Bias,
 16    pub version: clock::Global,
 17}
 18
 19#[derive(Clone)]
 20pub struct AnchorMap<T> {
 21    pub(crate) version: clock::Global,
 22    pub(crate) entries: Vec<((usize, Bias), T)>,
 23}
 24
 25#[derive(Clone)]
 26pub struct AnchorSet(pub(crate) AnchorMap<()>);
 27
 28#[derive(Clone)]
 29pub struct AnchorRangeMap<T> {
 30    pub(crate) version: clock::Global,
 31    pub(crate) entries: Vec<(Range<(usize, Bias)>, T)>,
 32}
 33
 34#[derive(Clone)]
 35pub struct AnchorRangeSet(pub(crate) AnchorRangeMap<()>);
 36
 37impl Anchor {
 38    pub fn min() -> Self {
 39        Self {
 40            offset: 0,
 41            bias: Bias::Left,
 42            version: Default::default(),
 43        }
 44    }
 45
 46    pub fn max() -> Self {
 47        Self {
 48            offset: usize::MAX,
 49            bias: Bias::Right,
 50            version: Default::default(),
 51        }
 52    }
 53
 54    pub fn cmp<'a>(&self, other: &Anchor, buffer: impl Into<Content<'a>>) -> Result<Ordering> {
 55        let buffer = buffer.into();
 56
 57        if self == other {
 58            return Ok(Ordering::Equal);
 59        }
 60
 61        let offset_comparison = if self.version == other.version {
 62            self.offset.cmp(&other.offset)
 63        } else {
 64            buffer
 65                .full_offset_for_anchor(self)
 66                .cmp(&buffer.full_offset_for_anchor(other))
 67        };
 68
 69        Ok(offset_comparison.then_with(|| self.bias.cmp(&other.bias)))
 70    }
 71
 72    pub fn bias_left(&self, buffer: &Buffer) -> Anchor {
 73        if self.bias == Bias::Left {
 74            self.clone()
 75        } else {
 76            buffer.anchor_before(self)
 77        }
 78    }
 79
 80    pub fn bias_right(&self, buffer: &Buffer) -> Anchor {
 81        if self.bias == Bias::Right {
 82            self.clone()
 83        } else {
 84            buffer.anchor_after(self)
 85        }
 86    }
 87}
 88
 89impl<T> AnchorMap<T> {
 90    pub fn to_points<'a>(
 91        &'a self,
 92        content: impl Into<Content<'a>> + 'a,
 93    ) -> impl Iterator<Item = (Point, &'a T)> + 'a {
 94        let content = content.into();
 95        content
 96            .summaries_for_anchors(self)
 97            .map(move |(sum, value)| (sum.lines, value))
 98    }
 99
100    pub fn version(&self) -> &clock::Global {
101        &self.version
102    }
103}
104
105impl AnchorSet {
106    pub fn to_points<'a>(
107        &'a self,
108        content: impl Into<Content<'a>> + 'a,
109    ) -> impl Iterator<Item = Point> + 'a {
110        self.0.to_points(content).map(move |(point, _)| point)
111    }
112}
113
114impl<T> AnchorRangeMap<T> {
115    pub fn from_raw(version: clock::Global, entries: Vec<(Range<(usize, Bias)>, T)>) -> Self {
116        Self { version, entries }
117    }
118
119    pub fn raw_entries(&self) -> &[(Range<(usize, Bias)>, T)] {
120        &self.entries
121    }
122
123    pub fn to_point_ranges<'a>(
124        &'a self,
125        content: impl Into<Content<'a>> + 'a,
126    ) -> impl Iterator<Item = (Range<Point>, &'a T)> + 'a {
127        let content = content.into();
128        content
129            .summaries_for_anchor_ranges(self)
130            .map(move |(range, value)| ((range.start.lines..range.end.lines), value))
131    }
132
133    pub fn version(&self) -> &clock::Global {
134        &self.version
135    }
136}
137
138impl<T: PartialEq> PartialEq for AnchorRangeMap<T> {
139    fn eq(&self, other: &Self) -> bool {
140        self.version == other.version && self.entries == other.entries
141    }
142}
143
144impl<T: Eq> Eq for AnchorRangeMap<T> {}
145
146impl<T: Debug> Debug for AnchorRangeMap<T> {
147    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
148        let f = f.debug_map();
149        for (range, value) in &self.entries {
150            f.key(range);
151            f.value(value);
152        }
153        f.finish()
154    }
155}
156
157impl AnchorRangeSet {
158    pub fn to_point_ranges<'a>(
159        &'a self,
160        content: impl Into<Content<'a>> + 'a,
161    ) -> impl Iterator<Item = Range<Point>> + 'a {
162        self.0.to_point_ranges(content).map(|(range, _)| range)
163    }
164
165    pub fn version(&self) -> &clock::Global {
166        self.0.version()
167    }
168}
169
170pub trait AnchorRangeExt {
171    fn cmp<'a>(&self, b: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering>;
172}
173
174impl AnchorRangeExt for Range<Anchor> {
175    fn cmp<'a>(&self, other: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering> {
176        let buffer = buffer.into();
177        Ok(match self.start.cmp(&other.start, &buffer)? {
178            Ordering::Equal => other.end.cmp(&self.end, buffer)?,
179            ord @ _ => ord,
180        })
181    }
182}