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}