refactor: simplify cursor code

This commit is contained in:
Zixuan Chen 2022-10-14 19:43:20 +08:00
parent 76269a8ca7
commit aae1b2a322
3 changed files with 33 additions and 216 deletions

View file

@ -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);
}
}

View file

@ -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,

View file

@ -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())
}
}