@@ -169,7 +169,7 @@ impl History {
}
fn push(&mut self, op: EditOperation) {
- self.ops.insert(op.id, op);
+ self.ops.insert(op.timestamp.local(), op);
}
fn start_transaction(
@@ -326,12 +326,34 @@ struct Diff {
changes: Vec<(ChangeTag, usize)>,
}
+#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
+struct InsertionTimestamp {
+ replica_id: ReplicaId,
+ local: time::Seq,
+ lamport: time::Seq,
+}
+
+impl InsertionTimestamp {
+ fn local(&self) -> time::Local {
+ time::Local {
+ replica_id: self.replica_id,
+ value: self.local,
+ }
+ }
+
+ fn lamport(&self) -> time::Lamport {
+ time::Lamport {
+ replica_id: self.replica_id,
+ value: self.lamport,
+ }
+ }
+}
+
#[derive(Eq, PartialEq, Clone, Debug)]
struct Fragment {
+ timestamp: InsertionTimestamp,
len: usize,
visible: bool,
- insertion_id: time::Local,
- lamport_timestamp: time::Lamport,
deletions: HashSet<time::Local>,
max_undos: time::Global,
}
@@ -359,10 +381,7 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Operation {
- Edit {
- edit: EditOperation,
- lamport_timestamp: time::Lamport,
- },
+ Edit(EditOperation),
Undo {
undo: UndoOperation,
lamport_timestamp: time::Lamport,
@@ -376,7 +395,7 @@ pub enum Operation {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EditOperation {
- id: time::Local,
+ timestamp: InsertionTimestamp,
version: time::Global,
ranges: Vec<Range<usize>>,
new_text: Option<String>,
@@ -457,12 +476,11 @@ impl Buffer {
if visible_text.len() > 0 {
fragments.push(
Fragment {
- insertion_id: Default::default(),
- lamport_timestamp: Default::default(),
+ timestamp: Default::default(),
len: visible_text.len(),
+ visible: true,
deletions: Default::default(),
max_undos: Default::default(),
- visible: true,
},
&None,
);
@@ -932,21 +950,21 @@ impl Buffer {
None
} else {
self.start_transaction_at(None, Instant::now()).unwrap();
- let edit_id = self.local_clock.tick();
- let lamport_timestamp = self.lamport_clock.tick();
- let edit = self.apply_local_edit(&ranges, new_text, edit_id, lamport_timestamp);
+ let timestamp = InsertionTimestamp {
+ replica_id: self.replica_id,
+ local: self.local_clock.tick().value,
+ lamport: self.lamport_clock.tick().value,
+ };
+ let edit = self.apply_local_edit(&ranges, new_text, timestamp);
self.history.push(edit.clone());
- self.history.push_undo(edit.id);
- self.last_edit = edit.id;
- self.version.observe(edit.id);
+ self.history.push_undo(edit.timestamp.local());
+ self.last_edit = edit.timestamp.local();
+ self.version.observe(edit.timestamp.local());
self.end_transaction_at(None, Instant::now(), cx).unwrap();
- Some(Operation::Edit {
- edit,
- lamport_timestamp,
- })
+ Some(Operation::Edit(edit))
}
}
@@ -1067,20 +1085,15 @@ impl Buffer {
fn apply_op(&mut self, op: Operation) -> Result<()> {
match op {
- Operation::Edit {
- edit,
- lamport_timestamp,
- ..
- } => {
- if !self.version.observed(edit.id) {
+ Operation::Edit(edit) => {
+ if !self.version.observed(edit.timestamp.local()) {
self.apply_remote_edit(
&edit.version,
&edit.ranges,
edit.new_text.as_deref(),
- edit.id,
- lamport_timestamp,
+ edit.timestamp,
);
- self.version.observe(edit.id);
+ self.version.observe(edit.timestamp.local());
self.history.push(edit);
}
}
@@ -1116,8 +1129,7 @@ impl Buffer {
version: &time::Global,
ranges: &[Range<usize>],
new_text: Option<&str>,
- local_timestamp: time::Local,
- lamport_timestamp: time::Lamport,
+ timestamp: InsertionTimestamp,
) {
if ranges.is_empty() {
return;
@@ -1171,7 +1183,9 @@ impl Buffer {
// Skip over insertions that are concurrent to this edit, but have a lower lamport
// timestamp.
while let Some(fragment) = old_fragments.item() {
- if fragment_start == range.start && fragment.lamport_timestamp > lamport_timestamp {
+ if fragment_start == range.start
+ && fragment.timestamp.lamport() > timestamp.lamport()
+ {
new_ropes.push_fragment(fragment, fragment.visible);
new_fragments.push(fragment.clone(), &None);
old_fragments.next(&cx);
@@ -1196,8 +1210,7 @@ impl Buffer {
new_ropes.push_str(new_text);
new_fragments.push(
Fragment {
- insertion_id: local_timestamp,
- lamport_timestamp,
+ timestamp,
len: new_text.len(),
deletions: Default::default(),
max_undos: Default::default(),
@@ -1216,7 +1229,7 @@ impl Buffer {
let intersection_end = cmp::min(range.end, fragment_end);
if fragment.was_visible(version, &self.undo_map) {
intersection.len = intersection_end - fragment_start;
- intersection.deletions.insert(local_timestamp);
+ intersection.deletions.insert(timestamp.local());
intersection.visible = false;
}
if intersection.len > 0 {
@@ -1252,8 +1265,8 @@ impl Buffer {
self.fragments = new_fragments;
self.visible_text = visible_text;
self.deleted_text = deleted_text;
- self.local_clock.observe(local_timestamp);
- self.lamport_clock.observe(lamport_timestamp);
+ self.local_clock.observe(timestamp.local());
+ self.lamport_clock.observe(timestamp.lamport());
}
pub fn undo(&mut self, mut cx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
@@ -1355,7 +1368,7 @@ impl Buffer {
let mut fragment = fragment.clone();
let fragment_was_visible = fragment.visible;
if fragment.was_visible(&edit.version, &self.undo_map)
- || fragment.insertion_id == edit.id
+ || fragment.timestamp.local() == edit.timestamp.local()
{
fragment.visible = fragment.is_visible(&self.undo_map);
fragment.max_undos.observe(undo.id);
@@ -1403,7 +1416,7 @@ impl Buffer {
false
} else {
match op {
- Operation::Edit { edit, .. } => self.version >= edit.version,
+ Operation::Edit(edit) => self.version >= edit.version,
Operation::Undo { undo, .. } => self.version.observed(undo.edit_id),
Operation::UpdateSelections { selections, .. } => {
if let Some(selections) = selections {
@@ -1430,11 +1443,10 @@ impl Buffer {
&mut self,
ranges: &[Range<usize>],
new_text: Option<String>,
- local_timestamp: time::Local,
- lamport_timestamp: time::Lamport,
+ timestamp: InsertionTimestamp,
) -> EditOperation {
let mut edit = EditOperation {
- id: local_timestamp,
+ timestamp,
version: self.version(),
ranges: Vec::with_capacity(ranges.len()),
new_text: None,
@@ -1487,8 +1499,7 @@ impl Buffer {
new_ropes.push_str(new_text);
new_fragments.push(
Fragment {
- insertion_id: local_timestamp,
- lamport_timestamp,
+ timestamp,
len: new_text.len(),
deletions: Default::default(),
max_undos: Default::default(),
@@ -1507,7 +1518,7 @@ impl Buffer {
let intersection_end = cmp::min(range.end, fragment_end);
if fragment.visible {
intersection.len = intersection_end - fragment_start;
- intersection.deletions.insert(local_timestamp);
+ intersection.deletions.insert(timestamp.local());
intersection.visible = false;
}
if intersection.len > 0 {
@@ -1987,11 +1998,13 @@ impl<'a> Iterator for HighlightedChunks<'a> {
impl Fragment {
fn is_visible(&self, undos: &UndoMap) -> bool {
- !undos.is_undone(self.insertion_id) && self.deletions.iter().all(|d| undos.is_undone(*d))
+ !undos.is_undone(self.timestamp.local())
+ && self.deletions.iter().all(|d| undos.is_undone(*d))
}
fn was_visible(&self, version: &time::Global, undos: &UndoMap) -> bool {
- (version.observed(self.insertion_id) && !undos.was_undone(self.insertion_id, version))
+ (version.observed(self.timestamp.local())
+ && !undos.was_undone(self.timestamp.local(), version))
&& self
.deletions
.iter()
@@ -2004,14 +2017,14 @@ impl sum_tree::Item for Fragment {
fn summary(&self) -> Self::Summary {
let mut max_version = time::Global::new();
- max_version.observe(self.insertion_id);
+ max_version.observe(self.timestamp.local());
for deletion in &self.deletions {
max_version.observe(*deletion);
}
max_version.join(&self.max_undos);
let mut min_insertion_version = time::Global::new();
- min_insertion_version.observe(self.insertion_id);
+ min_insertion_version.observe(self.timestamp.local());
let max_insertion_version = min_insertion_version.clone();
if self.visible {
FragmentSummary {
@@ -2124,9 +2137,7 @@ impl Operation {
fn lamport_timestamp(&self) -> time::Lamport {
match self {
- Operation::Edit {
- lamport_timestamp, ..
- } => *lamport_timestamp,
+ Operation::Edit(edit) => edit.timestamp.lamport(),
Operation::Undo {
lamport_timestamp, ..
} => *lamport_timestamp,
@@ -3474,7 +3485,7 @@ mod tests {
impl Operation {
fn edit_id(&self) -> Option<time::Local> {
match self {
- Operation::Edit { edit, .. } => Some(edit.id),
+ Operation::Edit(edit) => Some(edit.timestamp.local()),
Operation::Undo { undo, .. } => Some(undo.edit_id),
Operation::UpdateSelections { .. } => None,
}