mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-02 11:06:14 +00:00
feat: cursor mut
This commit is contained in:
parent
f2db2fdcf2
commit
66c50d4a9b
6 changed files with 126 additions and 13 deletions
|
@ -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<YSpan, YSpanTreeTrait>;
|
||||
use super::y_span::{StatusChange, YSpan, YSpanTreeTrait};
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub(super) struct ContentMap(RleTree<YSpan, YSpanTreeTrait>);
|
||||
|
||||
impl Deref for ContentMap {
|
||||
type Target = RleTree<YSpan, YSpanTreeTrait>;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<YSpan, 10>;
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<T>> 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<T>> 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> {
|
||||
|
|
|
@ -11,7 +11,11 @@ pub struct UnsafeCursor<'a, Tree, T: Rle, A: RleTreeTrait<T>> {
|
|||
}
|
||||
|
||||
pub struct SafeCursor<'a, 'b, T: Rle, A: RleTreeTrait<T>>(
|
||||
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<T>>(
|
||||
pub(crate) UnsafeCursor<'a, &'b RleTreeRaw<'a, T, A>, T, A>,
|
||||
);
|
||||
|
||||
impl<'a, Tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'a, Tree, T, A> {
|
||||
|
@ -61,9 +65,41 @@ impl<'a, 'b, T: Rle, A: RleTreeTrait<T>> SafeCursor<'a, 'b, T, A> {
|
|||
pub(crate) fn new(leaf: NonNull<LeafNode<'a, T, A>>, index: usize) -> Self {
|
||||
Self(UnsafeCursor::new(leaf, index))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursorMut<'a, 'b, T, A> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &T {
|
||||
unsafe { self.0.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'a, 'b, T, A> {
|
||||
#[inline]
|
||||
pub(crate) fn new(leaf: NonNull<LeafNode<'a, T, A>>, index: usize) -> Self {
|
||||
Self(UnsafeCursor::new(leaf, index))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: Rle, A: RleTreeTrait<T>> AsMut<T> 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<T>> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<T>> 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();
|
||||
|
|
Loading…
Reference in a new issue