1use anyhow::{Result, bail};
2use interval_tree::{IntervalTree as Tree, Node, StackIterator};
3
4use crate::{
5 Context,
6 core::{
7 cons::Cons,
8 error::{Type, TypeError},
9 gc::{IntoRoot, Slot, Trace},
10 object::{NIL, Object, ObjectType, TagType, WithLifetime},
11 },
12 fns::eq,
13 textprops::add_properties,
14};
15
16#[derive(Debug)]
17pub struct IntervalTree<'ob> {
18 pub tree: Tree<Slot<Object<'ob>>>,
19}
20
21impl Trace for IntervalTree<'_> {
22 fn trace(&self, state: &mut crate::core::gc::GcState) {
23 self.tree.apply(&mut |x| x.trace(state));
24 }
25}
26
27impl<'new> IntoRoot<IntervalTree<'new>> for IntervalTree<'_> {
28 unsafe fn into_root(self) -> IntervalTree<'new> {
29 self.with_lifetime()
30 }
31}
32
33impl<'new> WithLifetime<'new> for IntervalTree<'_> {
34 type Out = IntervalTree<'new>;
35 unsafe fn with_lifetime(self) -> IntervalTree<'new> {
36 let result: IntervalTree<'new> = std::mem::transmute(self);
37 result
38 }
39}
40
41unsafe impl Send for IntervalTree<'_> {}
42
43impl<'ob> IntervalTree<'ob> {
44 pub fn new() -> Self {
45 IntervalTree { tree: Tree::new() }
46 }
47
48 pub fn insert(&mut self, start: usize, end: usize, val: Slot<Object<'ob>>, cx: &'ob Context) {
53 self.tree
54 .insert((start, end), val, |a, b| {
55 add_properties(*a, *b, crate::textprops::PropertySetType::Append, false, cx)
56 .map(Slot::new)
57 .unwrap()
58 })
59 .unwrap();
60 }
61
62 pub fn set_properties(&mut self, start: usize, end: usize, properties: Object<'ob>) {
63 self.tree.insert((start, end), Slot::new(properties), |a, _b| a).unwrap();
64 }
65
66 pub fn find(&self, position: usize) -> Option<&Node<Slot<Object<'ob>>>> {
67 self.tree.find(position)
68 }
69
70 pub fn delete(&mut self, start: usize, end: usize, list_of_props: Object<'ob>) -> Result<()> {
82 let props = list_of_props.as_list()?;
83 self.tree.apply_with_split(
84 |val| {
85 let props = props.clone();
86 let mut result = *val;
87 for sym in props {
88 let sym = sym.ok()?;
89 result = remove_sym_from_props(sym, result).ok()?;
90 }
91 Some(unsafe { result.into_root() })
92 },
93 start..end,
94 );
95 Ok(())
96 }
97
98 pub fn clean(&mut self) {
99 self.tree.clean(|a, b| eq(**a, **b), |n| n.is_nil());
100 }
101
102 pub(crate) fn iter<'a>(&'a self, start: usize, end: usize) -> IntervalIntersections<'ob, 'a> {
103 IntervalIntersections::new(self, start, end)
104 }
105
106 pub(crate) fn iter_reverse<'a>(
107 &'a self,
108 start: usize,
109 end: usize,
110 ) -> ReverseIntervalIntersections<'ob, 'a> {
111 ReverseIntervalIntersections::new(self, start, end)
112 }
113}
114
115fn remove_sym_from_props<'ob>(sym: Object<'ob>, props: Object<'ob>) -> Result<Object<'ob>> {
128 let ObjectType::Cons(props) = props.untag() else {
129 bail!(TypeError::new(Type::List, props))
130 };
131
132 let mut plist = Some(props);
135 while let Some(cons) = plist {
136 let prop = cons.car();
137 if eq(prop, sym) {
138 plist = cons.cddr().and_then(|n| n.try_into().ok());
139 } else {
141 break;
142 }
143 }
144
145 let result = plist.map(|c| ObjectType::Cons(c).tag()).unwrap_or(NIL);
146
147 while let Some(cons) = plist {
149 println!("{cons:?}");
150 let cdr = cons.cdr();
151 if let ObjectType::Cons(cdr) = cdr.untag() {
152 let cddr = cdr.cdr();
154 if let ObjectType::Cons(this) = cddr.untag() {
155 if eq(this.car(), sym) {
159 set_cdr(cdr, this.cdr());
160 }
161 plist = Some(this);
162 } else {
163 break;
165 }
166 }
167 }
168
169 Ok(result)
170}
171
172fn set_cdr<'ob>(this: &'ob Cons, other: Object<'ob>) -> Option<&'ob Cons> {
173 if let ObjectType::Cons(cons) = other.untag() {
174 if let ObjectType::Cons(_c) = cons.cdr().untag() {
175 this.set_cdr(cons.cdr()).ok()?;
176 }
177 return Some(cons);
178 }
179 None
180}
181
182pub(crate) fn textget<'ob>(plist: Object<'ob>, prop: Object<'ob>) -> Result<Object<'ob>> {
187 lookup_char_property(plist, prop, true)
188}
189
190fn lookup_char_property<'ob>(
192 mut plist: Object<'ob>,
193 prop: Object<'ob>,
194 _is_textprop: bool,
195) -> Result<Object<'ob>> {
196 if plist.is_nil() {
197 return Ok(NIL);
199 }
200 let ObjectType::Cons(_cons) = plist.untag() else {
201 bail!(TypeError::new(Type::Cons, plist))
202 };
203
204 while let ObjectType::Cons(cons) = plist.untag() {
205 let p = cons.car();
206 let val = cons.cadr().ok_or(anyhow::anyhow!(TypeError::new(Type::Cons, prop)))?;
207 if eq(prop, p) {
208 return Ok(val);
209 }
210 match cons.cddr() {
211 Some(obj) => plist = obj,
212 None => break,
213 }
214 }
215 Ok(NIL)
216}
217
218pub(crate) struct IntervalIntersections<'ob, 'tree> {
221 start: usize,
222 end: usize,
223 current: Option<&'tree Node<Slot<Object<'ob>>>>,
224 iterator: StackIterator<'tree, Slot<Object<'ob>>>,
225 next_start: usize,
226}
227
228impl<'ob, 'tree> IntervalIntersections<'ob, 'tree> {
229 pub(crate) fn new(tree: &'tree IntervalTree<'ob>, start: usize, end: usize) -> Self {
230 let current = tree.tree.find_intersect_min(start..end);
231 let mut iterator = StackIterator::new(&tree.tree, current.map(|n| n.key), false);
232 iterator.next(); let next_start = start;
235 Self { start, end, current, iterator, next_start }
236 }
237}
238
239impl<'ob> Iterator for IntervalIntersections<'ob, '_> {
240 type Item = (std::ops::Range<usize>, Object<'ob>);
241
242 fn next(&mut self) -> Option<Self::Item> {
243 if self.next_start >= self.end {
244 return None;
245 }
246
247 if let Some(node) = self.current {
249 if self.next_start < node.key.start {
250 let gap_end = node.key.start.min(self.end);
251 let result = (self.next_start..gap_end, NIL);
252 self.next_start = gap_end;
253 return Some(result);
254 }
255 }
256
257 if let Some(node) = self.current {
259 let intersect_start = node.key.start.max(self.start);
260 let intersect_end = node.key.end.min(self.end);
261
262 if intersect_start < intersect_end {
263 let result = (intersect_start..intersect_end, *node.val);
264 self.next_start = intersect_end;
265 self.current = self.iterator.next();
266 return Some(result);
267 }
268 }
269
270 if self.next_start < self.end {
272 let result = (self.next_start..self.end, NIL);
273 self.next_start = self.end;
274 return Some(result);
275 }
276
277 None
278 }
279}
280
281pub(crate) struct ReverseIntervalIntersections<'ob, 'tree> {
284 start: usize,
285 end: usize,
286 current: Option<&'tree Node<Slot<Object<'ob>>>>,
287 iterator: StackIterator<'tree, Slot<Object<'ob>>>,
288 next_end: usize,
289}
290
291impl<'ob, 'tree> ReverseIntervalIntersections<'ob, 'tree> {
292 pub(crate) fn new(tree: &'tree IntervalTree<'ob>, start: usize, end: usize) -> Self {
293 let current = tree.tree.find_intersect_max(start..end);
294 let mut iterator = StackIterator::new(&tree.tree, current.map(|n| n.key), true);
295 iterator.next(); let next_end = end;
297 Self { start, end, current, iterator, next_end }
298 }
299}
300
301impl<'ob> Iterator for ReverseIntervalIntersections<'ob, '_> {
302 type Item = (std::ops::Range<usize>, Object<'ob>);
303
304 fn next(&mut self) -> Option<Self::Item> {
305 if self.next_end <= self.start {
306 return None;
307 }
308
309 if let Some(node) = self.current {
311 if self.next_end > node.key.end {
312 let gap_start = node.key.end.max(self.start);
313 let result = (gap_start..self.next_end, NIL);
314 self.next_end = gap_start;
315 return Some(result);
316 }
317 }
318
319 if let Some(node) = self.current {
321 let intersect_start = node.key.start.max(self.start);
322 let intersect_end = node.key.end.min(self.end);
323
324 if intersect_start < intersect_end {
325 let result = (intersect_start..intersect_end, *node.val);
326 self.next_end = intersect_start;
327 self.current = self.iterator.next();
328 return Some(result);
329 }
330 }
331
332 if self.next_end > self.start {
334 let result = (self.start..self.next_end, NIL);
335 self.next_end = self.start;
336 return Some(result);
337 }
338
339 None
340 }
341}
342
343#[cfg(test)]
345mod tests {
346 use rune_core::macros::list;
347
348 use super::*;
349 use crate::{RootSet, intern};
350
351 #[test]
352 fn test_remove_sym_from_props() {
353 let roots = &RootSet::default();
354 let cx = Context::new(roots);
355 let sym = intern("foo", &cx);
356 let props = list![ sym, 1, intern("bar", &cx), 2, sym, 3, intern("baz", &cx), 4; &cx];
357
358 let result = remove_sym_from_props(sym.into(), props).unwrap();
361 let rs = result.to_string();
362 assert_eq!(rs, "(bar 2 baz 4)".to_string());
363 }
364}
365
366#[cfg(test)]
367mod reverse_interval_iterator_tests {
368 use super::*;
369 use crate::{RootSet, intern};
370
371 #[test]
372 fn test_empty_tree() {
373 let tree = IntervalTree::new();
374
375 let mut iter = ReverseIntervalIntersections::new(&tree, 0, 100);
376 assert_eq!(iter.next(), Some((0..100, NIL)));
377 assert_eq!(iter.next(), None);
378 }
379
380 #[test]
381 fn test_single_interval() {
382 let roots = &RootSet::default();
383 let cx = Context::new(roots);
384 let val = intern("test", &cx);
385 let mut tree = IntervalTree::new();
386 tree.insert(10, 20, Slot::new(val.into()), &cx);
387
388 let mut iter = ReverseIntervalIntersections::new(&tree, 0, 30);
389 assert_eq!(iter.next(), Some((20..30, NIL)));
390 assert_eq!(iter.next(), Some((10..20, val.into())));
391 assert_eq!(iter.next(), Some((0..10, NIL)));
392 assert_eq!(iter.next(), None);
393 }
394
395 #[test]
396 fn test_multiple_intervals() {
397 let roots = &RootSet::default();
398 let cx = Context::new(roots);
399 let val1 = intern("test1", &cx);
400 let val2 = intern("test2", &cx);
401 let mut tree = IntervalTree::new();
402 tree.insert(10, 20, Slot::new(val1.into()), &cx);
403 tree.insert(25, 35, Slot::new(val2.into()), &cx);
404
405 let mut iter = ReverseIntervalIntersections::new(&tree, 0, 40);
406 assert_eq!(iter.next(), Some((35..40, NIL)));
407 assert_eq!(iter.next(), Some((25..35, val2.into())));
408 assert_eq!(iter.next(), Some((20..25, NIL)));
409 assert_eq!(iter.next(), Some((10..20, val1.into())));
410 assert_eq!(iter.next(), Some((0..10, NIL)));
411 assert_eq!(iter.next(), None);
412 }
413
414 #[test]
415 fn test_overlapping_intervals() {
416 let roots = &RootSet::default();
417 let cx = Context::new(roots);
418 let val1 = intern("test1", &cx);
419 let val2 = intern("test2", &cx);
420 let mut tree = IntervalTree::new();
421 tree.insert(10, 20, Slot::new(val1.into()), &cx);
422 tree.insert(20, 30, Slot::new(val1.into()), &cx);
423 tree.insert(30, 40, Slot::new(val2.into()), &cx);
424
425 let mut iter = ReverseIntervalIntersections::new(&tree, 0, 50);
426 assert_eq!(iter.next(), Some((40..50, NIL)));
427 assert_eq!(iter.next(), Some((30..40, val2.into())));
428 assert_eq!(iter.next(), Some((20..30, val1.into())));
429 assert_eq!(iter.next(), Some((10..20, val1.into())));
430 assert_eq!(iter.next(), Some((0..10, NIL)));
431 assert_eq!(iter.next(), None);
432 }
433}
434
435#[cfg(test)]
436mod interval_iterator_tests {
437 use super::*;
438 use crate::{RootSet, intern};
439
440 #[test]
441 fn test_empty_tree() {
442 let tree = IntervalTree::new();
443
444 let mut iter = IntervalIntersections::new(&tree, 0, 100);
445 assert_eq!(iter.next(), Some((0..100, NIL)));
446 assert_eq!(iter.next(), None);
447 }
448
449 #[test]
450 fn test_single_interval() {
451 let roots = &RootSet::default();
452 let cx = Context::new(roots);
453 let val = intern("test", &cx);
454 let mut tree = IntervalTree::new();
455 tree.insert(10, 20, Slot::new(val.into()), &cx);
456
457 let mut iter = IntervalIntersections::new(&tree, 0, 30);
458 assert_eq!(iter.next(), Some((0..10, NIL)));
459 assert_eq!(iter.next(), Some((10..20, val.into())));
460 assert_eq!(iter.next(), Some((20..30, NIL)));
461 assert_eq!(iter.next(), None);
462 }
463
464 #[test]
465 fn test_multiple_intervals() {
466 let roots = &RootSet::default();
467 let cx = Context::new(roots);
468 let val1 = intern("test1", &cx);
469 let val2 = intern("test2", &cx);
470 let mut tree = IntervalTree::new();
471 tree.insert(10, 20, Slot::new(val1.into()), &cx);
472 tree.insert(25, 35, Slot::new(val2.into()), &cx);
473
474 let mut iter = IntervalIntersections::new(&tree, 0, 40);
475 assert_eq!(iter.next(), Some((0..10, NIL)));
476 assert_eq!(iter.next(), Some((10..20, val1.into())));
477 assert_eq!(iter.next(), Some((20..25, NIL)));
478 assert_eq!(iter.next(), Some((25..35, val2.into())));
479 assert_eq!(iter.next(), Some((35..40, NIL)));
480 assert_eq!(iter.next(), None);
481 }
482
483 #[test]
484 fn test_overlapping_intervals() {
485 let roots = &RootSet::default();
486 let cx = Context::new(roots);
487 let val1 = intern("test1", &cx);
488 let val2 = intern("test2", &cx);
489 let mut tree = IntervalTree::new();
490 tree.insert(10, 20, Slot::new(val1.into()), &cx);
491 tree.insert(20, 30, Slot::new(val1.into()), &cx);
492 tree.insert(30, 40, Slot::new(val2.into()), &cx);
493 let mut iter = IntervalIntersections::new(&tree, 0, 50);
496 assert_eq!(iter.next(), Some((0..10, NIL)));
497 assert_eq!(iter.next(), Some((10..20, val1.into())));
498 assert_eq!(iter.next(), Some((20..30, val1.into())));
499 assert_eq!(iter.next(), Some((30..40, val2.into())));
500 assert_eq!(iter.next(), Some((40..50, NIL)));
501 assert_eq!(iter.next(), None);
502 }
503}