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(&self, bias: Bias, buffer: &BufferSnapshot) -> Anchor {
46        if bias == Bias::Left {
47            self.bias_left(buffer)
48        } else {
49            self.bias_right(buffer)
50        }
51    }
52
53    pub fn bias_left(&self, buffer: &BufferSnapshot) -> Anchor {
54        if self.bias == Bias::Left {
55            self.clone()
56        } else {
57            buffer.anchor_before(self)
58        }
59    }
60
61    pub fn bias_right(&self, buffer: &BufferSnapshot) -> Anchor {
62        if self.bias == Bias::Right {
63            self.clone()
64        } else {
65            buffer.anchor_after(self)
66        }
67    }
68
69    pub fn summary<'a, D>(&self, content: &'a BufferSnapshot) -> D
70    where
71        D: TextDimension,
72    {
73        content.summary_for_anchor(self)
74    }
75}
76
77pub trait AnchorRangeExt {
78    fn cmp(&self, b: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering>;
79    fn to_offset(&self, content: &BufferSnapshot) -> Range<usize>;
80    fn to_point(&self, content: &BufferSnapshot) -> Range<Point>;
81}
82
83impl AnchorRangeExt for Range<Anchor> {
84    fn cmp(&self, other: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering> {
85        Ok(match self.start.cmp(&other.start, buffer)? {
86            Ordering::Equal => other.end.cmp(&self.end, buffer)?,
87            ord @ _ => ord,
88        })
89    }
90
91    fn to_offset(&self, content: &BufferSnapshot) -> Range<usize> {
92        self.start.to_offset(&content)..self.end.to_offset(&content)
93    }
94
95    fn to_point(&self, content: &BufferSnapshot) -> Range<Point> {
96        self.start.summary::<Point>(&content)..self.end.summary::<Point>(&content)
97    }
98}