annotated_string/
rope.rs

1use std::{
2	cell,
3	cmp::Ordering,
4	fmt,
5	iter::repeat,
6	ops::{Bound, Range, RangeBounds},
7};
8
9use hi_doc_jumprope::{
10	iter::{Chars as RopeChars, ContentIter, SliceIter, Substrings},
11	JumpRope, JumpRopeBuf,
12};
13
14use crate::{AnnotatedRange, ApplyAnnotation};
15
16#[derive(Clone, Debug)]
17pub struct AnnotatedRope<M> {
18	rope: JumpRopeBuf,
19	annotations: AnnotatedRange<M>,
20}
21
22#[ouroboros::self_referencing]
23pub struct Fragments<'r> {
24	rope_buf: cell::Ref<'r, JumpRope>,
25	#[borrows(rope_buf)]
26	#[not_covariant]
27	iter: Substrings<'this, SliceIter<'this>>,
28}
29impl<'f> Iterator for Fragments<'f> {
30	type Item = &'f str;
31
32	fn next(&mut self) -> Option<Self::Item> {
33		let v = self.with_iter_mut(|s| s.next())?;
34
35		// Safety: this str is located in rope_buf, yet it isn't
36		// possible to explain this to jumprope
37		//
38		// This value will live as long as parent ropebuf, because
39		// the iterator itself has a lock on jumprope (Ref), and
40		// the string is borrowed from ouroboros.
41		Some(unsafe {
42			std::str::from_utf8_unchecked(std::slice::from_raw_parts(v.as_ptr(), v.len()))
43		})
44	}
45}
46#[ouroboros::self_referencing]
47pub struct Chars<'r> {
48	rope_buf: cell::Ref<'r, JumpRope>,
49	#[borrows(rope_buf)]
50	#[covariant]
51	iter: RopeChars<'this, ContentIter<'this>>,
52}
53impl Iterator for Chars<'_> {
54	type Item = char;
55
56	fn next(&mut self) -> Option<Self::Item> {
57		self.with_iter_mut(|c| c.next())
58	}
59}
60
61fn bounds_to_exclusive(bounds: impl RangeBounds<usize>, len: usize) -> Range<usize> {
62	let start = match bounds.start_bound() {
63		Bound::Included(v) => *v,
64		Bound::Excluded(_) => unreachable!("not creatable with standard syntax"),
65		Bound::Unbounded => 0,
66	};
67	let end = match bounds.end_bound() {
68		Bound::Included(i) => i + 1,
69		Bound::Excluded(e) => *e,
70		Bound::Unbounded => len,
71	};
72	start..end
73}
74
75impl<M: Clone> AnnotatedRope<M> {
76	pub fn new() -> Self {
77		Self {
78			rope: JumpRopeBuf::new(),
79			annotations: AnnotatedRange::new(),
80		}
81	}
82	pub fn fragment(v: impl AsRef<str>, meta: M) -> Self {
83		let v: String = v.as_ref().to_string();
84		let rope: JumpRopeBuf = v.into();
85		if rope.is_empty() {
86			Self::new()
87		} else {
88			Self {
89				annotations: AnnotatedRange::with_size(rope.len_chars(), meta),
90				rope,
91			}
92		}
93	}
94	pub fn fragment_chars(v: impl IntoIterator<Item = char>, meta: M) -> Self {
95		let v: String = v.into_iter().collect();
96		let rope: JumpRopeBuf = v.into();
97		if rope.is_empty() {
98			Self::new()
99		} else {
100			Self {
101				annotations: AnnotatedRange::with_size(rope.len_chars(), meta),
102				rope,
103			}
104		}
105	}
106	#[deprecated = "use fragment_chars with repeated char"]
107	pub fn repeated_char_fragment(char: char, count: usize, meta: M) -> Self {
108		Self::fragment(char.to_string().repeat(count), meta)
109	}
110	pub fn insert(&mut self, position: usize, buf: Self) {
111		let incoming = buf.rope.borrow();
112		let mut offset = position;
113		for (str, len) in incoming.substrings_with_len() {
114			self.rope.insert(offset, str);
115			offset += len;
116		}
117		self.annotations.insert(position, buf.annotations);
118	}
119	pub fn remove(&mut self, range: impl RangeBounds<usize>) {
120		let range = bounds_to_exclusive(range, self.len());
121		self.rope.remove(range.clone());
122		self.annotations.remove(range);
123	}
124	pub fn splice(&mut self, range: impl RangeBounds<usize>, value: Option<Self>) {
125		let range = bounds_to_exclusive(range, self.len());
126		let start = range.start;
127		self.remove(range);
128		if let Some(value) = value {
129			self.insert(start, value);
130		}
131	}
132	pub fn extend(&mut self, buf: impl IntoIterator<Item = Self>) {
133		for buf in buf {
134			self.insert(self.annotations.len(), buf)
135		}
136	}
137	pub fn append(&mut self, buf: Self) {
138		self.extend([buf]);
139	}
140	pub fn fragments(&self) -> impl IntoIterator<Item = (Fragments<'_>, &'_ M)> {
141		self.annotations.iter().map(|v| {
142			(
143				Fragments::new(self.rope.borrow(), |r| r.slice_substrings(v.1)),
144				v.0,
145			)
146		})
147	}
148	pub fn len(&self) -> usize {
149		self.rope.len_chars()
150	}
151	pub fn is_empty(&self) -> bool {
152		self.rope.is_empty()
153	}
154
155	pub fn get(&self, pos: usize) -> Option<(char, &M)> {
156		self.rope
157			.borrow()
158			.slice_chars(pos..pos + 1)
159			.next()
160			.map(|v| (v, self.annotations.get(pos).expect("meta is broken?")))
161	}
162
163	pub fn chars(&self) -> Chars<'_> {
164		Chars::new(self.rope.borrow(), |v| v.chars())
165	}
166	pub fn resize(&mut self, size: usize, char: char, meta: M) {
167		match size.cmp(&self.len()) {
168			Ordering::Less => self.remove(size..),
169			Ordering::Greater => self.extend([Self::fragment_chars(
170				repeat(char).take(size - self.len()),
171				meta,
172			)]),
173			Ordering::Equal => {}
174		}
175	}
176	pub fn split_at(self, pos: usize) -> (Self, Self) {
177		let rope = self.rope.into_inner();
178		let mut left = rope.clone();
179		left.remove(pos..left.len_chars());
180		let mut right = rope;
181		right.remove(0..pos);
182
183		let meta = self.annotations.clone();
184		let (meta_left, meta_right) = meta.split(pos);
185		(
186			AnnotatedRope {
187				rope: left.into(),
188				annotations: meta_left,
189			},
190			AnnotatedRope {
191				rope: right.into(),
192				annotations: meta_right,
193			},
194		)
195	}
196	pub fn index_of(&self, char: char) -> Option<usize> {
197		self.chars().position(|v| v == char)
198	}
199	pub fn split(&self, char: char) -> Vec<Self> {
200		let mut out = Vec::new();
201		let mut v = self.clone();
202		while let Some(pos) = v.index_of(char) {
203			let (left, right) = v.split_at(pos);
204			out.push(left);
205			v = right;
206		}
207		out.push(v);
208		out
209	}
210}
211impl<M> AnnotatedRope<M> {}
212
213impl<M: Clone + fmt::Debug> Default for AnnotatedRope<M> {
214	fn default() -> Self {
215		Self::new()
216	}
217}
218impl<M: Clone + PartialEq + fmt::Debug> AnnotatedRope<M> {
219	pub fn annotate_range<T>(&mut self, range: impl RangeBounds<usize>, value: &T)
220	where
221		M: ApplyAnnotation<T>,
222	{
223		self.annotations
224			.apply_meta(bounds_to_exclusive(range, self.len()), value)
225	}
226}
227
228impl<M: Clone> FromIterator<AnnotatedRope<M>> for AnnotatedRope<M> {
229	fn from_iter<T: IntoIterator<Item = AnnotatedRope<M>>>(iter: T) -> Self {
230		let mut rope = AnnotatedRope::new();
231		rope.extend(iter);
232		rope
233	}
234}