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