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 offsets<'a>(
 91        &'a self,
 92        content: impl Into<Content<'a>> + 'a,
 93    ) -> impl Iterator<Item = (usize, &'a T)> + 'a {
 94        let content = content.into();
 95        content
 96            .summaries_for_anchors(self)
 97            .map(move |(sum, value)| (sum.bytes, value))
 98    }
 99
100    pub fn points<'a>(
101        &'a self,
102        content: impl Into<Content<'a>> + 'a,
103    ) -> impl Iterator<Item = (Point, &'a T)> + 'a {
104        let content = content.into();
105        content
106            .summaries_for_anchors(self)
107            .map(move |(sum, value)| (sum.lines, value))
108    }
109
110    pub fn version(&self) -> &clock::Global {
111        &self.version
112    }
113}
114
115impl AnchorSet {
116    pub fn offsets<'a>(
117        &'a self,
118        content: impl Into<Content<'a>> + 'a,
119    ) -> impl Iterator<Item = usize> + 'a {
120        self.0.offsets(content).map(move |(offset, _)| offset)
121    }
122
123    pub fn points<'a>(
124        &'a self,
125        content: impl Into<Content<'a>> + 'a,
126    ) -> impl Iterator<Item = Point> + 'a {
127        self.0.points(content).map(move |(point, _)| point)
128    }
129}
130
131impl<T> AnchorRangeMap<T> {
132    pub fn from_raw(version: clock::Global, entries: Vec<(Range<(usize, Bias)>, T)>) -> Self {
133        Self { version, entries }
134    }
135
136    pub fn raw_entries(&self) -> &[(Range<(usize, Bias)>, T)] {
137        &self.entries
138    }
139
140    pub fn len(&self) -> usize {
141        self.entries.len()
142    }
143
144    pub fn point_ranges<'a>(
145        &'a self,
146        content: impl Into<Content<'a>> + 'a,
147    ) -> impl Iterator<Item = (Range<Point>, &'a T)> + 'a {
148        let content = content.into();
149        content
150            .summaries_for_anchor_ranges(self)
151            .map(move |(range, value)| ((range.start.lines..range.end.lines), value))
152    }
153
154    pub fn offset_ranges<'a>(
155        &'a self,
156        content: impl Into<Content<'a>> + 'a,
157    ) -> impl Iterator<Item = (Range<usize>, &'a T)> + 'a {
158        let content = content.into();
159        content
160            .summaries_for_anchor_ranges(self)
161            .map(move |(range, value)| ((range.start.bytes..range.end.bytes), value))
162    }
163
164    pub fn version(&self) -> &clock::Global {
165        &self.version
166    }
167}
168
169impl<T: PartialEq> PartialEq for AnchorRangeMap<T> {
170    fn eq(&self, other: &Self) -> bool {
171        self.version == other.version && self.entries == other.entries
172    }
173}
174
175impl<T: Eq> Eq for AnchorRangeMap<T> {}
176
177impl<T: Debug> Debug for AnchorRangeMap<T> {
178    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
179        let mut f = f.debug_map();
180        for (range, value) in &self.entries {
181            f.key(range);
182            f.value(value);
183        }
184        f.finish()
185    }
186}
187
188impl Debug for AnchorRangeSet {
189    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
190        let mut f = f.debug_set();
191        for (range, _) in &self.0.entries {
192            f.entry(range);
193        }
194        f.finish()
195    }
196}
197
198impl AnchorRangeSet {
199    pub fn len(&self) -> usize {
200        self.0.len()
201    }
202
203    pub fn to_offset_ranges<'a>(
204        &'a self,
205        content: impl Into<Content<'a>> + 'a,
206    ) -> impl Iterator<Item = Range<usize>> + 'a {
207        self.0.offset_ranges(content).map(|(range, _)| range)
208    }
209
210    pub fn to_point_ranges<'a>(
211        &'a self,
212        content: impl Into<Content<'a>> + 'a,
213    ) -> impl Iterator<Item = Range<Point>> + 'a {
214        self.0.point_ranges(content).map(|(range, _)| range)
215    }
216
217    pub fn version(&self) -> &clock::Global {
218        self.0.version()
219    }
220}
221
222pub trait AnchorRangeExt {
223    fn cmp<'a>(&self, b: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering>;
224}
225
226impl AnchorRangeExt for Range<Anchor> {
227    fn cmp<'a>(&self, other: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering> {
228        let buffer = buffer.into();
229        Ok(match self.start.cmp(&other.start, &buffer)? {
230            Ordering::Equal => other.end.cmp(&self.end, buffer)?,
231            ord @ _ => ord,
232        })
233    }
234}