diff --git a/crates/loro-core/src/container/text/tracker/content_map.rs b/crates/loro-core/src/container/text/tracker/content_map.rs index 709fc795..0ff7e07f 100644 --- a/crates/loro-core/src/container/text/tracker/content_map.rs +++ b/crates/loro-core/src/container/text/tracker/content_map.rs @@ -1,6 +1,6 @@ use std::ops::{Deref, DerefMut}; -use rle::{rle_tree::SafeCursorMut, Rle, RleTree, RleTreeTrait}; +use rle::{rle_tree::SafeCursorMut, RleTree}; use super::y_span::{StatusChange, YSpan, YSpanTreeTrait}; @@ -22,8 +22,8 @@ impl DerefMut for ContentMap { } } -pub(super) fn change_status( - cursor: &mut SafeCursorMut<'_, '_, YSpan, YSpanTreeTrait>, +pub(super) fn change_status<'a, 'b: 'a>( + cursor: &mut SafeCursorMut<'a, 'b, YSpan, YSpanTreeTrait>, change: StatusChange, ) { let value = cursor.as_mut(); diff --git a/crates/rle/src/rle_tree/cursor.rs b/crates/rle/src/rle_tree/cursor.rs index 8e4e6e45..e0c88fb2 100644 --- a/crates/rle/src/rle_tree/cursor.rs +++ b/crates/rle/src/rle_tree/cursor.rs @@ -30,13 +30,14 @@ pub struct SafeCursor<'tree, 'bump, T: Rle, A: RleTreeTrait>( pub(crate) UnsafeCursor<'tree, 'bump, T, A>, ); -pub struct SafeCursorMut<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait>( +#[repr(transparent)] +pub struct SafeCursorMut<'tree, 'bump, T: Rle, A: RleTreeTrait>( pub(crate) UnsafeCursor<'tree, 'bump, T, A>, ); impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait> Clone for SafeCursor<'tree, 'bump, T, A> { fn clone(&self) -> Self { - Self(self.0.clone()) + Self(self.0) } } @@ -152,6 +153,16 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait> SafeCursorMut<'tree, 'bump pub fn as_ref_(&self) -> &'tree T { unsafe { self.0.as_ref() } } + + #[inline] + pub fn leaf(&self) -> &'tree LeafNode<'bump, T, A> { + unsafe { self.0.leaf.as_ref() } + } + + #[inline] + pub fn child_index(&self) -> usize { + self.0.index + } } impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait> SafeCursorMut<'tree, 'bump, T, A> { diff --git a/crates/rle/src/rle_tree/iter.rs b/crates/rle/src/rle_tree/iter.rs index 9bef74c8..0ae834df 100644 --- a/crates/rle/src/rle_tree/iter.rs +++ b/crates/rle/src/rle_tree/iter.rs @@ -1,5 +1,3 @@ -use std::ptr::NonNull; - use crate::Rle; use super::{ @@ -8,7 +6,7 @@ use super::{ SafeCursor, }; -pub struct Iter<'some, 'bump, T: Rle, A: RleTreeTrait> { +pub struct Iter<'some, 'bump: 'some, T: Rle, A: RleTreeTrait> { node: Option<&'some LeafNode<'bump, T, A>>, child_index: usize, end_node: Option<&'some LeafNode<'bump, T, A>>, diff --git a/crates/rle/src/rle_tree/node.rs b/crates/rle/src/rle_tree/node.rs index bdd7b185..da775d14 100644 --- a/crates/rle/src/rle_tree/node.rs +++ b/crates/rle/src/rle_tree/node.rs @@ -64,12 +64,20 @@ impl<'a, T: Rle, A: RleTreeTrait> Node<'a, T, A> { match self { Self::Internal(node) => node .children - .get(0) + .first() .and_then(|child| child.get_first_leaf()), Self::Leaf(node) => Some(node), } } + #[inline] + pub(crate) fn get_last_leaf(&self) -> Option<&LeafNode<'a, T, A>> { + match self { + Self::Internal(node) => node.children.last().and_then(|child| child.get_last_leaf()), + Self::Leaf(node) => Some(node), + } + } + #[inline] fn children_num(&self) -> usize { match self { diff --git a/crates/rle/src/rle_tree/node/internal_impl.rs b/crates/rle/src/rle_tree/node/internal_impl.rs index 2813cc36..2b55348f 100644 --- a/crates/rle/src/rle_tree/node/internal_impl.rs +++ b/crates/rle/src/rle_tree/node/internal_impl.rs @@ -109,9 +109,10 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { from.map_or((0, None), |x| self._delete_start(x)); let (direct_delete_end, to_del_end_offset) = to.map_or((self.children.len(), None), |x| self._delete_end(x)); - let mut result = Ok(()); + let deleted_len = direct_delete_end as isize - direct_delete_start as isize; + let mut insertions = vec![]; { - // handle edge removing + // handle removing at the end point let mut handled = false; if let (Some(del_from), Some(del_to)) = (to_del_start_offset, to_del_end_offset) { if direct_delete_start - 1 == direct_delete_end { @@ -128,12 +129,12 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { depth + 1, notify, ) { - result = self._insert_with_split(direct_delete_end + 1, new); + insertions.push((direct_delete_end + 1, new)); } } Node::Leaf(node) => { if let Err(new) = node.delete(Some(del_from), Some(del_to), notify) { - result = self._insert_with_split(direct_delete_end + 1, new); + insertions.push((direct_delete_end + 1, new)); } } } @@ -152,12 +153,12 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { if let Err(new) = node._delete(Some(del_from), None, visited, depth + 1, notify) { - result = self._insert_with_split(direct_delete_start, new); + insertions.push((direct_delete_start, new)); } } Node::Leaf(node) => { if let Err(new) = node.delete(Some(del_from), None, notify) { - result = self._insert_with_split(direct_delete_start, new) + insertions.push((direct_delete_start, new)); } } } @@ -172,14 +173,12 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { if let Err(new) = node._delete(None, Some(del_to), visited, depth + 1, notify) { - debug_assert!(result.is_ok()); - result = self._insert_with_split(direct_delete_end + 1, new); + insertions.push((direct_delete_end + 1, new)); } } Node::Leaf(node) => { if let Err(new) = node.delete(None, Some(del_to), notify) { - debug_assert!(result.is_ok()); - result = self._insert_with_split(direct_delete_end + 1, new); + insertions.push((direct_delete_end + 1, new)); } } } @@ -187,10 +186,24 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { } } - if direct_delete_start < direct_delete_end { + if deleted_len > 0 { + self.connect_leaf(direct_delete_start, direct_delete_end - 1); self.children.drain(direct_delete_start..direct_delete_end); } + insertions.sort_by_key(|x| -(x.0 as isize)); + let mut result = Ok(()); + for mut insertion in insertions { + if insertion.0 >= direct_delete_end && deleted_len > 0 { + insertion.0 -= deleted_len as usize; + } + + if let Err(data) = self._insert_with_split(insertion.0, insertion.1) { + assert!(result.is_ok()); + result = Err(data); + } + } + A::update_cache_internal(self); if let Err(new) = &mut result { A::update_cache_internal(new.as_internal_mut().unwrap()); @@ -199,6 +212,24 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { result } + /// connect [prev leaf of left] with [next leaf of right] + fn connect_leaf(&mut self, left_index: usize, right_index: usize) { + let prev = self.children[left_index] + .get_first_leaf() + .and_then(|x| x.prev); + let next = self.children[right_index] + .get_last_leaf() + .and_then(|x| x.next); + if let Some(mut prev) = prev { + let prev = unsafe { prev.as_mut() }; + prev.next = next; + } + if let Some(mut next) = next { + let next = unsafe { next.as_mut() }; + next.prev = prev; + } + } + fn _delete_start(&mut self, from: A::Int) -> (usize, Option) { let from = A::find_pos_internal(self, from); if from.pos == Position::Start || from.pos == Position::Before { diff --git a/crates/rle/src/rle_tree/node/leaf_impl.rs b/crates/rle/src/rle_tree/node/leaf_impl.rs index 27309745..8391984e 100644 --- a/crates/rle/src/rle_tree/node/leaf_impl.rs +++ b/crates/rle/src/rle_tree/node/leaf_impl.rs @@ -41,6 +41,9 @@ impl<'bump, T: Rle, A: RleTreeTrait> LeafNode<'bump, T, A> { ans_inner.next = self.next; ans_inner.prev = Some(NonNull::new(self).unwrap()); + if let Some(mut next) = self.next { + unsafe { next.as_mut().prev = Some(NonNull::new_unchecked(ans_inner)) }; + } self.next = Some(NonNull::new(&mut *ans_inner).unwrap()); ans } @@ -94,6 +97,14 @@ impl<'bump, T: Rle, A: RleTreeTrait> LeafNode<'bump, T, A> { pub(crate) fn check(&mut self) { assert!(self.children.len() <= A::MAX_CHILDREN_NUM); A::check_cache_leaf(self); + if let Some(next) = self.next { + let self_ptr = unsafe { next.as_ref().prev.unwrap().as_ptr() }; + assert!(std::ptr::eq(self, self_ptr)); + } + if let Some(prev) = self.prev { + let self_ptr = unsafe { prev.as_ref().next.unwrap().as_ptr() }; + assert!(std::ptr::eq(self, self_ptr)); + } } fn _delete_start(&mut self, from: A::Int) -> (usize, Option) { diff --git a/crates/rle/src/rle_tree/test/notify_test.rs b/crates/rle/src/rle_tree/test/notify_test.rs index b65a437e..228d8615 100644 --- a/crates/rle/src/rle_tree/test/notify_test.rs +++ b/crates/rle/src/rle_tree/test/notify_test.rs @@ -90,6 +90,9 @@ fn test(interactions: &[Interaction]) { let out = out.unwrap(); //println!("vs \nindexMap: {:#?}", &out); assert_eq!(v.as_ref().value, out.start); + let leaf = v.0.leaf.as_ptr() as usize; + let out_ptr = out.value.as_ptr() as usize; + assert_eq!(out_ptr, leaf); } }); @@ -111,8 +114,8 @@ fn test(interactions: &[Interaction]) { prop_compose! { fn gen_interaction()( - _type in 0..1, - from in 0..10000, + _type in 0..2, + from in 0..100, len in 1..10, ) -> Interaction { if _type == 0 { @@ -157,59 +160,12 @@ fn issue_2() { } #[test] -fn issue_3() { +fn issue_4() { test(&[ - Insert { from: 0, len: 7 }, - Insert { from: 0, len: 4 }, - Insert { from: 0, len: 1 }, - Insert { from: 4, len: 2 }, - Insert { from: 0, len: 3 }, - Insert { from: 120, len: 1 }, - Insert { from: 1785, len: 1 }, - Insert { from: 6137, len: 1 }, - Insert { from: 2970, len: 5 }, - Insert { from: 2424, len: 5 }, - Insert { from: 2246, len: 4 }, - Insert { from: 104, len: 1 }, - Insert { from: 447, len: 1 }, - Insert { from: 5394, len: 3 }, - Insert { from: 113, len: 6 }, - Insert { from: 6563, len: 7 }, - Insert { from: 8964, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - Insert { from: 0, len: 1 }, - ]); + Insert { from: 0, len: 5 }, + Insert { from: 12, len: 2 }, + Insert { from: 5, len: 1 }, + ]) } #[cfg(not(no_proptest))] diff --git a/crates/rle/src/rle_tree/test/string_fuzzy.rs b/crates/rle/src/rle_tree/test/string_fuzzy.rs index 555c677a..f5475f12 100644 --- a/crates/rle/src/rle_tree/test/string_fuzzy.rs +++ b/crates/rle/src/rle_tree/test/string_fuzzy.rs @@ -125,7 +125,9 @@ impl Interaction { pub fn test_assert(&self, s: &mut String, tree: &mut RleTree) { self.apply_to_str(s); self.apply_to_tree(tree); + // println!("{:#?}", tree); assert_eq!(&tree.to_string(), s); + // println!("{}", s); } fn apply_to_str(&self, s: &mut String) { @@ -135,8 +137,12 @@ impl Interaction { s.insert_str(insert_at, content.as_str()) } Interaction::Delete { from, len } => { + if s.is_empty() { + return; + } + let from = *from % s.len(); - let mut to = from + (*len % s.len()); + let mut to = from + *len; if to > s.len() { to = s.len(); } @@ -156,8 +162,12 @@ impl Interaction { } Interaction::Delete { from, len } => { tree.with_tree_mut(|tree| { + if tree.len() == 0 { + return; + } + let from = *from % tree.len(); - let mut to = from + (*len % tree.len()); + let mut to = from + *len; if to > tree.len() { to = tree.len(); } @@ -169,6 +179,78 @@ impl Interaction { } } +fn run_test(interactions: Vec) { + let mut s = String::new(); + let mut tree = RleTree::default(); + for interaction in interactions { + interaction.test_assert(&mut s, &mut tree); + tree.with_tree_mut(|tree| { + tree.debug_check(); + }); + } +} + +use Interaction::*; + +#[test] +fn issue_delete() { + run_test(vec![ + Insert { + insert_at: 0, + content: "0000000000000".into(), + }, + Delete { from: 7, len: 1 }, + Insert { + insert_at: 0, + content: "11111111111111111".into(), + }, + Delete { from: 0, len: 1 }, + Insert { + insert_at: 1, + content: "2222222".into(), + }, + Delete { from: 0, len: 3 }, + Delete { from: 0, len: 1 }, + Insert { + insert_at: 0, + content: "333333333".into(), + }, + Insert { + insert_at: 8, + content: "44".into(), + }, + Insert { + insert_at: 0, + content: "55555555555555555555555555555555".into(), + }, + Delete { from: 0, len: 1 }, + Delete { from: 2, len: 4 }, + Delete { from: 3, len: 9 }, + Insert { + insert_at: 0, + content: "6".into(), + }, + Delete { from: 5, len: 6 }, + Delete { from: 4, len: 6 }, + Insert { + insert_at: 9, + content: "7".into(), + }, + Insert { + insert_at: 8, + content: "88".into(), + }, + Insert { + insert_at: 0, + content: "9".into(), + }, + // 96555555388373333334432222111111111111111000000000000 + Delete { from: 6, len: 6 }, + // Expected: 96555573333334432222111111111111111000000000000 + // Out: 965573333334432222111111111111111000000000000 + ]) +} + #[cfg(not(no_proptest))] mod string_prop_test { use super::*; @@ -176,10 +258,10 @@ mod string_prop_test { prop_compose! { fn gen_interaction()( - _type in 0..1, + _type in 0..2, from in 0..10000000, - len in 0..10, - content in "[a-z]*" + len in 1..10, + content in "[a-z]+" ) -> Interaction { if _type == 0 { Interaction::Insert { @@ -200,12 +282,7 @@ mod string_prop_test { fn test_tree_string_op_the_same( interactions in prop::collection::vec(gen_interaction(), 1..100), ) { - let mut s = String::new(); - let mut tree = RleTree::default(); - for interaction in interactions { - interaction.test_assert(&mut s, &mut tree); - tree.with_tree_mut(|tree|tree.debug_check()); - } + run_test(interactions); } }