fix: string fuzzy

This commit is contained in:
Zixuan Chen 2022-09-09 02:01:24 +08:00
parent 0d99ceb01c
commit 1df1f1d2bf
8 changed files with 177 additions and 85 deletions

View file

@ -1,6 +1,6 @@
use std::ops::{Deref, DerefMut};
use rle::{rle_tree::SafeCursorMut, Rle, RleTree, RleTreeTrait};
use rle::{rle_tree::SafeCursorMut, RleTree};
use super::y_span::{StatusChange, YSpan, YSpanTreeTrait};
@ -22,8 +22,8 @@ impl DerefMut for ContentMap {
}
}
pub(super) fn change_status(
cursor: &mut SafeCursorMut<'_, '_, YSpan, YSpanTreeTrait>,
pub(super) fn change_status<'a, 'b: 'a>(
cursor: &mut SafeCursorMut<'a, 'b, YSpan, YSpanTreeTrait>,
change: StatusChange,
) {
let value = cursor.as_mut();

View file

@ -30,13 +30,14 @@ pub struct SafeCursor<'tree, 'bump, T: Rle, A: RleTreeTrait<T>>(
pub(crate) UnsafeCursor<'tree, 'bump, T, A>,
);
pub struct SafeCursorMut<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>>(
#[repr(transparent)]
pub struct SafeCursorMut<'tree, 'bump, T: Rle, A: RleTreeTrait<T>>(
pub(crate) UnsafeCursor<'tree, 'bump, T, A>,
);
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Clone for SafeCursor<'tree, 'bump, T, A> {
fn clone(&self) -> Self {
Self(self.0.clone())
Self(self.0)
}
}
@ -152,6 +153,16 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
pub fn as_ref_(&self) -> &'tree T {
unsafe { self.0.as_ref() }
}
#[inline]
pub fn leaf(&self) -> &'tree LeafNode<'bump, T, A> {
unsafe { self.0.leaf.as_ref() }
}
#[inline]
pub fn child_index(&self) -> usize {
self.0.index
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump, T, A> {

View file

@ -1,5 +1,3 @@
use std::ptr::NonNull;
use crate::Rle;
use super::{
@ -8,7 +6,7 @@ use super::{
SafeCursor,
};
pub struct Iter<'some, 'bump, T: Rle, A: RleTreeTrait<T>> {
pub struct Iter<'some, 'bump: 'some, T: Rle, A: RleTreeTrait<T>> {
node: Option<&'some LeafNode<'bump, T, A>>,
child_index: usize,
end_node: Option<&'some LeafNode<'bump, T, A>>,

View file

@ -64,12 +64,20 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> Node<'a, T, A> {
match self {
Self::Internal(node) => node
.children
.get(0)
.first()
.and_then(|child| child.get_first_leaf()),
Self::Leaf(node) => Some(node),
}
}
#[inline]
pub(crate) fn get_last_leaf(&self) -> Option<&LeafNode<'a, T, A>> {
match self {
Self::Internal(node) => node.children.last().and_then(|child| child.get_last_leaf()),
Self::Leaf(node) => Some(node),
}
}
#[inline]
fn children_num(&self) -> usize {
match self {

View file

@ -109,9 +109,10 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
from.map_or((0, None), |x| self._delete_start(x));
let (direct_delete_end, to_del_end_offset) =
to.map_or((self.children.len(), None), |x| self._delete_end(x));
let mut result = Ok(());
let deleted_len = direct_delete_end as isize - direct_delete_start as isize;
let mut insertions = vec![];
{
// handle edge removing
// handle removing at the end point
let mut handled = false;
if let (Some(del_from), Some(del_to)) = (to_del_start_offset, to_del_end_offset) {
if direct_delete_start - 1 == direct_delete_end {
@ -128,12 +129,12 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
depth + 1,
notify,
) {
result = self._insert_with_split(direct_delete_end + 1, new);
insertions.push((direct_delete_end + 1, new));
}
}
Node::Leaf(node) => {
if let Err(new) = node.delete(Some(del_from), Some(del_to), notify) {
result = self._insert_with_split(direct_delete_end + 1, new);
insertions.push((direct_delete_end + 1, new));
}
}
}
@ -152,12 +153,12 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
if let Err(new) =
node._delete(Some(del_from), None, visited, depth + 1, notify)
{
result = self._insert_with_split(direct_delete_start, new);
insertions.push((direct_delete_start, new));
}
}
Node::Leaf(node) => {
if let Err(new) = node.delete(Some(del_from), None, notify) {
result = self._insert_with_split(direct_delete_start, new)
insertions.push((direct_delete_start, new));
}
}
}
@ -172,14 +173,12 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
if let Err(new) =
node._delete(None, Some(del_to), visited, depth + 1, notify)
{
debug_assert!(result.is_ok());
result = self._insert_with_split(direct_delete_end + 1, new);
insertions.push((direct_delete_end + 1, new));
}
}
Node::Leaf(node) => {
if let Err(new) = node.delete(None, Some(del_to), notify) {
debug_assert!(result.is_ok());
result = self._insert_with_split(direct_delete_end + 1, new);
insertions.push((direct_delete_end + 1, new));
}
}
}
@ -187,10 +186,24 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
}
}
if direct_delete_start < direct_delete_end {
if deleted_len > 0 {
self.connect_leaf(direct_delete_start, direct_delete_end - 1);
self.children.drain(direct_delete_start..direct_delete_end);
}
insertions.sort_by_key(|x| -(x.0 as isize));
let mut result = Ok(());
for mut insertion in insertions {
if insertion.0 >= direct_delete_end && deleted_len > 0 {
insertion.0 -= deleted_len as usize;
}
if let Err(data) = self._insert_with_split(insertion.0, insertion.1) {
assert!(result.is_ok());
result = Err(data);
}
}
A::update_cache_internal(self);
if let Err(new) = &mut result {
A::update_cache_internal(new.as_internal_mut().unwrap());
@ -199,6 +212,24 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
result
}
/// connect [prev leaf of left] with [next leaf of right]
fn connect_leaf(&mut self, left_index: usize, right_index: usize) {
let prev = self.children[left_index]
.get_first_leaf()
.and_then(|x| x.prev);
let next = self.children[right_index]
.get_last_leaf()
.and_then(|x| x.next);
if let Some(mut prev) = prev {
let prev = unsafe { prev.as_mut() };
prev.next = next;
}
if let Some(mut next) = next {
let next = unsafe { next.as_mut() };
next.prev = prev;
}
}
fn _delete_start(&mut self, from: A::Int) -> (usize, Option<A::Int>) {
let from = A::find_pos_internal(self, from);
if from.pos == Position::Start || from.pos == Position::Before {

View file

@ -41,6 +41,9 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
ans_inner.next = self.next;
ans_inner.prev = Some(NonNull::new(self).unwrap());
if let Some(mut next) = self.next {
unsafe { next.as_mut().prev = Some(NonNull::new_unchecked(ans_inner)) };
}
self.next = Some(NonNull::new(&mut *ans_inner).unwrap());
ans
}
@ -94,6 +97,14 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
pub(crate) fn check(&mut self) {
assert!(self.children.len() <= A::MAX_CHILDREN_NUM);
A::check_cache_leaf(self);
if let Some(next) = self.next {
let self_ptr = unsafe { next.as_ref().prev.unwrap().as_ptr() };
assert!(std::ptr::eq(self, self_ptr));
}
if let Some(prev) = self.prev {
let self_ptr = unsafe { prev.as_ref().next.unwrap().as_ptr() };
assert!(std::ptr::eq(self, self_ptr));
}
}
fn _delete_start(&mut self, from: A::Int) -> (usize, Option<usize>) {

View file

@ -90,6 +90,9 @@ fn test(interactions: &[Interaction]) {
let out = out.unwrap();
//println!("vs \nindexMap: {:#?}", &out);
assert_eq!(v.as_ref().value, out.start);
let leaf = v.0.leaf.as_ptr() as usize;
let out_ptr = out.value.as_ptr() as usize;
assert_eq!(out_ptr, leaf);
}
});
@ -111,8 +114,8 @@ fn test(interactions: &[Interaction]) {
prop_compose! {
fn gen_interaction()(
_type in 0..1,
from in 0..10000,
_type in 0..2,
from in 0..100,
len in 1..10,
) -> Interaction {
if _type == 0 {
@ -157,59 +160,12 @@ fn issue_2() {
}
#[test]
fn issue_3() {
fn issue_4() {
test(&[
Insert { from: 0, len: 7 },
Insert { from: 0, len: 4 },
Insert { from: 0, len: 1 },
Insert { from: 4, len: 2 },
Insert { from: 0, len: 3 },
Insert { from: 120, len: 1 },
Insert { from: 1785, len: 1 },
Insert { from: 6137, len: 1 },
Insert { from: 2970, len: 5 },
Insert { from: 2424, len: 5 },
Insert { from: 2246, len: 4 },
Insert { from: 104, len: 1 },
Insert { from: 447, len: 1 },
Insert { from: 5394, len: 3 },
Insert { from: 113, len: 6 },
Insert { from: 6563, len: 7 },
Insert { from: 8964, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
Insert { from: 0, len: 1 },
]);
Insert { from: 0, len: 5 },
Insert { from: 12, len: 2 },
Insert { from: 5, len: 1 },
])
}
#[cfg(not(no_proptest))]

View file

@ -125,7 +125,9 @@ impl Interaction {
pub fn test_assert(&self, s: &mut String, tree: &mut RleTree<CustomString, StringTreeTrait>) {
self.apply_to_str(s);
self.apply_to_tree(tree);
// println!("{:#?}", tree);
assert_eq!(&tree.to_string(), s);
// println!("{}", s);
}
fn apply_to_str(&self, s: &mut String) {
@ -135,8 +137,12 @@ impl Interaction {
s.insert_str(insert_at, content.as_str())
}
Interaction::Delete { from, len } => {
if s.is_empty() {
return;
}
let from = *from % s.len();
let mut to = from + (*len % s.len());
let mut to = from + *len;
if to > s.len() {
to = s.len();
}
@ -156,8 +162,12 @@ impl Interaction {
}
Interaction::Delete { from, len } => {
tree.with_tree_mut(|tree| {
if tree.len() == 0 {
return;
}
let from = *from % tree.len();
let mut to = from + (*len % tree.len());
let mut to = from + *len;
if to > tree.len() {
to = tree.len();
}
@ -169,6 +179,78 @@ impl Interaction {
}
}
fn run_test(interactions: Vec<Interaction>) {
let mut s = String::new();
let mut tree = RleTree::default();
for interaction in interactions {
interaction.test_assert(&mut s, &mut tree);
tree.with_tree_mut(|tree| {
tree.debug_check();
});
}
}
use Interaction::*;
#[test]
fn issue_delete() {
run_test(vec![
Insert {
insert_at: 0,
content: "0000000000000".into(),
},
Delete { from: 7, len: 1 },
Insert {
insert_at: 0,
content: "11111111111111111".into(),
},
Delete { from: 0, len: 1 },
Insert {
insert_at: 1,
content: "2222222".into(),
},
Delete { from: 0, len: 3 },
Delete { from: 0, len: 1 },
Insert {
insert_at: 0,
content: "333333333".into(),
},
Insert {
insert_at: 8,
content: "44".into(),
},
Insert {
insert_at: 0,
content: "55555555555555555555555555555555".into(),
},
Delete { from: 0, len: 1 },
Delete { from: 2, len: 4 },
Delete { from: 3, len: 9 },
Insert {
insert_at: 0,
content: "6".into(),
},
Delete { from: 5, len: 6 },
Delete { from: 4, len: 6 },
Insert {
insert_at: 9,
content: "7".into(),
},
Insert {
insert_at: 8,
content: "88".into(),
},
Insert {
insert_at: 0,
content: "9".into(),
},
// 96555555388373333334432222111111111111111000000000000
Delete { from: 6, len: 6 },
// Expected: 96555573333334432222111111111111111000000000000
// Out: 965573333334432222111111111111111000000000000
])
}
#[cfg(not(no_proptest))]
mod string_prop_test {
use super::*;
@ -176,10 +258,10 @@ mod string_prop_test {
prop_compose! {
fn gen_interaction()(
_type in 0..1,
_type in 0..2,
from in 0..10000000,
len in 0..10,
content in "[a-z]*"
len in 1..10,
content in "[a-z]+"
) -> Interaction {
if _type == 0 {
Interaction::Insert {
@ -200,12 +282,7 @@ mod string_prop_test {
fn test_tree_string_op_the_same(
interactions in prop::collection::vec(gen_interaction(), 1..100),
) {
let mut s = String::new();
let mut tree = RleTree::default();
for interaction in interactions {
interaction.test_assert(&mut s, &mut tree);
tree.with_tree_mut(|tree|tree.debug_check());
}
run_test(interactions);
}
}