feat: cursor mut

This commit is contained in:
Zixuan Chen 2022-09-02 18:41:59 +08:00
parent f2db2fdcf2
commit 66c50d4a9b
6 changed files with 126 additions and 13 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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