refactor: use ouroboros to self-ref

previous solution has a fatal bug when dropping
This commit is contained in:
Zixuan Chen 2022-08-12 17:54:47 +08:00
parent c498a3e243
commit 9755782cf9
4 changed files with 117 additions and 115 deletions

View file

@ -9,7 +9,7 @@ edition = "2021"
bumpalo = { version = "3.10.0", features = ["collections", "boxed"] }
num = "0.4.0"
enum-as-inner = "0.5.1"
owning_ref = "0.4.1"
ouroboros = "0.15.2"
[dev-dependencies]
color-backtrace = { version = "0.5" }

View file

@ -2,8 +2,13 @@ use self::node::{InternalNode, Node};
use crate::{HasLength, Rle};
pub(self) use bumpalo::collections::vec::Vec as BumpVec;
use bumpalo::Bump;
use owning_ref::OwningRefMut;
use std::marker::{PhantomData, PhantomPinned};
use ouroboros::self_referencing;
use std::{
borrow::{Borrow, BorrowMut},
marker::{PhantomData, PhantomPinned},
pin::Pin,
ptr::NonNull,
};
use tree_trait::RleTreeTrait;
mod iter;
mod node;
@ -18,34 +23,21 @@ pub struct RleTreeRaw<'a, T: Rle, A: RleTreeTrait<T>> {
_a: PhantomData<(A, T)>,
}
type TreeRef<T, A> =
OwningRefMut<Box<(Box<Bump>, RleTreeRaw<'static, T, A>)>, RleTreeRaw<'static, T, A>>;
#[self_referencing]
pub struct RleTree<T: Rle + 'static, A: RleTreeTrait<T> + 'static> {
tree: TreeRef<T, A>,
}
impl<T: Rle + 'static, A: RleTreeTrait<T> + 'static> RleTree<T, A> {
pub fn new() -> Self {
let bump = Box::new(Bump::new());
let tree = RleTreeRaw::new(unsafe { &*(&*bump as *const _) });
let m = OwningRefMut::new(Box::new((bump, tree)));
let tree = m.map_mut(|(_, tree)| tree);
Self { tree }
}
pub fn get_ref(&self) -> &RleTreeRaw<'static, T, A> {
self.tree.as_ref()
}
pub fn get_mut(&mut self) -> &mut RleTreeRaw<'static, T, A> {
self.tree.as_mut()
}
bump: Bump,
#[borrows(bump)]
#[not_covariant]
tree: RleTreeRaw<'this, T, A>,
}
impl<T: Rle + 'static, A: RleTreeTrait<T> + 'static> Default for RleTree<T, A> {
fn default() -> Self {
Self::new()
RleTreeBuilder {
bump: Bump::new(),
tree_builder: |bump| RleTreeRaw::new(bump),
}
.build()
}
}

View file

@ -103,118 +103,125 @@ fn get_pos<T: HasLength>(index: usize, child: &T) -> Position {
#[test]
fn insert() {
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::new();
let tree = t.get_mut();
tree.insert(0, 0..1);
tree.insert(1, 4..8);
tree.insert(5, 8..10);
tree.insert(3, 101..108);
tree.insert(2, 200..208);
assert_eq!(tree.len(), 22);
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::default();
t.with_tree_mut(|tree| {
tree.insert(0, 0..1);
tree.insert(1, 4..8);
tree.insert(5, 8..10);
tree.insert(3, 101..108);
tree.insert(2, 200..208);
assert_eq!(tree.len(), 22);
let ans = vec![0..1, 4..5, 200..208, 5..6, 101..108, 6..10];
let ans = vec![0..1, 4..5, 200..208, 5..6, 101..108, 6..10];
for (actual, expected) in tree.iter().zip(ans.iter()) {
assert_eq!(actual, expected);
}
for (actual, expected) in tree.iter().zip(ans.iter()) {
assert_eq!(actual, expected);
}
})
}
#[test]
fn delete() {
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::new();
let tree = t.get_mut();
tree.insert(0, 0..10);
tree.delete_range(Some(4), Some(5));
assert_eq!(tree.len(), 9);
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::default();
t.with_tree_mut(|tree| {
tree.insert(0, 0..10);
tree.delete_range(Some(4), Some(5));
assert_eq!(tree.len(), 9);
let ans = vec![0..4, 5..10];
for (actual, expected) in tree.iter().zip(ans.iter()) {
assert_eq!(actual, expected);
}
let ans = vec![0..4, 5..10];
for (actual, expected) in tree.iter().zip(ans.iter()) {
assert_eq!(actual, expected);
}
})
}
#[test]
fn insert_50times() {
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::new();
let tree = t.get_mut();
for i in (0..100).step_by(2) {
assert_eq!(tree.len(), i / 2);
tree.insert(tree.len(), i..i + 1);
tree.debug_check();
}
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::default();
t.with_tree_mut(|tree| {
for i in (0..100).step_by(2) {
assert_eq!(tree.len(), i / 2);
tree.insert(tree.len(), i..i + 1);
tree.debug_check();
}
});
}
#[test]
fn deletion_that_need_merge_to_sibling() {
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::new();
let tree = t.get_mut();
for i in (0..18).step_by(2) {
tree.insert(tree.len(), i..i + 1);
}
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::default();
t.with_tree_mut(|tree| {
for i in (0..18).step_by(2) {
tree.insert(tree.len(), i..i + 1);
}
tree.delete_range(Some(1), Some(tree.len() - 1));
tree.debug_check();
tree.delete_range(Some(1), Some(tree.len() - 1));
tree.debug_check();
});
}
#[test]
fn delete_that_need_borrow_from_sibling() {
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::new();
let tree = t.get_mut();
for i in (0..16).step_by(2) {
tree.insert(tree.len(), i..i + 1);
}
tree.delete_range(Some(2), Some(3));
// Left [ 0..1, 2..3, 6..7 ]
// Right [8..9, 10..11, 12..13, 14..15]
tree.delete_range(Some(1), Some(2));
{
// Left [ 0..1, 6..7 ]
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::default();
t.with_tree_mut(|tree| {
for i in (0..16).step_by(2) {
tree.insert(tree.len(), i..i + 1);
}
tree.delete_range(Some(2), Some(3));
// Left [ 0..1, 2..3, 6..7 ]
// Right [8..9, 10..11, 12..13, 14..15]
let left = &tree.node.as_internal().unwrap().children[0];
assert_eq!(left.as_leaf().unwrap().cache, 2);
let right = &tree.node.as_internal().unwrap().children[1];
assert_eq!(right.as_leaf().unwrap().cache, 4);
}
tree.delete_range(Some(1), Some(2));
{
// Left [ 0..1, 8..9, 10..11 ]
// Right [12..13, 14..15]
let left = &tree.node.as_internal().unwrap().children[0];
assert_eq!(left.as_leaf().unwrap().cache, 3);
let right = &tree.node.as_internal().unwrap().children[1];
assert_eq!(right.as_leaf().unwrap().cache, 2);
}
tree.delete_range(Some(1), Some(2));
{
// Left [ 0..1, 6..7 ]
// Right [8..9, 10..11, 12..13, 14..15]
let left = &tree.node.as_internal().unwrap().children[0];
assert_eq!(left.as_leaf().unwrap().cache, 2);
let right = &tree.node.as_internal().unwrap().children[1];
assert_eq!(right.as_leaf().unwrap().cache, 4);
}
let expected = [0..1, 8..9, 10..11, 12..13, 14..15];
for (actual, expected) in tree.iter().zip(expected.iter()) {
assert_eq!(actual, expected);
}
tree.delete_range(Some(1), Some(2));
{
// Left [ 0..1, 8..9, 10..11 ]
// Right [12..13, 14..15]
let left = &tree.node.as_internal().unwrap().children[0];
assert_eq!(left.as_leaf().unwrap().cache, 3);
let right = &tree.node.as_internal().unwrap().children[1];
assert_eq!(right.as_leaf().unwrap().cache, 2);
}
tree.debug_check();
let expected = [0..1, 8..9, 10..11, 12..13, 14..15];
for (actual, expected) in tree.iter().zip(expected.iter()) {
assert_eq!(actual, expected);
}
tree.debug_check();
});
}
#[test]
fn delete_that_causes_removing_layers() {
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::new();
let tree = t.get_mut();
for i in (0..128).step_by(2) {
tree.insert(tree.len(), i..i + 1);
}
tree.debug_check();
tree.delete_range(Some(1), None);
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::default();
t.with_tree_mut(|tree| {
for i in (0..128).step_by(2) {
tree.insert(tree.len(), i..i + 1);
}
tree.debug_check();
tree.delete_range(Some(1), None);
});
}
#[test]
fn delete_that_causes_increase_levels() {
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::new();
let tree = t.get_mut();
tree.insert(0, 0..100);
for i in 0..50 {
tree.delete_range(Some(i), Some(i + 1));
tree.debug_check();
}
let mut t: RleTree<Range<usize>, RangeTreeTrait> = RleTree::default();
t.with_tree_mut(|tree| {
tree.insert(0, 0..100);
for i in 0..50 {
tree.delete_range(Some(i), Some(i + 1));
tree.debug_check();
}
dbg!(tree);
dbg!(tree);
});
}

View file

@ -146,11 +146,13 @@ fn get_pos<T: HasLength>(index: usize, child: &T) -> Position {
impl Display for RleTree<CustomString, StringTreeTrait> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
for s in self.get_ref().iter() {
f.write_str(s.0.as_str())?;
}
self.with_tree(|tree| {
for s in tree.iter() {
f.write_str(s.0.as_str())?;
}
Ok(())
Ok(())
})
}
}
@ -168,10 +170,11 @@ impl From<&str> for CustomString {
#[test]
fn basic_string_op() {
let mut tree: RleTree<CustomString, StringTreeTrait> = RleTree::new();
let handler = tree.get_mut();
handler.insert(0, "test".into());
handler.insert(0, "hello ".into());
let mut tree: RleTree<CustomString, StringTreeTrait> = RleTree::default();
tree.with_tree_mut(|tree| {
tree.insert(0, "test".into());
tree.insert(0, "hello ".into());
});
let m = format!("{}", tree);
assert_eq!(m, "hello test");
}