annotated_string/
annotated_range.rs1use itertools::Itertools;
2use std::cell::Cell;
3use std::collections::{btree_map, BTreeMap};
4use std::fmt;
5use std::iter::Peekable;
6use std::ops::Range;
7
8use crate::ApplyAnnotation;
9
10#[derive(PartialEq, Eq, PartialOrd, Ord, Default, Clone)]
11struct MutableOffset(Cell<usize>);
12impl MutableOffset {
13 fn new(value: usize) -> Self {
14 Self(Cell::new(value))
15 }
16 fn set(&self, value: usize) {
17 self.0.set(value)
18 }
19 fn get(&self) -> usize {
20 self.0.get()
21 }
22}
23impl fmt::Debug for MutableOffset {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 fmt::Debug::fmt(&self.0.get(), f)
26 }
27}
28
29#[derive(Debug, Clone)]
30pub struct AnnotatedRange<D> {
31 data: BTreeMap<MutableOffset, D>,
38 len: usize,
39}
40impl<D> Default for AnnotatedRange<D> {
41 fn default() -> Self {
42 Self {
43 data: Default::default(),
44 len: Default::default(),
45 }
46 }
47}
48fn assert_none<T>(v: Option<T>) {
49 debug_assert!(v.is_none());
50}
51impl<D: Clone> AnnotatedRange<D> {
52 pub fn new() -> Self {
53 Self::default()
54 }
55 pub fn with_size(size: usize, data: D) -> Self {
56 if size == 0 {
57 Self::new()
58 } else {
59 Self {
60 data: [(MutableOffset::new(0), data)].into_iter().collect(),
61 len: size,
62 }
63 }
64 }
65 pub fn append(&mut self, size: usize, data: D) {
66 if size == 0 {
67 return;
68 }
69 self.data.insert(MutableOffset::new(self.len), data);
70 self.len += size;
71 }
72 pub fn insert(&mut self, pos: usize, value: Self) {
73 if value.len == 0 {
74 return;
75 }
76 if pos == self.len {
77 self.data.extend(
79 value
80 .data
81 .into_iter()
82 .map(|(k, v)| (MutableOffset::new(k.get() + self.len), v)),
83 );
84 self.len += value.len;
85 return;
86 }
87 assert!(pos < self.len);
88
89 let (prev_meta, prev_pos) = self
90 .data
91 .range(..=MutableOffset::new(pos))
92 .next_back()
93 .map(|(k, v)| (v, k.get()))
94 .expect("element at idx 0 always has associated meta");
95
96 for (key, _) in self.data.range(MutableOffset::new(pos)..).rev() {
98 key.set(key.get() + value.len);
99 }
100
101 if prev_pos < pos {
102 assert_none(
105 self.data
106 .insert(MutableOffset::new(pos + value.len), prev_meta.clone()),
107 );
108 }
109
110 for (off, data) in value.data {
111 assert_none(self.data.insert(MutableOffset::new(pos + off.get()), data));
112 }
113 self.len += value.len;
114 }
115 pub fn remove(&mut self, range: Range<usize>) {
116 let pos = range.start;
117 let size = range.len();
118 if size == 0 {
119 return;
120 }
121 assert!(pos <= self.len - size);
122
123 let mut removed_keys = Vec::new();
124 let mut removed_range = self
125 .data
126 .range(MutableOffset::new(pos)..MutableOffset::new(pos + size));
127 let meta = removed_range.next_back().map(|(key, v)| {
128 removed_keys.push(key.get());
129 v.clone()
131 });
132 for (key, _) in removed_range {
133 removed_keys.push(key.get());
134 }
135 for key in removed_keys {
136 self.data.remove(&MutableOffset::new(key));
137 }
138 for (key, _) in self.data.range(MutableOffset::new(pos)..) {
139 key.set(key.get() - size);
140 }
141 if let Some(meta) = meta {
142 self.data.entry(MutableOffset::new(pos)).or_insert(meta);
144 }
145
146 self.len -= size;
147 }
148 pub fn concat(&mut self, other: Self) {
149 if other.is_empty() {
150 return;
151 }
152 let offset = self.len;
153 self.len += other.len;
154 self.data.extend(other.data.into_iter().map(|(k, v)| {
155 k.set(k.get() + offset);
156 (k, v)
157 }))
158 }
159 pub fn split(mut self, offset: usize) -> (Self, Self) {
160 assert!(offset <= self.len);
161 if offset == 0 {
162 return (Self::new(), self);
163 }
164 if offset == self.len {
165 return (self, Self::new());
166 }
167
168 #[allow(clippy::mutable_key_type, reason = "invariants are held")]
169 let mut other = self.data.split_off(&MutableOffset(Cell::new(offset)));
170
171 let mut split_in_the_middle = true;
173
174 for (i, (pos, _)) in other.iter_mut().enumerate() {
175 pos.set(pos.get() - offset);
176 if i == 0 && pos.get() == 0 {
177 split_in_the_middle = false;
178 }
179 }
180
181 if split_in_the_middle {
182 let mid_data = self
183 .data
184 .range(..MutableOffset::new(offset))
185 .next_back()
186 .expect("not empty");
187 assert_none(other.insert(MutableOffset::new(0), mid_data.1.clone()));
188 }
189
190 let other_len = self.len - offset;
191 self.len = offset;
192 (
193 self,
194 Self {
195 data: other,
196 len: other_len,
197 },
198 )
199 }
200
201 pub fn is_empty(&self) -> bool {
202 self.len == 0
203 }
204 pub fn len(&self) -> usize {
205 self.len
206 }
207 pub fn iter(&self) -> Annotations<'_, D> {
208 Annotations {
209 inner: self.data.iter().peekable(),
210 total_size: self.len,
211 }
212 }
213 pub fn get(&self, pos: usize) -> Option<&D> {
214 self.data
215 .range(..=MutableOffset::new(pos))
216 .next_back()
217 .map(|v| v.1)
218 }
219 fn cut(&mut self, pos: usize) {
221 debug_assert!(pos <= self.len);
222 let mut iter = self.data.range_mut(..=MutableOffset::new(pos));
223 let (item_pos, item_at_pos) = iter.next_back().expect("we always have 0th element");
224 if item_pos.get() == pos {
225 return;
227 }
228 let data = item_at_pos.clone();
229 self.data.insert(MutableOffset::new(pos), data);
230 }
231}
232impl<D: Clone + PartialEq> AnnotatedRange<D> {
233 fn merge_hint(&mut self, pos: usize) {
236 let Some((a, b)) = self
237 .data
238 .range_mut(..=MutableOffset::new(pos))
239 .rev()
240 .next_tuple()
241 else {
242 return;
244 };
245 if a.1 != b.1 {
246 return;
248 }
249 self.data.remove(&MutableOffset::new(pos));
251 }
252}
253
254impl<D: Clone + PartialEq + fmt::Debug> AnnotatedRange<D> {
255 pub fn apply_meta<T>(&mut self, range: Range<usize>, change: &T)
256 where
257 D: ApplyAnnotation<T>,
258 {
259 self.cut(range.start);
260 self.cut(range.end);
261 for (_, meta) in self
262 .data
263 .range_mut(MutableOffset::new(range.start)..MutableOffset::new(range.end))
264 {
265 meta.apply(change);
266 }
267 self.merge_hint(range.start);
268 self.merge_hint(range.end);
269 }
270}
271pub struct Annotations<'a, D> {
272 inner: Peekable<btree_map::Iter<'a, MutableOffset, D>>,
273 total_size: usize,
274}
275impl<'a, D> Iterator for Annotations<'a, D> {
276 type Item = (&'a D, Range<usize>);
277
278 fn next(&mut self) -> Option<Self::Item> {
279 let this = self.inner.next()?;
280 let offset_of_this = this.0.get();
281 let offset_of_next = self
282 .inner
283 .peek()
284 .map(|v| v.0.get())
285 .unwrap_or(self.total_size);
286 Some((this.1, offset_of_this..offset_of_next))
287 }
288}
289
290#[test]
291fn assoc_smoke() {
292 let mut data = <AnnotatedRange<char>>::new();
293 data.insert(0, AnnotatedRange::with_size(3, 'a'));
294 data.insert(2, AnnotatedRange::with_size(1, 'c'));
295 data.insert(0, AnnotatedRange::with_size(3, 'b'));
296 data.remove(1..3);
297}