fix: movable list undo del impl

This commit is contained in:
Zixuan Chen 2024-10-12 13:49:36 +08:00
parent ba7c1b7b94
commit f4823191e7
No known key found for this signature in database
2 changed files with 156 additions and 22 deletions

View file

@ -12782,6 +12782,132 @@ fn movable_list_undo_impl() {
)
}
#[test]
fn movable_list_undo_impl_1() {
test_multi_sites(
5,
vec![FuzzTarget::All],
&mut [
Handle {
site: 29,
target: 29,
container: 6,
action: Generic(GenericAction {
value: Container(Text),
bool: false,
key: 4292569563,
pos: 15492342490870120406,
length: 18446519864200508159,
prop: 10161246657334578573,
}),
},
Handle {
site: 167,
target: 129,
container: 4,
action: Generic(GenericAction {
value: Container(Map),
bool: true,
key: 123736320,
pos: 12898264252198542080,
length: 15789862182697904091,
prop: 18446618237837639456,
}),
},
SyncAll,
SyncAll,
Handle {
site: 0,
target: 24,
container: 24,
action: Generic(GenericAction {
value: I32(-65536),
bool: true,
key: 4009754624,
pos: 17221764975752642560,
length: 7421932185895899375,
prop: 18446744073709551474,
}),
},
Handle {
site: 128,
target: 81,
container: 43,
action: Generic(GenericAction {
value: Container(Text),
bool: true,
key: 757935366,
pos: 7627690425558565057,
length: 15810408764199600091,
prop: 3752949689037608703,
}),
},
SyncAllUndo {
site: 108,
op_len: 2365849344,
},
Handle {
site: 167,
target: 129,
container: 4,
action: Generic(GenericAction {
value: Container(Map),
bool: true,
key: 123736320,
pos: 12838591557135883008,
length: 15789862182697904091,
prop: 18446618237837639456,
}),
},
SyncAll,
SyncAll,
Handle {
site: 0,
target: 24,
container: 24,
action: Generic(GenericAction {
value: I32(-65536),
bool: true,
key: 4009754624,
pos: 17221764975752642560,
length: 7421932185895899375,
prop: 18446744073709551474,
}),
},
Handle {
site: 128,
target: 79,
container: 43,
action: Generic(GenericAction {
value: Container(Text),
bool: false,
key: 4612,
pos: 6293508899878207488,
length: 185600485263537,
prop: 8169935443840729235,
}),
},
Checkout {
site: 147,
to: 2067994371,
},
SyncAllUndo {
site: 0,
op_len: 3318087425,
},
Sync { from: 197, to: 35 },
SyncAllUndo {
site: 151,
op_len: 2543294359,
},
Undo {
site: 1,
op_len: 4250350213,
},
],
)
}
#[test]
fn minify() {
minify_error(

View file

@ -78,11 +78,15 @@ impl MovableListHandler {
let mut index_shift = 0;
let mut deleted_indices = Vec::new();
let mut next_deleted = BinaryHeap::new();
// - positive values are retain
// - negative values are deletions
let mut delta_change: Vec<isize> = Vec::new();
for delta_item in delta.iter() {
match delta_item {
loro_delta::DeltaItem::Retain { len, .. } => {
index += len;
delta_change.push(*len as isize);
}
loro_delta::DeltaItem::Replace {
value,
@ -90,13 +94,16 @@ impl MovableListHandler {
attr,
} => {
// Handle deletions in the current replace operation.
let old_index = index;
self.handle_deletions_in_replace(
*delete,
&mut index,
index_shift,
&mut next_deleted,
);
delta_change.push(-((index - old_index) as isize));
let old_index = index;
// Process the insertions and moves.
let mut context = ReplacementContext {
index: &mut index,
@ -109,12 +116,13 @@ impl MovableListHandler {
self.process_replacements(value, attr, &mut context)
.unwrap();
delta_change.push((index - old_index) as isize);
}
}
}
// Apply any remaining deletions.
self.apply_remaining_deletions(&delta, &mut deleted_indices)
self.apply_remaining_deletions(delta_change, &mut deleted_indices)
.unwrap();
Ok(())
@ -162,7 +170,8 @@ impl MovableListHandler {
to_delete
}
/// Handles deletions within a replace operation.
/// Handles deletions' effect on the index within a replace operation.
/// It will not perform the deletions.
///
/// # Arguments
///
@ -268,25 +277,27 @@ impl MovableListHandler {
/// * `deleted_indices` - A list of indices that have been deleted.
fn apply_remaining_deletions(
&self,
delta: &loro_delta::DeltaRope<
loro_delta::array_vec::ArrayVec<ValueOrHandler, 8>,
crate::event::ListDeltaMeta,
>,
delta: Vec<isize>,
deleted_indices: &mut Vec<usize>,
) -> LoroResult<()> {
// Sort deleted indices from largest to smallest.
deleted_indices.sort_by_key(|&x| std::cmp::Reverse(x));
let mut index = 0;
let mut index: usize = 0;
for delta_item in delta.iter() {
match delta_item {
loro_delta::DeltaItem::Retain { len, .. } => {
index += len;
match *delta_item {
x if x > 0 => {
index += x as usize;
}
loro_delta::DeltaItem::Replace { delete, value, .. } => {
if *delete > 0 {
let mut remaining_deletes = *delete;
neg_delete => {
let delete = neg_delete.unsigned_abs();
let mut remaining_deletes = delete;
while let Some(&last) = deleted_indices.last() {
if last < index {
deleted_indices.pop();
continue;
}
if last < index + remaining_deletes {
deleted_indices.pop();
remaining_deletes -= 1;
@ -297,9 +308,6 @@ impl MovableListHandler {
self.delete(index, remaining_deletes)?;
}
index += value.len();
}
}
}