From 66c50d4a9b33e61adca26f89e566c0149767a076 Mon Sep 17 00:00:00 2001 From: Zixuan Chen Date: Fri, 2 Sep 2022 18:41:59 +0800 Subject: [PATCH] feat: cursor mut --- .../src/container/text/tracker/content_map.rs | 34 ++++++++++++++-- .../src/container/text/tracker/y_span.rs | 39 ++++++++++++++++++- crates/rle/src/rle_tree.rs | 12 +++--- crates/rle/src/rle_tree/cursor.rs | 38 +++++++++++++++++- crates/rle/src/rle_tree/node.rs | 2 +- crates/rle/src/rle_tree/node/leaf_impl.rs | 14 ++++++- 6 files changed, 126 insertions(+), 13 deletions(-) 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 28a49657..709fc795 100644 --- a/crates/loro-core/src/container/text/tracker/content_map.rs +++ b/crates/loro-core/src/container/text/tracker/content_map.rs @@ -1,5 +1,33 @@ -use rle::RleTree; +use std::ops::{Deref, DerefMut}; -use super::y_span::{YSpan, YSpanTreeTrait}; +use rle::{rle_tree::SafeCursorMut, Rle, RleTree, RleTreeTrait}; -pub(super) type ContentMap = RleTree; +use super::y_span::{StatusChange, YSpan, YSpanTreeTrait}; + +#[repr(transparent)] +#[derive(Debug)] +pub(super) struct ContentMap(RleTree); + +impl Deref for ContentMap { + type Target = RleTree; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for ContentMap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +pub(super) fn change_status( + cursor: &mut SafeCursorMut<'_, '_, YSpan, YSpanTreeTrait>, + change: StatusChange, +) { + let value = cursor.as_mut(); + if value.status.apply(change) { + cursor.update_cache_recursively(); + } +} diff --git a/crates/loro-core/src/container/text/tracker/y_span.rs b/crates/loro-core/src/container/text/tracker/y_span.rs index ee99a773..ceb79bbe 100644 --- a/crates/loro-core/src/container/text/tracker/y_span.rs +++ b/crates/loro-core/src/container/text/tracker/y_span.rs @@ -8,6 +8,29 @@ pub(super) struct Status { undo_times: usize, } +impl Status { + #[inline] + pub fn is_activated(&self) -> bool { + !self.unapplied && self.delete_times == 0 && self.undo_times == 0 + } + + /// Return whether the activation changed + #[inline] + pub fn apply(&mut self, change: StatusChange) -> bool { + let activated = self.is_activated(); + match change { + StatusChange::Apply => self.unapplied = false, + StatusChange::PreApply => self.unapplied = true, + StatusChange::Redo => self.undo_times -= 1, + StatusChange::Undo => self.undo_times += 1, + StatusChange::Delete => self.delete_times += 1, + StatusChange::UndoDelete => self.delete_times -= 1, + } + + self.is_activated() != activated + } +} + #[derive(Debug, Clone)] pub(super) struct YSpan { pub origin_left: ID, @@ -17,6 +40,16 @@ pub(super) struct YSpan { pub status: Status, } +#[derive(Clone, Copy, Debug)] +pub(super) enum StatusChange { + Apply, + PreApply, + Redo, + Undo, + Delete, + UndoDelete, +} + pub(super) type YSpanTreeTrait = CumulateTreeTrait; impl Mergable for YSpan { @@ -71,7 +104,11 @@ impl InsertContent for YSpan { impl HasLength for YSpan { fn len(&self) -> usize { - self.len + if self.status.is_activated() { + self.len + } else { + 0 + } } } diff --git a/crates/rle/src/rle_tree.rs b/crates/rle/src/rle_tree.rs index 12aeaa28..b491e9a8 100644 --- a/crates/rle/src/rle_tree.rs +++ b/crates/rle/src/rle_tree.rs @@ -1,10 +1,8 @@ -use self::{ - cursor::SafeCursor, - node::{InternalNode, Node}, -}; +use self::node::{InternalNode, Node}; use crate::Rle; pub(self) use bumpalo::collections::vec::Vec as BumpVec; use bumpalo::Bump; +pub use cursor::{SafeCursor, SafeCursorMut}; use ouroboros::self_referencing; use std::marker::{PhantomData, PhantomPinned}; use tree_trait::RleTreeTrait; @@ -61,6 +59,7 @@ impl<'a, T: Rle, A: RleTreeTrait> RleTreeRaw<'a, T, A> { } /// return a cursor to the tree + #[inline] pub fn get<'b>(&'b self, mut index: A::Int) -> SafeCursor<'a, 'b, T, A> { let mut node = &self.node; loop { @@ -79,8 +78,9 @@ impl<'a, T: Rle, A: RleTreeTrait> RleTreeRaw<'a, T, A> { } #[inline] - pub fn get_mut<'b>(&'b mut self, index: A::Int) -> SafeCursor<'a, 'b, T, A> { - self.get(index) + pub fn get_mut<'b>(&'b mut self, index: A::Int) -> SafeCursorMut<'a, 'b, T, A> { + let cursor = self.get(index); + SafeCursorMut(cursor.0) } pub fn iter(&self) -> iter::Iter<'_, 'a, T, A> { diff --git a/crates/rle/src/rle_tree/cursor.rs b/crates/rle/src/rle_tree/cursor.rs index 2cbcf169..d097c0e0 100644 --- a/crates/rle/src/rle_tree/cursor.rs +++ b/crates/rle/src/rle_tree/cursor.rs @@ -11,7 +11,11 @@ pub struct UnsafeCursor<'a, Tree, T: Rle, A: RleTreeTrait> { } pub struct SafeCursor<'a, 'b, T: Rle, A: RleTreeTrait>( - UnsafeCursor<'a, &'b RleTreeRaw<'a, T, A>, T, A>, + pub(crate) UnsafeCursor<'a, &'b RleTreeRaw<'a, T, A>, T, A>, +); + +pub struct SafeCursorMut<'a, 'b, T: Rle, A: RleTreeTrait>( + pub(crate) UnsafeCursor<'a, &'b RleTreeRaw<'a, T, A>, T, A>, ); impl<'a, Tree, T: Rle, A: RleTreeTrait> UnsafeCursor<'a, Tree, T, A> { @@ -61,9 +65,41 @@ impl<'a, 'b, T: Rle, A: RleTreeTrait> SafeCursor<'a, 'b, T, A> { pub(crate) fn new(leaf: NonNull>, index: usize) -> Self { Self(UnsafeCursor::new(leaf, index)) } +} +impl<'a, 'b, T: Rle, A: RleTreeTrait> AsRef for SafeCursorMut<'a, 'b, T, A> { + #[inline] + fn as_ref(&self) -> &T { + unsafe { self.0.as_ref() } + } +} + +impl<'a, 'b, T: Rle, A: RleTreeTrait> SafeCursorMut<'a, 'b, T, A> { + #[inline] + pub(crate) fn new(leaf: NonNull>, index: usize) -> Self { + Self(UnsafeCursor::new(leaf, index)) + } +} + +impl<'a, 'b, T: Rle, A: RleTreeTrait> AsMut for SafeCursorMut<'a, 'b, T, A> { #[inline] fn as_mut(&mut self) -> &mut T { unsafe { self.0.as_mut() } } } + +impl<'a, 'b, T: Rle, A: RleTreeTrait> SafeCursorMut<'a, 'b, T, A> { + #[inline] + pub fn update_cache_recursively(&mut self) { + let leaf = unsafe { self.0.leaf.as_mut() }; + A::update_cache_leaf(leaf); + let mut node = unsafe { leaf.parent.as_mut() }; + loop { + A::update_cache_internal(node); + match node.parent { + Some(mut parent) => node = unsafe { parent.as_mut() }, + None => return, + } + } + } +} diff --git a/crates/rle/src/rle_tree/node.rs b/crates/rle/src/rle_tree/node.rs index 080b374a..d8bd422c 100644 --- a/crates/rle/src/rle_tree/node.rs +++ b/crates/rle/src/rle_tree/node.rs @@ -6,7 +6,7 @@ use std::{ use crate::Rle; -use super::{tree_trait::RleTreeTrait, BumpVec}; +use super::{cursor::SafeCursor, tree_trait::RleTreeTrait, BumpVec}; use bumpalo::Bump; use enum_as_inner::EnumAsInner; mod internal_impl; diff --git a/crates/rle/src/rle_tree/node/leaf_impl.rs b/crates/rle/src/rle_tree/node/leaf_impl.rs index 65331690..4629ff52 100644 --- a/crates/rle/src/rle_tree/node/leaf_impl.rs +++ b/crates/rle/src/rle_tree/node/leaf_impl.rs @@ -1,4 +1,4 @@ -use crate::rle_tree::tree_trait::Position; +use crate::rle_tree::{cursor::SafeCursorMut, tree_trait::Position}; use std::fmt::{Debug, Error, Formatter}; use super::*; @@ -37,6 +37,18 @@ impl<'a, T: Rle, A: RleTreeTrait> LeafNode<'a, T, A> { ans } + #[inline] + pub fn get_cursor<'b>(&'b self, pos: A::Int) -> SafeCursor<'a, 'b, T, A> { + let index = A::find_pos_leaf(self, pos).0; + SafeCursor::new(self.into(), index) + } + + #[inline] + pub fn get_cursor_mut<'b>(&'b mut self, pos: A::Int) -> SafeCursorMut<'a, 'b, T, A> { + let index = A::find_pos_leaf(self, pos).0; + SafeCursorMut::new(self.into(), index) + } + pub fn push_child(&mut self, value: T) -> Result<(), &'a mut Node<'a, T, A>> { if !self.children.is_empty() { let last = self.children.last_mut().unwrap();