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