refactor: find pos result

This commit is contained in:
Zixuan Chen 2022-09-06 22:33:18 +08:00
parent 72599b99d1
commit a9134a9844
4 changed files with 67 additions and 46 deletions

View file

@ -79,13 +79,12 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> RleTreeRaw<'a, T, A> {
loop {
match node {
Node::Internal(internal_node) => {
let (child_index, next, _) = A::find_pos_internal(internal_node, index);
node = internal_node.children[child_index];
index = next;
let result = A::find_pos_internal(internal_node, index);
node = internal_node.children[result.child_index];
index = result.new_search_index;
}
Node::Leaf(leaf) => {
let (child_index, _, _) = A::find_pos_leaf(leaf, index);
return SafeCursor::new(leaf.into(), child_index);
return SafeCursor::new(leaf.into(), A::find_pos_leaf(leaf, index).child_index);
}
}
}

View file

@ -3,7 +3,7 @@ use std::{
fmt::{Debug, Error, Formatter},
};
use crate::rle_tree::tree_trait::Position;
use crate::rle_tree::tree_trait::{FindPosResult, Position};
use super::*;
@ -196,20 +196,20 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
}
fn _delete_start(&mut self, from: A::Int) -> (usize, Option<A::Int>) {
let (index_from, relative_from, pos_from) = A::find_pos_internal(self, from);
if pos_from == Position::Start {
(index_from, None)
let from = A::find_pos_internal(self, from);
if from.pos == Position::Start {
(from.child_index, None)
} else {
(index_from + 1, Some(relative_from))
(from.child_index + 1, Some(from.new_search_index))
}
}
fn _delete_end(&mut self, to: A::Int) -> (usize, Option<A::Int>) {
let (index_to, relative_to, pos_to) = A::find_pos_internal(self, to);
if pos_to == Position::End {
(index_to + 1, None)
let to = A::find_pos_internal(self, to);
if to.pos == Position::End {
(to.child_index + 1, None)
} else {
(index_to, Some(relative_to))
(to.child_index, Some(to.new_search_index))
}
}
@ -275,7 +275,11 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
self.children.push(Node::new_leaf(self.bump, ptr));
}
let (child_index, relative_idx, _) = A::find_pos_internal(self, index);
let FindPosResult {
child_index,
new_search_index: relative_idx,
..
} = A::find_pos_internal(self, index);
let child = &mut self.children[child_index];
let new = match child {
Node::Internal(child) => child.insert(relative_idx, value, notify),

View file

@ -1,4 +1,7 @@
use crate::rle_tree::{cursor::SafeCursorMut, tree_trait::Position};
use crate::rle_tree::{
cursor::SafeCursorMut,
tree_trait::{FindPosResult, Position},
};
use std::fmt::{Debug, Error, Formatter};
use super::*;
@ -44,13 +47,13 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> LeafNode<'a, T, A> {
#[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;
let index = A::find_pos_leaf(self, pos).child_index;
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;
let index = A::find_pos_leaf(self, pos).child_index;
SafeCursorMut::new(self.into(), index)
}
@ -87,20 +90,20 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> LeafNode<'a, T, A> {
}
fn _delete_start(&mut self, from: A::Int) -> (usize, Option<usize>) {
let (index_from, relative_from, pos_from) = A::find_pos_leaf(self, from);
if pos_from == Position::Start {
(index_from, None)
let result = A::find_pos_leaf(self, from);
if result.pos == Position::Start {
(result.child_index, None)
} else {
(index_from + 1, Some(relative_from))
(result.child_index + 1, Some(result.new_search_index))
}
}
fn _delete_end(&mut self, to: A::Int) -> (usize, Option<usize>) {
let (index_to, relative_to, pos_to) = A::find_pos_leaf(self, to);
if pos_to == Position::End {
(index_to + 1, None)
let result = A::find_pos_leaf(self, to);
if result.pos == Position::End {
(result.child_index + 1, None)
} else {
(index_to, Some(relative_to))
(result.child_index, Some(result.new_search_index))
}
}
@ -140,7 +143,11 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> LeafNode<'a, T, A> {
return Ok(());
}
let (mut index, mut offset, _pos) = A::find_pos_leaf(self, raw_index);
let FindPosResult {
child_index: mut index,
new_search_index: mut offset,
..
} = A::find_pos_leaf(self, raw_index);
let prev = {
if offset == 0 && index > 0 {
Some(&mut self.children[index - 1])

View file

@ -14,9 +14,19 @@ pub enum Position {
}
pub struct FindPosResult<I> {
child_index: usize,
new_search_index: I,
pos: Position,
pub child_index: usize,
pub new_search_index: I,
pub pos: Position,
}
impl<I> FindPosResult<I> {
pub(crate) fn new(child_index: usize, new_search_index: I, pos: Position) -> Self {
FindPosResult {
child_index,
new_search_index,
pos,
}
}
}
pub trait RleTreeTrait<T: Rle>: Sized + Debug {
@ -36,14 +46,14 @@ pub trait RleTreeTrait<T: Rle>: Sized + Debug {
fn find_pos_internal(
node: &InternalNode<'_, T, Self>,
index: Self::Int,
) -> (usize, Self::Int, Position);
) -> FindPosResult<Self::Int>;
/// returns `(index, offset, pos)`
///
/// if `pos == Middle`, we need to split the node
///
/// - We need the third arg to determine whether the child is included or excluded
fn find_pos_leaf(node: &LeafNode<'_, T, Self>, index: Self::Int) -> (usize, usize, Position);
fn find_pos_leaf(node: &LeafNode<'_, T, Self>, index: Self::Int) -> FindPosResult<usize>;
fn len_leaf(node: &LeafNode<'_, T, Self>) -> Self::Int;
fn len_internal(node: &InternalNode<'_, T, Self>) -> Self::Int;
@ -83,19 +93,19 @@ impl<T: Rle, const MAX_CHILD: usize> RleTreeTrait<T> for CumulateTreeTrait<T, MA
fn find_pos_internal(
node: &InternalNode<'_, T, Self>,
mut index: Self::Int,
) -> (usize, Self::Int, Position) {
) -> FindPosResult<usize> {
let mut last_cache = 0;
for (i, child) in node.children().iter().enumerate() {
last_cache = match child {
Node::Internal(x) => {
if index <= x.cache {
return (i, index, get_pos(index, child.len()));
return FindPosResult::new(i, index, get_pos(index, child.len()));
}
x.cache
}
Node::Leaf(x) => {
if index <= x.cache {
return (i, index, get_pos(index, child.len()));
return FindPosResult::new(i, index, get_pos(index, child.len()));
}
x.cache
}
@ -108,22 +118,19 @@ impl<T: Rle, const MAX_CHILD: usize> RleTreeTrait<T> for CumulateTreeTrait<T, MA
dbg!(&node);
assert_eq!(index, 0);
}
(node.children().len() - 1, last_cache, Position::End)
FindPosResult::new(node.children().len() - 1, last_cache, Position::End)
}
fn find_pos_leaf(
node: &LeafNode<'_, T, Self>,
mut index: Self::Int,
) -> (usize, usize, Position) {
fn find_pos_leaf(node: &LeafNode<'_, T, Self>, mut index: Self::Int) -> FindPosResult<usize> {
for (i, child) in node.children().iter().enumerate() {
if index < HasLength::len(&**child) {
return (i, index, get_pos(index, child.len()));
return FindPosResult::new(i, index, get_pos(index, child.len()));
}
index -= HasLength::len(&**child);
}
(
FindPosResult::new(
node.children().len() - 1,
HasLength::len(&**node.children().last().unwrap()),
Position::End,
@ -226,19 +233,19 @@ impl<T: Rle + HasGlobalIndex, const MAX_CHILD: usize> RleTreeTrait<T>
fn find_pos_internal(
node: &InternalNode<'_, T, Self>,
index: Self::Int,
) -> (usize, Self::Int, Position) {
) -> FindPosResult<Self::Int> {
for (i, child) in node.children().iter().enumerate() {
let cache = get_cache(child);
if index <= cache.end {
assert!(index >= cache.start);
return (i, index, get_pos_global(index, cache));
return FindPosResult::new(i, index, get_pos_global(index, cache));
}
}
unreachable!();
}
fn find_pos_leaf(node: &LeafNode<'_, T, Self>, index: Self::Int) -> (usize, usize, Position) {
fn find_pos_leaf(node: &LeafNode<'_, T, Self>, index: Self::Int) -> FindPosResult<usize> {
for (i, child) in node.children().iter().enumerate() {
let cache = Cache {
start: child.get_global_start(),
@ -246,7 +253,11 @@ impl<T: Rle + HasGlobalIndex, const MAX_CHILD: usize> RleTreeTrait<T>
};
if index <= cache.end {
assert!(index >= cache.start);
return (i, (index - cache.start).as_(), get_pos_global(index, cache));
return FindPosResult::new(
i,
(index - cache.start).as_(),
get_pos_global(index, cache),
);
}
}