anchor.rs

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