mirror of
https://github.com/loro-dev/loro.git
synced 2024-11-28 17:41:49 +00:00
refactor: simplify cursor code
This commit is contained in:
parent
76269a8ca7
commit
aae1b2a322
3 changed files with 33 additions and 216 deletions
|
@ -151,98 +151,3 @@ pub(super) fn change_status(
|
|||
cursor.update_cache_recursively();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_get_yspan_at_pos {
|
||||
use crate::{
|
||||
container::text::tracker::y_span::{Status, YSpan},
|
||||
id::ID,
|
||||
};
|
||||
|
||||
use super::ContentMap;
|
||||
|
||||
fn insert(map: &mut ContentMap, id: ID, pos: usize, len: usize) {
|
||||
map.insert(
|
||||
pos,
|
||||
YSpan {
|
||||
id,
|
||||
len,
|
||||
status: Default::default(),
|
||||
origin_left: None,
|
||||
origin_right: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn delete(map: &mut ContentMap, pos: usize, len: usize) {
|
||||
map.0.update_range(
|
||||
pos,
|
||||
Some(pos + len),
|
||||
&mut |v| v.status.delete_times = 1,
|
||||
&mut |_, _| {},
|
||||
)
|
||||
}
|
||||
|
||||
fn insert_deleted(map: &mut ContentMap, id: ID, pos: usize, len: usize) {
|
||||
map.insert(
|
||||
pos,
|
||||
YSpan {
|
||||
id,
|
||||
len,
|
||||
status: Status {
|
||||
delete_times: 1,
|
||||
unapplied: false,
|
||||
undo_times: 0,
|
||||
},
|
||||
origin_left: None,
|
||||
origin_right: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_at_pos(
|
||||
map: &ContentMap,
|
||||
pos: usize,
|
||||
origin_left: Option<ID>,
|
||||
origin_right: Option<ID>,
|
||||
) {
|
||||
let ans = map.get_yspan_at_pos(ID::new(111, 11), pos, 1);
|
||||
assert_eq!(ans.origin_left, origin_left);
|
||||
assert_eq!(ans.origin_right, origin_right);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple() {
|
||||
let mut map = ContentMap::default();
|
||||
insert(&mut map, ID::new(0, 0), 0, 10);
|
||||
assert_at_pos(&map, 0, None, Some(ID::new(0, 0)));
|
||||
assert_at_pos(&map, 10, Some(ID::new(0, 9)), None);
|
||||
assert_at_pos(&map, 3, Some(ID::new(0, 2)), Some(ID::new(0, 3)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complicated() {
|
||||
let mut map = ContentMap::default();
|
||||
insert(&mut map, ID::new(0, 0), 0, 20);
|
||||
delete(&mut map, 10, 10);
|
||||
insert(&mut map, ID::new(1, 0), 10, 10);
|
||||
insert(&mut map, ID::new(2, 0), 20, 10);
|
||||
insert(&mut map, ID::new(3, 0), 30, 10);
|
||||
|
||||
// dbg!(&map);
|
||||
assert_at_pos(&map, 10, Some(ID::new(0, 9)), Some(ID::new(1, 0)));
|
||||
assert_at_pos(&map, 11, Some(ID::new(1, 0)), Some(ID::new(1, 1)));
|
||||
|
||||
assert_at_pos(&map, 20, Some(ID::new(1, 9)), Some(ID::new(2, 0)));
|
||||
assert_at_pos(&map, 21, Some(ID::new(2, 0)), Some(ID::new(2, 1)));
|
||||
delete(&mut map, 20, 1);
|
||||
assert_at_pos(&map, 20, Some(ID::new(1, 9)), Some(ID::new(2, 1)));
|
||||
assert_at_pos(&map, 21, Some(ID::new(2, 1)), Some(ID::new(2, 2)));
|
||||
|
||||
delete(&mut map, 0, 10);
|
||||
assert_at_pos(&map, 0, None, Some(ID::new(0, 0)));
|
||||
assert_at_pos(&map, 29, Some(ID::new(3, 9)), None);
|
||||
delete(&mut map, 0, 28);
|
||||
assert_at_pos(&map, 1, Some(ID::new(3, 9)), None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,7 +158,8 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
|
|||
#[inline]
|
||||
pub fn get_mut(&mut self, index: A::Int) -> Option<SafeCursorMut<'_, T, A>> {
|
||||
let cursor = self.get(index);
|
||||
cursor.map(|x| SafeCursorMut(x.0))
|
||||
// SAFETY: this is safe because we have exclusive ref to the tree
|
||||
cursor.map(|x| unsafe { SafeCursorMut::from(x.0) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -197,7 +198,7 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
|
|||
let start = start.unwrap_or_else(|| {
|
||||
std::mem::transmute(SafeCursor::new(leaf, 0, 0, Position::Start, 0))
|
||||
});
|
||||
let start: SafeCursorMut<'_, T, A> = SafeCursorMut(start.0);
|
||||
let start: SafeCursorMut<'_, T, A> = SafeCursorMut::from(start.0);
|
||||
std::mem::transmute::<_, iter::IterMut<'_, T, A>>(iter::IterMut::from_cursor(
|
||||
std::mem::transmute::<_, SafeCursorMut<'_, T, A>>(start),
|
||||
end,
|
||||
|
|
|
@ -55,18 +55,22 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> Clone for UnsafeCursor<'tree, T, A> {
|
|||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> Copy for UnsafeCursor<'tree, T, A> {}
|
||||
pub struct Im;
|
||||
pub struct Mut;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct SafeCursor<'tree, T: Rle, A: RleTreeTrait<T>>(pub(crate) UnsafeCursor<'tree, T, A>);
|
||||
#[repr(transparent)]
|
||||
pub struct RawSafeCursor<'tree, T: Rle, A: RleTreeTrait<T>, State>(
|
||||
pub(crate) UnsafeCursor<'tree, T, A>,
|
||||
PhantomData<State>,
|
||||
);
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct SafeCursorMut<'tree, T: Rle, A: RleTreeTrait<T>>(pub(crate) UnsafeCursor<'tree, T, A>);
|
||||
pub type SafeCursor<'tree, T, A> = RawSafeCursor<'tree, T, A, Im>;
|
||||
pub type SafeCursorMut<'tree, T, A> = RawSafeCursor<'tree, T, A, Mut>;
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> Clone for SafeCursor<'tree, T, A> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0)
|
||||
Self(self.0, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,20 +110,6 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, T, A> {
|
|||
self.leaf.as_mut().children[self.index]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn update_cache(&mut self) {
|
||||
let leaf = self.leaf.as_mut();
|
||||
A::update_cache_leaf(leaf);
|
||||
let mut node = leaf.parent.as_mut();
|
||||
loop {
|
||||
A::update_cache_internal(node);
|
||||
match node.parent {
|
||||
Some(mut parent) => node = parent.as_mut(),
|
||||
None => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// we need to make sure that the cursor is still valid
|
||||
|
@ -274,7 +264,7 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, T, A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursor<'tree, T, A> {
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>, M> AsRef<T> for RawSafeCursor<'tree, T, A, M> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &'tree T {
|
||||
// SAFETY: SafeCursor is a shared reference to the tree
|
||||
|
@ -282,7 +272,7 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursor<'tree, T, A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, T, A> {
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>, M> RawSafeCursor<'tree, T, A, M> {
|
||||
/// # Safety
|
||||
///
|
||||
/// Users should make sure aht leaf is pointing to a valid LeafNode with 'bump lifetime, and index is inbound
|
||||
|
@ -294,11 +284,14 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, T, A> {
|
|||
pos: Position,
|
||||
len: usize,
|
||||
) -> Self {
|
||||
Self(UnsafeCursor::new(leaf, index, offset, pos, len))
|
||||
Self(
|
||||
UnsafeCursor::new(leaf, index, offset, pos, len),
|
||||
PhantomData,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, T, A> {
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>, M> RawSafeCursor<'tree, T, A, M> {
|
||||
#[inline]
|
||||
pub fn as_tree_ref(&self) -> &'tree T {
|
||||
// SAFETY: SafeCursor is a shared reference to the tree
|
||||
|
@ -308,13 +301,13 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, T, A> {
|
|||
#[inline]
|
||||
pub fn next_elem_start(&self) -> Option<Self> {
|
||||
// SAFETY: SafeCursor is a shared reference to the tree
|
||||
unsafe { self.0.next_elem_start().map(|x| Self(x)) }
|
||||
unsafe { self.0.next_elem_start().map(|x| Self(x, PhantomData)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn prev_elem(&self) -> Option<Self> {
|
||||
// SAFETY: SafeCursor is a shared reference to the tree
|
||||
unsafe { self.0.prev_elem().map(|x| Self(x)) }
|
||||
unsafe { self.0.prev_elem().map(|x| Self(x, PhantomData)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -346,68 +339,29 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, T, A> {
|
|||
#[inline]
|
||||
pub fn shift(self, shift: usize) -> Option<Self> {
|
||||
// SAFETY: SafeCursor is a shared reference to the tree
|
||||
unsafe { Some(Self(self.0.shift(shift)?)) }
|
||||
unsafe { Some(Self(self.0.shift(shift)?, PhantomData)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursorMut<'tree, T, A> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &T {
|
||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree
|
||||
unsafe { self.0.as_ref() }
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>, M> GetOp for RawSafeCursor<'tree, T, A, M> {
|
||||
type Target = T;
|
||||
|
||||
fn get_op(&self) -> Self::Target {
|
||||
self.as_ref()
|
||||
.slice(self.offset(), self.offset() + self.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, T, A> {
|
||||
#[inline]
|
||||
pub fn as_ref_(&self) -> &'tree T {
|
||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree
|
||||
unsafe { self.0.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn leaf(&self) -> &'tree LeafNode<'tree, T, A> {
|
||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree
|
||||
unsafe { self.0.leaf.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn leaf_mut(&mut self) -> &'tree mut LeafNode<'tree, T, A> {
|
||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree
|
||||
unsafe { self.0.leaf.as_mut() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn child_index(&self) -> usize {
|
||||
self.0.index
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> HasLength for SafeCursorMut<'tree, T, A> {
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>, M> HasLength for RawSafeCursor<'tree, T, A, M> {
|
||||
fn len(&self) -> usize {
|
||||
self.0.len
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, T, A> {
|
||||
/// # Safety
|
||||
///
|
||||
/// User must be sure that there is not exclusive reference to the tree and leaf pointer is valid
|
||||
#[inline]
|
||||
pub unsafe fn new(
|
||||
leaf: NonNull<LeafNode<'tree, T, A>>,
|
||||
index: usize,
|
||||
offset: usize,
|
||||
pos: Position,
|
||||
len: usize,
|
||||
) -> Self {
|
||||
Self(UnsafeCursor::new(leaf, index, offset, pos, len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_tree_mut(&mut self) -> &'tree mut T {
|
||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree
|
||||
unsafe { self.0.as_mut() }
|
||||
#[inline(always)]
|
||||
pub unsafe fn from(cursor: UnsafeCursor<'tree, T, A>) -> Self {
|
||||
Self(cursor, PhantomData)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -427,40 +381,6 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, T, A> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn unwrap(self) -> UnsafeCursor<'tree, T, A> {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn next_elem_start(&self) -> Option<Self> {
|
||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree so we are safe to
|
||||
// get a reference to the element
|
||||
unsafe { self.0.next_elem_start().map(|x| Self(x)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn prev_elem(&self) -> Option<Self> {
|
||||
// SAFETY: SafeCursorMut is a exclusive reference to the tree so we are safe to
|
||||
// get a reference to the element
|
||||
unsafe { self.0.prev_elem().map(|x| Self(x)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn index(&self) -> usize {
|
||||
self.0.index
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pos(&self) -> Position {
|
||||
self.0.pos
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn offset(&self) -> usize {
|
||||
self.0.offset
|
||||
}
|
||||
|
||||
/// self should be moved here, because after mutating self should be invalidate
|
||||
pub fn insert_before_notify<F>(self, value: T, notify: &mut F)
|
||||
where
|
||||
|
@ -513,12 +433,3 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> AsMut<T> for SafeCursorMut<'tree, T, A>
|
|||
unsafe { self.0.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree, T: Rle, A: RleTreeTrait<T>> GetOp for SafeCursorMut<'tree, T, A> {
|
||||
type Target = T;
|
||||
|
||||
fn get_op(&self) -> Self::Target {
|
||||
self.as_ref()
|
||||
.slice(self.offset(), self.offset() + self.len())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue