annotated_string/
annotated_range.rs

1use 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	// Segment start => Data
32	// As every segment needs to be annotated (Otherwise, use Option<D>),
33	// no need to keep segment sizes here.
34	//
35	// TODO: Might be done without interior mutability, but BTreeMap provides
36	// no mutable access to the keys.
37	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			// Otherwise will fail prev_meta get check on empty buffer.
78			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		// .rev() for prevent self-overriding
97		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			// If not inserting before element, then splitting current meta
103			// at insertion place.
104			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			// TODO: take
130			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			// If there is no range starting right after deleted - insert start of meta from what was deleted.
143			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		// Do we need to clone split element?
172		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	// Make sure there is an element at pos
220	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			// Already split
226			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	// Compare meta at chunks on `(pos..)` and `(..pos-1)`
234	// If it equals - merge those two chunks
235	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			// pos it at first chunk
243			return;
244		};
245		if a.1 != b.1 {
246			// Inequal - do not merge
247			return;
248		}
249		// Expand left chunk automatically
250		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}