More work on Transaction.
This commit is contained in:
parent
f9415d915f
commit
f3c12d6cee
|
@ -33,28 +33,69 @@ impl Transaction {
|
|||
}
|
||||
}
|
||||
|
||||
/// Adds another edit to the Transaction.
|
||||
///
|
||||
/// This composes as if the edits already in the Transaction were
|
||||
/// performed first, and then the new edit was performed after.
|
||||
pub fn push_edit(&mut self, byte_idx: usize, old: &str, new: &str) {
|
||||
if self.ops.is_empty() {
|
||||
// The easy case.
|
||||
self.buffer.push_str(old);
|
||||
self.buffer.push_str(new);
|
||||
self.ops.push(Op::Retain {
|
||||
/// Creates a Transaction from a single edit.
|
||||
pub fn from_edit(byte_idx: usize, old: &str, new: &str) -> Transaction {
|
||||
let mut buffer = String::new();
|
||||
buffer.push_str(old);
|
||||
buffer.push_str(new);
|
||||
|
||||
let ops = vec![
|
||||
Op::Retain {
|
||||
byte_count: byte_idx,
|
||||
});
|
||||
self.ops.push(Op::Replace {
|
||||
},
|
||||
Op::Replace {
|
||||
old: 0..old.len(),
|
||||
new: old.len()..(old.len() + new.len()),
|
||||
});
|
||||
} else {
|
||||
// The complex case.
|
||||
todo!()
|
||||
},
|
||||
];
|
||||
|
||||
Transaction {
|
||||
ops: ops,
|
||||
buffer: buffer,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a Transaction from a sorted, non-overlapping set of
|
||||
/// simultaneous edits.
|
||||
///
|
||||
/// Takes an iterator that yields `(byte_index, old_text, replacement_text)`
|
||||
/// tuples, representing the edits. The items are expected to be
|
||||
/// yielded in byte-index order, and the byte indices are relative to
|
||||
/// the original text--this function does _not_ treat them as a
|
||||
/// sequence of progressively applied edits, but rather as a set of
|
||||
/// edits applied simultaneously.
|
||||
pub fn from_ordered_edit_set<'a, I>(edit_iter: I) -> Transaction
|
||||
where
|
||||
I: Iterator<Item = (usize, &'a str, &'a str)> + 'a,
|
||||
{
|
||||
let mut trans = Transaction::new();
|
||||
let mut i = 0;
|
||||
let mut len_delta = 0isize;
|
||||
for (byte_idx, old, new) in edit_iter {
|
||||
let adjusted_byte_idx = (byte_idx as isize + len_delta) as usize;
|
||||
let retained = adjusted_byte_idx - i;
|
||||
|
||||
let old_range = trans.buffer.len()..(trans.buffer.len() + old.len());
|
||||
trans.buffer.push_str(old);
|
||||
let new_range = trans.buffer.len()..(trans.buffer.len() + new.len());
|
||||
trans.buffer.push_str(new);
|
||||
|
||||
if retained > 0 {
|
||||
trans.ops.push(Op::Retain {
|
||||
byte_count: retained,
|
||||
});
|
||||
}
|
||||
trans.ops.push(Op::Replace {
|
||||
old: old_range,
|
||||
new: new_range,
|
||||
});
|
||||
|
||||
i += retained + new.len();
|
||||
len_delta += new.len() as isize - old.len() as isize;
|
||||
}
|
||||
trans
|
||||
}
|
||||
|
||||
/// Build a Transaction that is functionally identical to applying
|
||||
/// first `self` and then `other` sequentially.
|
||||
#[must_use]
|
||||
|
|
Loading…
Reference in New Issue
Block a user