Add merge
This commit is contained in:
parent
08910f1454
commit
05cdd68d39
1 changed files with 73 additions and 2 deletions
|
|
@ -91,7 +91,8 @@ impl Operation {
|
|||
if let Some(text) = deleted_text {
|
||||
debug_assert_eq!(
|
||||
rope_text.get_slice(self.range()).unwrap().to_string(),
|
||||
*text
|
||||
*text,
|
||||
"Text to delete does not match the text in the rope"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +133,12 @@ impl Operation {
|
|||
}
|
||||
}
|
||||
|
||||
/// The operation cannot be empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
debug_assert!(self.len() > 0, "Operation cannot be empty");
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns the range of indices of characters that the operation affects, inclusive.
|
||||
pub fn range(&self) -> std::ops::RangeInclusive<usize> {
|
||||
self.start_index()..=self.end_index()
|
||||
|
|
@ -173,6 +180,70 @@ impl Operation {
|
|||
|
||||
Ok(self.with_index(non_negative_index))
|
||||
}
|
||||
|
||||
/// Merges the operation with another operation that is consequtive to this operation.
|
||||
/// The other operation must start where this operation ends.
|
||||
/// The two operations must be of the same type, otherwise panics.
|
||||
pub fn merge(self, other: &Self) -> Self {
|
||||
match (self, other) {
|
||||
(
|
||||
Operation::Insert { index, text },
|
||||
Operation::Insert {
|
||||
text: other_text, ..
|
||||
},
|
||||
) => {
|
||||
let end_index = index + text.chars().count();
|
||||
debug_assert!(
|
||||
end_index == other.start_index(),
|
||||
"Cannot merge non-consequtive inserts with index {} and {}",
|
||||
end_index,
|
||||
other.start_index()
|
||||
);
|
||||
|
||||
Operation::Insert {
|
||||
index,
|
||||
text: text + other_text,
|
||||
}
|
||||
}
|
||||
(
|
||||
Operation::Delete {
|
||||
index,
|
||||
deleted_character_count,
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
deleted_text,
|
||||
},
|
||||
Operation::Delete {
|
||||
index: other_index,
|
||||
deleted_character_count: other_deleted_character_count,
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
deleted_text: other_deleted_text,
|
||||
},
|
||||
) => {
|
||||
debug_assert!(
|
||||
index == *other_index,
|
||||
"Cannot merge non-consequtive deletes",
|
||||
);
|
||||
|
||||
Operation::Delete {
|
||||
index,
|
||||
deleted_character_count: deleted_character_count
|
||||
+ other_deleted_character_count,
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
deleted_text: deleted_text
|
||||
.into_iter()
|
||||
.flat_map(|t1| other_deleted_text.as_ref().map(|t2| t1 + t2).into_iter())
|
||||
.last(),
|
||||
}
|
||||
}
|
||||
(this, other) => panic!(
|
||||
"Cannot merge operations of different type: {:?} and {:?}",
|
||||
&this, &other
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Operation {
|
||||
|
|
@ -222,7 +293,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_apply_delete_with_create() -> Result<(), SyncLibError> {
|
||||
let mut rope = Rope::from_str("hello world");
|
||||
let operation = Operation::create_delete_with_text(5, "world ".to_string()).unwrap();
|
||||
let operation = Operation::create_delete_with_text(5, " world".to_string()).unwrap();
|
||||
|
||||
operation.apply(&mut rope)?;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue