mirror of
https://github.com/loro-dev/loro.git
synced 2024-11-28 17:41:49 +00:00
fix: fix a few bugs
This commit is contained in:
parent
1f69322bc4
commit
5f6d66368e
9 changed files with 241 additions and 39 deletions
|
@ -105,7 +105,7 @@ impl ContentMap {
|
||||||
};
|
};
|
||||||
|
|
||||||
if prev.is_none() {
|
if prev.is_none() {
|
||||||
let mut prev_cursor = cursor.prev();
|
let mut prev_cursor = cursor.prev_elem_end();
|
||||||
while let Some(prev_inner) = prev_cursor {
|
while let Some(prev_inner) = prev_cursor {
|
||||||
if prev_inner.as_ref().status.is_activated() {
|
if prev_inner.as_ref().status.is_activated() {
|
||||||
let cursor = prev_inner;
|
let cursor = prev_inner;
|
||||||
|
@ -119,12 +119,12 @@ impl ContentMap {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev_cursor = prev_inner.prev();
|
prev_cursor = prev_inner.prev_elem_end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if next.is_none() {
|
if next.is_none() {
|
||||||
let mut next_cursor = cursor.next();
|
let mut next_cursor = cursor.next_elem_start();
|
||||||
while let Some(next_inner) = next_cursor {
|
while let Some(next_inner) = next_cursor {
|
||||||
if next_inner.as_ref().status.is_activated() {
|
if next_inner.as_ref().status.is_activated() {
|
||||||
let mut cursor = next_inner.unwrap();
|
let mut cursor = next_inner.unwrap();
|
||||||
|
@ -136,7 +136,7 @@ impl ContentMap {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
next_cursor = next_inner.next();
|
next_cursor = next_inner.next_elem_start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,15 @@ impl Marker {
|
||||||
debug_assert!(!node.is_deleted());
|
debug_assert!(!node.is_deleted());
|
||||||
let position = node.children().iter().position(|x| x.contain_id(id))?;
|
let position = node.children().iter().position(|x| x.contain_id(id))?;
|
||||||
// SAFETY: we just checked it is valid
|
// SAFETY: we just checked it is valid
|
||||||
Some(unsafe { SafeCursor::new(*ptr, position, 0, rle::rle_tree::Position::Start) })
|
Some(unsafe {
|
||||||
|
SafeCursor::new(
|
||||||
|
*ptr,
|
||||||
|
position,
|
||||||
|
0,
|
||||||
|
rle::rle_tree::Position::Start,
|
||||||
|
self.len(),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Marker::Delete(_) => None,
|
Marker::Delete(_) => None,
|
||||||
}
|
}
|
||||||
|
@ -50,7 +58,7 @@ impl Marker {
|
||||||
debug_assert!(!node.is_deleted());
|
debug_assert!(!node.is_deleted());
|
||||||
let position = node.children().iter().position(|x| x.contain_id(id))?;
|
let position = node.children().iter().position(|x| x.contain_id(id))?;
|
||||||
// SAFETY: we just checked it is valid
|
// SAFETY: we just checked it is valid
|
||||||
Some(unsafe { SafeCursorMut::new(*ptr, position, 0, Position::Start) })
|
Some(unsafe { SafeCursorMut::new(*ptr, position, 0, Position::Start, self.len()) })
|
||||||
}
|
}
|
||||||
Marker::Delete(_) => None,
|
Marker::Delete(_) => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,13 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> RleTreeRaw<'bump, T, A> {
|
||||||
|
|
||||||
// SAFETY: result is valid
|
// SAFETY: result is valid
|
||||||
return Some(unsafe {
|
return Some(unsafe {
|
||||||
SafeCursor::new(leaf.into(), result.child_index, result.offset, result.pos)
|
SafeCursor::new(
|
||||||
|
leaf.into(),
|
||||||
|
result.child_index,
|
||||||
|
result.offset,
|
||||||
|
result.pos,
|
||||||
|
0,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +132,13 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> RleTreeRaw<'bump, T, A> {
|
||||||
|
|
||||||
// SAFETY: result is valid
|
// SAFETY: result is valid
|
||||||
return Some(unsafe {
|
return Some(unsafe {
|
||||||
SafeCursor::new(leaf.into(), result.child_index, result.offset, result.pos)
|
SafeCursor::new(
|
||||||
|
leaf.into(),
|
||||||
|
result.child_index,
|
||||||
|
result.offset,
|
||||||
|
result.pos,
|
||||||
|
0,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,6 +181,7 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> RleTreeRaw<'bump, T, A> {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
Position::Start,
|
Position::Start,
|
||||||
|
0,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub struct UnsafeCursor<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> {
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
pub offset: usize,
|
pub offset: usize,
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
|
pub len: usize,
|
||||||
_phantom: PhantomData<&'tree usize>,
|
_phantom: PhantomData<&'tree usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> Clone for UnsafeCursor<'tree, 'bu
|
||||||
index: self.index,
|
index: self.index,
|
||||||
pos: self.pos,
|
pos: self.pos,
|
||||||
offset: self.offset,
|
offset: self.offset,
|
||||||
|
len: self.len,
|
||||||
_phantom: Default::default(),
|
_phantom: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,12 +54,14 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, 'bump,
|
||||||
index: usize,
|
index: usize,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
|
len: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
leaf,
|
leaf,
|
||||||
index,
|
index,
|
||||||
pos,
|
pos,
|
||||||
offset,
|
offset,
|
||||||
|
len,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,32 +111,93 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, 'bump,
|
||||||
node = node.parent.unwrap().as_mut();
|
node = node.parent.unwrap().as_mut();
|
||||||
result = node.insert_at_pos(old_node_index + 1, new);
|
result = node.insert_at_pos(old_node_index + 1, new);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
A::update_cache_internal(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
while node.parent.is_some() {
|
||||||
|
node = node.parent.unwrap().as_mut();
|
||||||
|
A::update_cache_internal(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// we need to make sure that the cursor is still valid
|
/// we need to make sure that the cursor is still valid
|
||||||
pub unsafe fn next(&self) -> Option<Self> {
|
pub unsafe fn next_elem_start(&self) -> Option<Self> {
|
||||||
let leaf = self.leaf.as_ref();
|
let leaf = self.leaf.as_ref();
|
||||||
if leaf.children.len() > self.index + 1 {
|
if leaf.children.len() > self.index + 1 {
|
||||||
return Some(Self::new(self.leaf, self.index + 1, 0, Position::Start));
|
return Some(Self::new(self.leaf, self.index + 1, 0, Position::Start, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
leaf.next.map(|next| Self::new(next, 0, 0, Position::Start))
|
leaf.next
|
||||||
|
.map(|next| Self::new(next, 0, 0, Position::Start, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// we need to make sure that the cursor is still valid
|
/// we need to make sure that the cursor is still valid
|
||||||
pub unsafe fn prev(&self) -> Option<Self> {
|
pub unsafe fn prev_elem_end(&self) -> Option<Self> {
|
||||||
let leaf = self.leaf.as_ref();
|
let leaf = self.leaf.as_ref();
|
||||||
if self.index > 0 {
|
if self.index > 0 {
|
||||||
return Some(Self::new(self.leaf, self.index - 1, 0, Position::Start));
|
return Some(Self::new(self.leaf, self.index - 1, 0, Position::Start, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
leaf.prev
|
leaf.prev.map(|prev| {
|
||||||
.map(|prev| Self::new(prev, prev.as_ref().children.len() - 1, 0, Position::Start))
|
Self::new(
|
||||||
|
prev,
|
||||||
|
prev.as_ref().children.len() - 1,
|
||||||
|
0,
|
||||||
|
Position::Start,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// move cursor forward
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// self should still be valid pointer
|
||||||
|
unsafe fn shift(mut self, mut shift: usize) -> Option<Self> {
|
||||||
|
if shift == 0 {
|
||||||
|
return Some(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut leaf = self.leaf.as_ref();
|
||||||
|
println!("s");
|
||||||
|
while shift > 0 {
|
||||||
|
let diff = leaf.children[self.index].len() - self.offset;
|
||||||
|
leaf.check();
|
||||||
|
match shift.cmp(&diff) {
|
||||||
|
std::cmp::Ordering::Less => {
|
||||||
|
self.offset += shift;
|
||||||
|
self.pos = Position::Middle;
|
||||||
|
return Some(self);
|
||||||
|
}
|
||||||
|
std::cmp::Ordering::Equal => {
|
||||||
|
self.offset = leaf.children[self.index].len();
|
||||||
|
self.pos = Position::End;
|
||||||
|
return Some(self);
|
||||||
|
}
|
||||||
|
std::cmp::Ordering::Greater => {
|
||||||
|
shift -= diff;
|
||||||
|
if self.index == leaf.children.len() - 1 {
|
||||||
|
leaf = leaf.next()?;
|
||||||
|
self.leaf = leaf.into();
|
||||||
|
self.index = 0;
|
||||||
|
self.offset = 0;
|
||||||
|
self.pos = Position::Start;
|
||||||
|
} else {
|
||||||
|
self.index += 1;
|
||||||
|
self.offset = 0;
|
||||||
|
self.pos = Position::Start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,15 +217,15 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, 'bump, T
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn next(&self) -> Option<Self> {
|
pub fn next_elem_start(&self) -> Option<Self> {
|
||||||
// SAFETY: SafeCursor is a shared reference to the tree
|
// SAFETY: SafeCursor is a shared reference to the tree
|
||||||
unsafe { self.0.next().map(|x| Self(x)) }
|
unsafe { self.0.next_elem_start().map(|x| Self(x)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn prev(&self) -> Option<Self> {
|
pub fn prev_elem_end(&self) -> Option<Self> {
|
||||||
// SAFETY: SafeCursor is a shared reference to the tree
|
// SAFETY: SafeCursor is a shared reference to the tree
|
||||||
unsafe { self.0.prev().map(|x| Self(x)) }
|
unsafe { self.0.prev_elem_end().map(|x| Self(x)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -193,8 +258,9 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, 'bump, T
|
||||||
index: usize,
|
index: usize,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
|
len: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self(UnsafeCursor::new(leaf, index, offset, pos))
|
Self(UnsafeCursor::new(leaf, index, offset, pos, len))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -248,8 +314,9 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
|
||||||
index: usize,
|
index: usize,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
|
len: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self(UnsafeCursor::new(leaf, index, offset, pos))
|
Self(UnsafeCursor::new(leaf, index, offset, pos, len))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -281,17 +348,17 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn next(&self) -> Option<Self> {
|
pub fn next_elem_start(&self) -> Option<Self> {
|
||||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree so we are safe to
|
// SAFETY: SafeCursorMut is a exclusive reference to the tree so we are safe to
|
||||||
// get a reference to the element
|
// get a reference to the element
|
||||||
unsafe { self.0.next().map(|x| Self(x)) }
|
unsafe { self.0.next_elem_start().map(|x| Self(x)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn prev(&self) -> Option<Self> {
|
pub fn prev_elem_end(&self) -> Option<Self> {
|
||||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree so we are safe to
|
// SAFETY: SafeCursorMut is a exclusive reference to the tree so we are safe to
|
||||||
// get a reference to the element
|
// get a reference to the element
|
||||||
unsafe { self.0.prev().map(|x| Self(x)) }
|
unsafe { self.0.prev_elem_end().map(|x| Self(x)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -309,13 +376,28 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
|
||||||
self.0.offset
|
self.0.offset
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_notify<F>(&mut self, value: T, notify: &mut F)
|
/// self should be moved here, because after mutating self should be invalidate
|
||||||
|
pub fn insert_before_notify<F>(mut self, value: T, notify: &mut F)
|
||||||
where
|
where
|
||||||
F: FnMut(&T, *mut LeafNode<'_, T, A>),
|
F: FnMut(&T, *mut LeafNode<'_, T, A>),
|
||||||
{
|
{
|
||||||
// SAFETY: we know the cursor is a valid pointer
|
// SAFETY: we know the cursor is a valid pointer
|
||||||
unsafe { self.0.insert_notify(value, notify) }
|
unsafe { self.0.insert_notify(value, notify) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// self should be moved here, because after mutating self should be invalidate
|
||||||
|
pub fn insert_after_notify<F>(self, value: T, notify: &mut F)
|
||||||
|
where
|
||||||
|
F: FnMut(&T, *mut LeafNode<'_, T, A>),
|
||||||
|
{
|
||||||
|
// SAFETY: we know the cursor is a valid pointer
|
||||||
|
unsafe {
|
||||||
|
self.0
|
||||||
|
.shift(self.0.len)
|
||||||
|
.unwrap()
|
||||||
|
.insert_notify(value, notify)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsMut<T>
|
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsMut<T>
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> IterMut<'tree, 'bump, T, A> {
|
||||||
mut end: Option<SafeCursor<'tree, 'bump, T, A>>,
|
mut end: Option<SafeCursor<'tree, 'bump, T, A>>,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
if start.0.pos == Position::After {
|
if start.0.pos == Position::After {
|
||||||
start = start.next()?
|
start = start.next_elem_start()?
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(end_inner) = end {
|
if let Some(end_inner) = end {
|
||||||
|
@ -45,7 +45,7 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> IterMut<'tree, 'bump, T, A> {
|
||||||
|| end_inner.0.pos == Position::End
|
|| end_inner.0.pos == Position::End
|
||||||
|| end_inner.0.pos == Position::After
|
|| end_inner.0.pos == Position::After
|
||||||
{
|
{
|
||||||
end = end_inner.next();
|
end = end_inner.next_elem_start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> Iter<'tree, 'bump, T, A> {
|
||||||
mut end: Option<SafeCursor<'tree, 'bump, T, A>>,
|
mut end: Option<SafeCursor<'tree, 'bump, T, A>>,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
if start.0.pos == Position::After {
|
if start.0.pos == Position::After {
|
||||||
start = start.next()?
|
start = start.next_elem_start()?
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(end_inner) = end {
|
if let Some(end_inner) = end {
|
||||||
|
@ -83,7 +83,7 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> Iter<'tree, 'bump, T, A> {
|
||||||
|| end_inner.0.pos == Position::End
|
|| end_inner.0.pos == Position::End
|
||||||
|| end_inner.0.pos == Position::After
|
|| end_inner.0.pos == Position::After
|
||||||
{
|
{
|
||||||
end = end_inner.next();
|
end = end_inner.next_elem_start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,13 @@ impl<'rf, 'bump, T: Rle, A: RleTreeTrait<T>> Iterator for Iter<'rf, 'bump, T, A>
|
||||||
self.child_index += 1;
|
self.child_index += 1;
|
||||||
// SAFETY: we just checked that the child exists
|
// SAFETY: we just checked that the child exists
|
||||||
return Some(unsafe {
|
return Some(unsafe {
|
||||||
SafeCursor::new(node.into(), self.child_index - 1, 0, Position::Start)
|
SafeCursor::new(
|
||||||
|
node.into(),
|
||||||
|
self.child_index - 1,
|
||||||
|
0,
|
||||||
|
Position::Start,
|
||||||
|
node.children[self.child_index - 1].len(),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => match node.next() {
|
None => match node.next() {
|
||||||
|
@ -158,12 +164,13 @@ impl<'rf, 'bump, T: Rle, A: RleTreeTrait<T>> Iterator for IterMut<'rf, 'bump, T,
|
||||||
let node_ptr = node as *const _;
|
let node_ptr = node as *const _;
|
||||||
match node.children.get(self.child_index) {
|
match node.children.get(self.child_index) {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
|
let len = node.children()[self.child_index - 1].len();
|
||||||
self.child_index += 1;
|
self.child_index += 1;
|
||||||
let leaf = node.into();
|
let leaf = node.into();
|
||||||
self.node = Some(node);
|
self.node = Some(node);
|
||||||
// SAFETY: we just checked that the child exists
|
// SAFETY: we just checked that the child exists
|
||||||
return Some(unsafe {
|
return Some(unsafe {
|
||||||
SafeCursorMut::new(leaf, self.child_index - 1, 0, Position::Start)
|
SafeCursorMut::new(leaf, self.child_index - 1, 0, Position::Start, len)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => match node.next_mut() {
|
None => match node.next_mut() {
|
||||||
|
|
|
@ -288,6 +288,19 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> Node<'a, T, A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn remove(&mut self) {
|
pub(crate) fn remove(&mut self) {
|
||||||
|
if let Some(leaf) = self.as_leaf_mut() {
|
||||||
|
let next = leaf.next;
|
||||||
|
let prev = leaf.prev;
|
||||||
|
if let Some(mut next) = next {
|
||||||
|
// SAFETY: it is safe here
|
||||||
|
unsafe { next.as_mut() }.prev = prev;
|
||||||
|
}
|
||||||
|
if let Some(mut prev) = prev {
|
||||||
|
// SAFETY: it is safe here
|
||||||
|
unsafe { prev.as_mut() }.next = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let index = self.get_self_index().unwrap();
|
let index = self.get_self_index().unwrap();
|
||||||
let parent = self.parent_mut().unwrap();
|
let parent = self.parent_mut().unwrap();
|
||||||
for _ in parent.children.drain(index..index + 1) {}
|
for _ in parent.children.drain(index..index + 1) {}
|
||||||
|
|
|
@ -54,7 +54,15 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
|
||||||
let result = A::find_pos_leaf(self, pos);
|
let result = A::find_pos_leaf(self, pos);
|
||||||
assert!(result.found);
|
assert!(result.found);
|
||||||
// SAFETY: result.found is true
|
// SAFETY: result.found is true
|
||||||
unsafe { SafeCursor::new(self.into(), result.child_index, result.offset, result.pos) }
|
unsafe {
|
||||||
|
SafeCursor::new(
|
||||||
|
self.into(),
|
||||||
|
result.child_index,
|
||||||
|
result.offset,
|
||||||
|
result.pos,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -62,7 +70,15 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
|
||||||
let result = A::find_pos_leaf(self, pos);
|
let result = A::find_pos_leaf(self, pos);
|
||||||
assert!(result.found);
|
assert!(result.found);
|
||||||
// SAFETY: result.found is true
|
// SAFETY: result.found is true
|
||||||
unsafe { SafeCursorMut::new(self.into(), result.child_index, result.offset, result.pos) }
|
unsafe {
|
||||||
|
SafeCursorMut::new(
|
||||||
|
self.into(),
|
||||||
|
result.child_index,
|
||||||
|
result.offset,
|
||||||
|
result.pos,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_child<F>(
|
pub fn push_child<F>(
|
||||||
|
@ -99,17 +115,22 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check(&mut self) {
|
pub(crate) fn check(&self) {
|
||||||
assert!(self.children.len() <= A::MAX_CHILDREN_NUM);
|
assert!(self.children.len() <= A::MAX_CHILDREN_NUM);
|
||||||
|
assert!(!self.is_deleted());
|
||||||
A::check_cache_leaf(self);
|
A::check_cache_leaf(self);
|
||||||
if let Some(next) = self.next {
|
if let Some(next) = self.next {
|
||||||
// SAFETY: this is only for testing, and next must be a valid pointer
|
// SAFETY: this is only for testing, and next must be a valid pointer
|
||||||
let self_ptr = unsafe { next.as_ref().prev.unwrap().as_ptr() };
|
let self_ptr = unsafe { next.as_ref().prev.unwrap().as_ptr() };
|
||||||
|
// SAFETY: this is only for testing, and next must be a valid pointer
|
||||||
|
assert!(unsafe { !next.as_ref().is_deleted() });
|
||||||
assert!(std::ptr::eq(self, self_ptr));
|
assert!(std::ptr::eq(self, self_ptr));
|
||||||
}
|
}
|
||||||
if let Some(prev) = self.prev {
|
if let Some(prev) = self.prev {
|
||||||
// SAFETY: this is only for testing, and prev must be a valid pointer
|
// SAFETY: this is only for testing, and prev must be a valid pointer
|
||||||
let self_ptr = unsafe { prev.as_ref().next.unwrap().as_ptr() };
|
let self_ptr = unsafe { prev.as_ref().next.unwrap().as_ptr() };
|
||||||
|
// SAFETY: this is only for testing, and next must be a valid pointer
|
||||||
|
assert!(unsafe { !prev.as_ref().is_deleted() });
|
||||||
assert!(std::ptr::eq(self, self_ptr));
|
assert!(std::ptr::eq(self, self_ptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,6 +344,12 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
|
||||||
unsafe { self.prev.map(|p| p.as_ref()) }
|
unsafe { self.prev.map(|p| p.as_ref()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn prev_mut(&mut self) -> Option<&mut Self> {
|
||||||
|
// SAFETY: internal variant ensure prev and next are valid reference
|
||||||
|
unsafe { self.prev.map(|mut p| p.as_mut()) }
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn children(&self) -> &[&'bump mut T] {
|
pub fn children(&self) -> &[&'bump mut T] {
|
||||||
&self.children
|
&self.children
|
||||||
|
|
|
@ -64,8 +64,8 @@ impl Interaction {
|
||||||
};
|
};
|
||||||
_println!("Insert {{from: {}, len: {}}},", from, len);
|
_println!("Insert {{from: {}, len: {}}},", from, len);
|
||||||
if *use_cursor {
|
if *use_cursor {
|
||||||
if let Some(mut cursor) = tree.get_mut(from) {
|
if let Some(cursor) = tree.get_mut(from) {
|
||||||
cursor.insert_notify(value, notify)
|
cursor.insert_before_notify(value, notify)
|
||||||
} else {
|
} else {
|
||||||
tree.insert_notify(from, value, notify);
|
tree.insert_notify(from, value, notify);
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,7 +157,17 @@ impl Interaction {
|
||||||
Interaction::Insert { insert_at, content } => {
|
Interaction::Insert { insert_at, content } => {
|
||||||
tree.with_tree_mut(|tree| {
|
tree.with_tree_mut(|tree| {
|
||||||
let insert_at = *insert_at % (tree.len() + 1);
|
let insert_at = *insert_at % (tree.len() + 1);
|
||||||
tree.insert(insert_at, content.clone().into());
|
if insert_at % 3 == 0 && insert_at > 10 {
|
||||||
|
let mut cursor = tree.get_mut(insert_at - 5).unwrap();
|
||||||
|
cursor.0.len = 5;
|
||||||
|
cursor.insert_after_notify(content.clone().into(), &mut |_a, _| {});
|
||||||
|
} else {
|
||||||
|
tree.node
|
||||||
|
.as_internal_mut()
|
||||||
|
.unwrap()
|
||||||
|
.insert(insert_at, content.clone().into(), &mut |_a, _b| {})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Interaction::Delete { from, len } => {
|
Interaction::Delete { from, len } => {
|
||||||
|
@ -192,6 +202,48 @@ fn run_test(interactions: Vec<Interaction>) {
|
||||||
|
|
||||||
use Interaction::*;
|
use Interaction::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_insert_after() {
|
||||||
|
run_test(vec![
|
||||||
|
Insert {
|
||||||
|
insert_at: 0,
|
||||||
|
content: "aaaaaaaa".to_string(),
|
||||||
|
},
|
||||||
|
Insert {
|
||||||
|
insert_at: 4040,
|
||||||
|
content: "aaaaaaaaaaa".to_string(),
|
||||||
|
},
|
||||||
|
Insert {
|
||||||
|
insert_at: 3209832,
|
||||||
|
content: "b".to_string(),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_delete_0() {
|
||||||
|
run_test(vec![
|
||||||
|
Insert {
|
||||||
|
insert_at: 0,
|
||||||
|
content: "0000".into(),
|
||||||
|
},
|
||||||
|
Insert {
|
||||||
|
insert_at: 2,
|
||||||
|
content: "3333".into(),
|
||||||
|
},
|
||||||
|
// 00333300
|
||||||
|
Insert {
|
||||||
|
insert_at: 4,
|
||||||
|
content: "222".into(),
|
||||||
|
},
|
||||||
|
// insert: 0033[222]3300
|
||||||
|
// 00332223300
|
||||||
|
Delete { from: 1, len: 5 },
|
||||||
|
// delete: 0[03322]23300
|
||||||
|
// 023300
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn issue_delete() {
|
fn issue_delete() {
|
||||||
run_test(vec![
|
run_test(vec![
|
||||||
|
@ -252,7 +304,7 @@ fn issue_delete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(no_proptest))]
|
#[cfg(not(no_proptest))]
|
||||||
mod string_prop_test_0 {
|
mod string_proptest {
|
||||||
use super::*;
|
use super::*;
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue