anchor.rs

 1use super::{Point, ToOffset};
 2use crate::{rope::TextDimension, BufferSnapshot};
 3use anyhow::Result;
 4use std::{cmp::Ordering, fmt::Debug, ops::Range};
 5use sum_tree::Bias;
 6
 7#[derive(Clone, Eq, PartialEq, Debug, Hash)]
 8pub struct Anchor {
 9    pub timestamp: clock::Local,
10    pub offset: usize,
11    pub bias: Bias,
12}
13
14impl Anchor {
15    pub fn min() -> Self {
16        Self {
17            timestamp: clock::Local::MIN,
18            offset: usize::MIN,
19            bias: Bias::Left,
20        }
21    }
22
23    pub fn max() -> Self {
24        Self {
25            timestamp: clock::Local::MAX,
26            offset: usize::MAX,
27            bias: Bias::Right,
28        }
29    }
30
31    pub fn cmp(&self, other: &Anchor, buffer: &BufferSnapshot) -> Result<Ordering> {
32        let fragment_id_comparison = if self.timestamp == other.timestamp {
33            Ordering::Equal
34        } else {
35            buffer
36                .fragment_id_for_anchor(self)
37                .cmp(&buffer.fragment_id_for_anchor(other))
38        };
39
40        Ok(fragment_id_comparison
41            .then_with(|| self.offset.cmp(&other.offset))
42            .then_with(|| self.bias.cmp(&other.bias)))
43    }
44
45    pub fn bias_left(&self, buffer: &BufferSnapshot) -> Anchor {
46        if self.bias == Bias::Left {
47            self.clone()
48        } else {
49            buffer.anchor_before(self)
50        }
51    }
52
53    pub fn bias_right(&self, buffer: &BufferSnapshot) -> Anchor {
54        if self.bias == Bias::Right {
55            self.clone()
56        } else {
57            buffer.anchor_after(self)
58        }
59    }
60
61    pub fn summary<'a, D>(&self, content: &'a BufferSnapshot) -> D
62    where
63        D: TextDimension,
64    {
65        content.summary_for_anchor(self)
66    }
67}
68
69pub trait AnchorRangeExt {
70    fn cmp(&self, b: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering>;
71    fn to_offset(&self, content: &BufferSnapshot) -> Range<usize>;
72    fn to_point(&self, content: &BufferSnapshot) -> Range<Point>;
73}
74
75impl AnchorRangeExt for Range<Anchor> {
76    fn cmp(&self, other: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering> {
77        Ok(match self.start.cmp(&other.start, buffer)? {
78            Ordering::Equal => other.end.cmp(&self.end, buffer)?,
79            ord @ _ => ord,
80        })
81    }
82
83    fn to_offset(&self, content: &BufferSnapshot) -> Range<usize> {
84        self.start.to_offset(&content)..self.end.to_offset(&content)
85    }
86
87    fn to_point(&self, content: &BufferSnapshot) -> Range<Point> {
88        self.start.summary::<Point>(&content)..self.end.summary::<Point>(&content)
89    }
90}