This commit is contained in:
Antonio Scandurra 2021-11-12 15:18:55 +01:00
parent f49c9db423
commit b2aab0c773

View File

@ -1,12 +1,16 @@
use std::{cmp, iter::Peekable, mem, ops::Range};
use std::{cmp, mem, slice};
type Edit = buffer::Edit<u32>;
#[derive(Default, Debug, PartialEq, Eq)]
struct Patch(Vec<Edit>);
pub struct Patch(Vec<Edit>);
impl Patch {
fn compose(&self, other: &Self) -> Self {
pub unsafe fn new_unchecked(edits: Vec<Edit>) -> Self {
Self(edits)
}
pub fn compose(&self, other: &Self) -> Self {
let mut old_edits_iter = self.0.iter().cloned().peekable();
let mut new_edits_iter = other.0.iter().cloned().peekable();
let mut composed = Patch(Vec::new());
@ -61,7 +65,6 @@ impl Patch {
old_start = old_end;
new_start = new_end;
old_edits_iter.next();
continue;
} else if new_edit.old.end < old_edit.new.start {
let catchup = new_edit.new.start - new_start;
old_start += catchup;
@ -114,10 +117,8 @@ impl Patch {
}
if old_edit.new.end > new_edit.old.end {
let old_len =
cmp::min(old_edit.old.len() as u32, new_edit.old.len() as u32);
let old_end = old_start + old_len;
let old_end = old_start
+ cmp::min(old_edit.old.len() as u32, new_edit.old.len() as u32);
let new_end = new_start + new_edit.new.len() as u32;
composed.push(Edit {
old: old_start..old_end,
@ -130,11 +131,9 @@ impl Patch {
new_start = new_end;
new_edits_iter.next();
} else {
let new_len =
cmp::min(old_edit.new.len() as u32, new_edit.new.len() as u32);
let old_end = old_start + old_edit.old.len() as u32;
let new_end = new_start + new_len;
let new_end = new_start
+ cmp::min(old_edit.new.len() as u32, new_edit.new.len() as u32);
composed.push(Edit {
old: old_start..old_end,
new: new_start..new_end,
@ -154,6 +153,17 @@ impl Patch {
composed
}
pub fn invert(&mut self) -> &mut Self {
for edit in &mut self.0 {
mem::swap(&mut edit.old, &mut edit.new);
}
self
}
pub fn clear(&mut self) {
self.0.clear();
}
fn push(&mut self, edit: Edit) {
if edit.old.len() == 0 && edit.new.len() == 0 {
return;
@ -172,6 +182,15 @@ impl Patch {
}
}
impl<'a> IntoIterator for &'a Patch {
type Item = &'a Edit;
type IntoIter = slice::Iter<'a, Edit>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -399,13 +418,13 @@ mod tests {
);
}
#[gpui::test(iterations = 100, seed = 1)]
#[gpui::test(iterations = 100)]
fn test_random_patch_compositions(mut rng: StdRng) {
let operations = env::var("OPERATIONS")
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(5);
.unwrap_or(20);
let initial_chars = (0..rng.gen_range(0..=10))
let initial_chars = (0..rng.gen_range(0..=100))
.map(|_| rng.gen_range(b'a'..=b'z') as char)
.collect::<Vec<_>>();
println!("initial chars: {:?}", initial_chars);