1use super::{Point, ToOffset};
2use crate::{rope::TextDimension, BufferSnapshot, PointUtf16, ToPoint, ToPointUtf16};
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 OffsetRangeExt {
78 fn to_offset(&self, snapshot: &BufferSnapshot) -> Range<usize>;
79 fn to_point(&self, snapshot: &BufferSnapshot) -> Range<Point>;
80 fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> Range<PointUtf16>;
81}
82
83impl<T> OffsetRangeExt for Range<T>
84where
85 T: ToOffset,
86{
87 fn to_offset(&self, snapshot: &BufferSnapshot) -> Range<usize> {
88 self.start.to_offset(snapshot)..self.end.to_offset(&snapshot)
89 }
90
91 fn to_point(&self, snapshot: &BufferSnapshot) -> Range<Point> {
92 self.start.to_offset(snapshot).to_point(snapshot)
93 ..self.end.to_offset(snapshot).to_point(snapshot)
94 }
95
96 fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> Range<PointUtf16> {
97 self.start.to_offset(snapshot).to_point_utf16(snapshot)
98 ..self.end.to_offset(snapshot).to_point_utf16(snapshot)
99 }
100}
101
102pub trait AnchorRangeExt {
103 fn cmp(&self, b: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering>;
104}
105
106impl AnchorRangeExt for Range<Anchor> {
107 fn cmp(&self, other: &Range<Anchor>, buffer: &BufferSnapshot) -> Result<Ordering> {
108 Ok(match self.start.cmp(&other.start, buffer)? {
109 Ordering::Equal => other.end.cmp(&self.end, buffer)?,
110 ord @ _ => ord,
111 })
112 }
113}