1use crate::Point;
2
3use super::{Buffer, Content};
4use anyhow::Result;
5use std::{
6 cmp::Ordering,
7 fmt::{Debug, Formatter},
8 ops::Range,
9};
10use sum_tree::Bias;
11
12#[derive(Clone, Eq, PartialEq, Debug, Hash)]
13pub struct Anchor {
14 pub offset: usize,
15 pub bias: Bias,
16 pub version: clock::Global,
17}
18
19#[derive(Clone)]
20pub struct AnchorMap<T> {
21 pub(crate) version: clock::Global,
22 pub(crate) entries: Vec<((usize, Bias), T)>,
23}
24
25#[derive(Clone)]
26pub struct AnchorSet(pub(crate) AnchorMap<()>);
27
28#[derive(Clone)]
29pub struct AnchorRangeMap<T> {
30 pub(crate) version: clock::Global,
31 pub(crate) entries: Vec<(Range<(usize, Bias)>, T)>,
32}
33
34#[derive(Clone)]
35pub struct AnchorRangeSet(pub(crate) AnchorRangeMap<()>);
36
37impl Anchor {
38 pub fn min() -> Self {
39 Self {
40 offset: 0,
41 bias: Bias::Left,
42 version: Default::default(),
43 }
44 }
45
46 pub fn max() -> Self {
47 Self {
48 offset: usize::MAX,
49 bias: Bias::Right,
50 version: Default::default(),
51 }
52 }
53
54 pub fn cmp<'a>(&self, other: &Anchor, buffer: impl Into<Content<'a>>) -> Result<Ordering> {
55 let buffer = buffer.into();
56
57 if self == other {
58 return Ok(Ordering::Equal);
59 }
60
61 let offset_comparison = if self.version == other.version {
62 self.offset.cmp(&other.offset)
63 } else {
64 buffer
65 .full_offset_for_anchor(self)
66 .cmp(&buffer.full_offset_for_anchor(other))
67 };
68
69 Ok(offset_comparison.then_with(|| self.bias.cmp(&other.bias)))
70 }
71
72 pub fn bias_left(&self, buffer: &Buffer) -> Anchor {
73 if self.bias == Bias::Left {
74 self.clone()
75 } else {
76 buffer.anchor_before(self)
77 }
78 }
79
80 pub fn bias_right(&self, buffer: &Buffer) -> Anchor {
81 if self.bias == Bias::Right {
82 self.clone()
83 } else {
84 buffer.anchor_after(self)
85 }
86 }
87}
88
89impl<T> AnchorMap<T> {
90 pub fn offsets<'a>(
91 &'a self,
92 content: impl Into<Content<'a>> + 'a,
93 ) -> impl Iterator<Item = (usize, &'a T)> + 'a {
94 let content = content.into();
95 content
96 .summaries_for_anchors(self)
97 .map(move |(sum, value)| (sum.bytes, value))
98 }
99
100 pub fn points<'a>(
101 &'a self,
102 content: impl Into<Content<'a>> + 'a,
103 ) -> impl Iterator<Item = (Point, &'a T)> + 'a {
104 let content = content.into();
105 content
106 .summaries_for_anchors(self)
107 .map(move |(sum, value)| (sum.lines, value))
108 }
109
110 pub fn version(&self) -> &clock::Global {
111 &self.version
112 }
113}
114
115impl AnchorSet {
116 pub fn offsets<'a>(
117 &'a self,
118 content: impl Into<Content<'a>> + 'a,
119 ) -> impl Iterator<Item = usize> + 'a {
120 self.0.offsets(content).map(move |(offset, _)| offset)
121 }
122
123 pub fn points<'a>(
124 &'a self,
125 content: impl Into<Content<'a>> + 'a,
126 ) -> impl Iterator<Item = Point> + 'a {
127 self.0.points(content).map(move |(point, _)| point)
128 }
129}
130
131impl<T> AnchorRangeMap<T> {
132 pub fn from_raw(version: clock::Global, entries: Vec<(Range<(usize, Bias)>, T)>) -> Self {
133 Self { version, entries }
134 }
135
136 pub fn raw_entries(&self) -> &[(Range<(usize, Bias)>, T)] {
137 &self.entries
138 }
139
140 pub fn len(&self) -> usize {
141 self.entries.len()
142 }
143
144 pub fn point_ranges<'a>(
145 &'a self,
146 content: impl Into<Content<'a>> + 'a,
147 ) -> impl Iterator<Item = (Range<Point>, &'a T)> + 'a {
148 let content = content.into();
149 content
150 .summaries_for_anchor_ranges(self)
151 .map(move |(range, value)| ((range.start.lines..range.end.lines), value))
152 }
153
154 pub fn offset_ranges<'a>(
155 &'a self,
156 content: impl Into<Content<'a>> + 'a,
157 ) -> impl Iterator<Item = (Range<usize>, &'a T)> + 'a {
158 let content = content.into();
159 content
160 .summaries_for_anchor_ranges(self)
161 .map(move |(range, value)| ((range.start.bytes..range.end.bytes), value))
162 }
163
164 pub fn version(&self) -> &clock::Global {
165 &self.version
166 }
167}
168
169impl<T: PartialEq> PartialEq for AnchorRangeMap<T> {
170 fn eq(&self, other: &Self) -> bool {
171 self.version == other.version && self.entries == other.entries
172 }
173}
174
175impl<T: Eq> Eq for AnchorRangeMap<T> {}
176
177impl<T: Debug> Debug for AnchorRangeMap<T> {
178 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
179 let mut f = f.debug_map();
180 for (range, value) in &self.entries {
181 f.key(range);
182 f.value(value);
183 }
184 f.finish()
185 }
186}
187
188impl Debug for AnchorRangeSet {
189 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
190 let mut f = f.debug_set();
191 for (range, _) in &self.0.entries {
192 f.entry(range);
193 }
194 f.finish()
195 }
196}
197
198impl AnchorRangeSet {
199 pub fn len(&self) -> usize {
200 self.0.len()
201 }
202
203 pub fn to_offset_ranges<'a>(
204 &'a self,
205 content: impl Into<Content<'a>> + 'a,
206 ) -> impl Iterator<Item = Range<usize>> + 'a {
207 self.0.offset_ranges(content).map(|(range, _)| range)
208 }
209
210 pub fn to_point_ranges<'a>(
211 &'a self,
212 content: impl Into<Content<'a>> + 'a,
213 ) -> impl Iterator<Item = Range<Point>> + 'a {
214 self.0.point_ranges(content).map(|(range, _)| range)
215 }
216
217 pub fn version(&self) -> &clock::Global {
218 self.0.version()
219 }
220}
221
222pub trait AnchorRangeExt {
223 fn cmp<'a>(&self, b: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering>;
224}
225
226impl AnchorRangeExt for Range<Anchor> {
227 fn cmp<'a>(&self, other: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering> {
228 let buffer = buffer.into();
229 Ok(match self.start.cmp(&other.start, &buffer)? {
230 Ordering::Equal => other.end.cmp(&self.end, buffer)?,
231 ord @ _ => ord,
232 })
233 }
234}