anchor.rs

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