Fix compile errors and get serialization unit test passing

Antonio Scandurra created

Change summary

crates/language/src/buffer.rs | 17 +++++++----
crates/language/src/proto.rs  | 27 ++++++++++++------
crates/rpc/proto/zed.proto    |  5 ++-
crates/rpc/src/peer.rs        |  8 ++--
crates/text/src/locator.rs    |  5 +++
crates/text/src/text.rs       | 54 +++++++++++++++++++-----------------
6 files changed, 70 insertions(+), 46 deletions(-)

Detailed changes

crates/language/src/buffer.rs 🔗

@@ -287,12 +287,12 @@ impl Buffer {
         file: Option<Box<dyn File>>,
         cx: &mut ModelContext<Self>,
     ) -> Result<Self> {
-        let mut fragments_len = message.fragments.len();
+        let fragments_len = message.fragments.len();
         let buffer = TextBuffer::from_parts(
             replica_id,
             message.id,
-            message.content,
-            message.deleted_content,
+            &message.visible_text,
+            &message.deleted_text,
             message
                 .undo_map
                 .into_iter()
@@ -304,6 +304,8 @@ impl Buffer {
                 .map(|(i, fragment)| {
                     proto::deserialize_buffer_fragment(fragment, i, fragments_len)
                 }),
+            message.lamport_timestamp,
+            From::from(message.version),
         );
         let mut this = Self::build(buffer, file);
         for selection_set in message.selections {
@@ -331,14 +333,15 @@ impl Buffer {
     pub fn to_proto(&self) -> proto::Buffer {
         proto::Buffer {
             id: self.remote_id(),
-            content: self.text.text(),
-            deleted_content: self.text.deleted_text(),
+            visible_text: self.text.text(),
+            deleted_text: self.text.deleted_text(),
             undo_map: self
                 .text
                 .undo_history()
                 .map(proto::serialize_undo_map_entry)
                 .collect(),
-            version: proto::serialize_vector_clock(&self.version),
+            version: From::from(&self.version),
+            lamport_timestamp: self.lamport_clock.value,
             fragments: self
                 .text
                 .fragments()
@@ -1114,6 +1117,8 @@ impl Buffer {
         cx: &mut ModelContext<Self>,
     ) {
         let lamport_timestamp = self.text.lamport_clock.tick();
+        self.remote_selections
+            .insert(self.text.replica_id(), selections.clone());
         self.send_operation(
             Operation::UpdateSelections {
                 replica_id: self.text.replica_id(),

crates/language/src/proto.rs 🔗

@@ -1,6 +1,7 @@
 use crate::{diagnostic_set::DiagnosticEntry, Diagnostic, Operation};
 use anyhow::{anyhow, Result};
 use clock::ReplicaId;
+use collections::HashSet;
 use lsp::DiagnosticSeverity;
 use rpc::proto;
 use std::sync::Arc;
@@ -124,14 +125,7 @@ pub fn serialize_buffer_fragment(fragment: &text::Fragment) -> proto::BufferFrag
                 timestamp: clock.value,
             })
             .collect(),
-        max_undos: fragment
-            .max_undos
-            .iter()
-            .map(|clock| proto::VectorClockEntry {
-                replica_id: clock.replica_id as u32,
-                timestamp: clock.value,
-            })
-            .collect(),
+        max_undos: From::from(&fragment.max_undos),
     }
 }
 
@@ -325,7 +319,22 @@ pub fn deserialize_buffer_fragment(
     ix: usize,
     count: usize,
 ) -> Fragment {
-    todo!()
+    Fragment {
+        id: locator::Locator::from_index(ix, count),
+        insertion_timestamp: InsertionTimestamp {
+            replica_id: message.replica_id as ReplicaId,
+            local: message.local_timestamp,
+            lamport: message.lamport_timestamp,
+        },
+        insertion_offset: message.insertion_offset as usize,
+        len: message.len as usize,
+        visible: message.visible,
+        deletions: HashSet::from_iter(message.deletions.into_iter().map(|entry| clock::Local {
+            replica_id: entry.replica_id as ReplicaId,
+            value: entry.timestamp,
+        })),
+        max_undos: From::from(message.max_undos),
+    }
 }
 
 pub fn deserialize_selections(selections: Vec<proto::Selection>) -> Arc<[Selection<Anchor>]> {

crates/rpc/proto/zed.proto 🔗

@@ -262,13 +262,14 @@ message Entry {
 
 message Buffer {
     uint64 id = 1;
-    string content = 2;
-    string deleted_content = 3;
+    string visible_text = 2;
+    string deleted_text = 3;
     repeated BufferFragment fragments = 4;
     repeated UndoMapEntry undo_map = 5;
     repeated VectorClockEntry version = 6;
     repeated SelectionSet selections = 7;
     repeated DiagnosticSet diagnostic_sets = 8;
+    uint32 lamport_timestamp = 9;
 }
 
 message BufferFragment {

crates/rpc/src/peer.rs 🔗

@@ -398,7 +398,7 @@ mod tests {
                 proto::OpenBufferResponse {
                     buffer: Some(proto::Buffer {
                         id: 101,
-                        content: "path/one content".to_string(),
+                        visible_text: "path/one content".to_string(),
                         ..Default::default()
                     }),
                 }
@@ -419,7 +419,7 @@ mod tests {
                 proto::OpenBufferResponse {
                     buffer: Some(proto::Buffer {
                         id: 102,
-                        content: "path/two content".to_string(),
+                        visible_text: "path/two content".to_string(),
                         ..Default::default()
                     }),
                 }
@@ -448,7 +448,7 @@ mod tests {
                                 proto::OpenBufferResponse {
                                     buffer: Some(proto::Buffer {
                                         id: 101,
-                                        content: "path/one content".to_string(),
+                                        visible_text: "path/one content".to_string(),
                                         ..Default::default()
                                     }),
                                 }
@@ -458,7 +458,7 @@ mod tests {
                                 proto::OpenBufferResponse {
                                     buffer: Some(proto::Buffer {
                                         id: 102,
-                                        content: "path/two content".to_string(),
+                                        visible_text: "path/two content".to_string(),
                                         ..Default::default()
                                     }),
                                 }

crates/text/src/locator.rs 🔗

@@ -19,6 +19,11 @@ impl Locator {
         Self(smallvec![u64::MAX])
     }
 
+    pub fn from_index(ix: usize, count: usize) -> Self {
+        let id = ((ix as u128 * u64::MAX as u128) / count as u128) as u64;
+        Self(smallvec![id])
+    }
+
     pub fn assign(&mut self, other: &Self) {
         self.0.resize(other.0.len(), 0);
         self.0.copy_from_slice(&other.0);

crates/text/src/text.rs 🔗

@@ -42,7 +42,6 @@ pub type TransactionId = usize;
 
 pub struct Buffer {
     snapshot: BufferSnapshot,
-    last_edit: clock::Local,
     history: History,
     deferred_ops: OperationQueue<Operation>,
     deferred_replicas: HashSet<ReplicaId>,
@@ -385,7 +384,7 @@ impl InsertionTimestamp {
 
 #[derive(Eq, PartialEq, Clone, Debug)]
 pub struct Fragment {
-    id: Locator,
+    pub id: Locator,
     pub insertion_timestamp: InsertionTimestamp,
     pub insertion_offset: usize,
     pub len: usize,
@@ -496,7 +495,6 @@ impl Buffer {
                 version,
                 undo_map: Default::default(),
             },
-            last_edit: clock::Local::default(),
             history,
             deferred_ops: OperationQueue::new(),
             deferred_replicas: HashSet::default(),
@@ -515,30 +513,46 @@ impl Buffer {
         deleted_text: &str,
         undo_map: impl Iterator<Item = (clock::Local, Vec<(clock::Local, u32)>)>,
         fragments: impl ExactSizeIterator<Item = Fragment>,
+        lamport_timestamp: u32,
+        version: clock::Global,
     ) -> Self {
         let visible_text = visible_text.into();
         let deleted_text = deleted_text.into();
         let fragments = SumTree::from_iter(fragments, &None);
-        let undo_map = UndoMap(undo_map.collect());
+        let mut insertions = fragments
+            .iter()
+            .map(|fragment| InsertionFragment {
+                timestamp: fragment.insertion_timestamp.local(),
+                split_offset: fragment.insertion_offset,
+                fragment_id: fragment.id.clone(),
+            })
+            .collect::<Vec<_>>();
+        insertions.sort_unstable_by_key(|i| (i.timestamp, i.split_offset));
         Self {
             remote_id,
             replica_id,
+
+            history: History::new("".into()),
+            deferred_ops: OperationQueue::new(),
+            deferred_replicas: Default::default(),
+            local_clock: clock::Local {
+                replica_id,
+                value: version.get(replica_id) + 1,
+            },
+            lamport_clock: clock::Lamport {
+                replica_id,
+                value: lamport_timestamp,
+            },
+            subscriptions: Default::default(),
             snapshot: BufferSnapshot {
                 replica_id,
                 visible_text,
                 deleted_text,
-                undo_map,
+                undo_map: UndoMap(undo_map.collect()),
                 fragments,
-                insertions: (),
-                version: (),
+                insertions: SumTree::from_iter(insertions, &()),
+                version,
             },
-            history: History::new("".into()),
-            deferred_ops: OperationQueue::new(),
-            deferred_replicas: Default::default(),
-            last_edit: todo!(),
-            local_clock: todo!(),
-            lamport_clock: todo!(),
-            subscriptions: Default::default(),
         }
     }
 
@@ -591,7 +605,6 @@ impl Buffer {
 
         self.history.push(edit.clone());
         self.history.push_undo(edit.timestamp.local());
-        self.last_edit = edit.timestamp.local();
         self.snapshot.version.observe(edit.timestamp.local());
         self.end_transaction();
         edit
@@ -1338,16 +1351,7 @@ impl BufferSnapshot {
     }
 
     pub fn fragments(&self) -> impl Iterator<Item = &Fragment> {
-        let mut cursor = self.fragments.cursor::<()>();
-        let mut started = false;
-        std::iter::from_fn(move || {
-            if started {
-                cursor.next(&None);
-            } else {
-                started = true;
-            }
-            cursor.item()
-        })
+        self.fragments.iter()
     }
 
     pub fn text_summary(&self) -> TextSummary {