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.
|
/// Creates a Transaction from a single edit.
|
||||||
///
|
pub fn from_edit(byte_idx: usize, old: &str, new: &str) -> Transaction {
|
||||||
/// This composes as if the edits already in the Transaction were
|
let mut buffer = String::new();
|
||||||
/// performed first, and then the new edit was performed after.
|
buffer.push_str(old);
|
||||||
pub fn push_edit(&mut self, byte_idx: usize, old: &str, new: &str) {
|
buffer.push_str(new);
|
||||||
if self.ops.is_empty() {
|
|
||||||
// The easy case.
|
let ops = vec![
|
||||||
self.buffer.push_str(old);
|
Op::Retain {
|
||||||
self.buffer.push_str(new);
|
|
||||||
self.ops.push(Op::Retain {
|
|
||||||
byte_count: byte_idx,
|
byte_count: byte_idx,
|
||||||
});
|
},
|
||||||
self.ops.push(Op::Replace {
|
Op::Replace {
|
||||||
old: 0..old.len(),
|
old: 0..old.len(),
|
||||||
new: old.len()..(old.len() + new.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
|
/// Build a Transaction that is functionally identical to applying
|
||||||
/// first `self` and then `other` sequentially.
|
/// first `self` and then `other` sequentially.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user