WIP: Avoid converting RopeFingerprint into a string

Antonio Scandurra and Petros Amoiridis created

Co-Authored-By: Petros Amoiridis <petros@zed.dev>

Change summary

Cargo.lock                    |  3 +--
crates/language/src/buffer.rs | 25 +++++++++++++------------
crates/language/src/proto.rs  |  9 +++++++++
crates/project/src/project.rs | 16 ++++++++++------
crates/rope/Cargo.toml        |  2 +-
crates/rope/src/rope.rs       |  8 +++++---
6 files changed, 39 insertions(+), 24 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -739,8 +739,7 @@ dependencies = [
 [[package]]
 name = "bromberg_sl2"
 version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ed88064f69518b7e3ea50ecfc1b61d43f19248618a377b95ae5c8b611134d4d"
+source = "git+https://github.com/zed-industries/bromberg_sl2?rev=dac565a90e8f9245f48ff46225c915dc50f76920#dac565a90e8f9245f48ff46225c915dc50f76920"
 dependencies = [
  "digest 0.9.0",
  "lazy_static",

crates/language/src/buffer.rs 🔗

@@ -60,7 +60,7 @@ pub struct Buffer {
     git_diff_status: GitDiffStatus,
     file: Option<Arc<dyn File>>,
     saved_version: clock::Global,
-    saved_version_fingerprint: String,
+    saved_version_fingerprint: RopeFingerprint,
     saved_mtime: SystemTime,
     transaction_depth: usize,
     was_dirty_before_starting_transaction: Option<bool>,
@@ -221,7 +221,7 @@ pub trait File: Send + Sync {
         version: clock::Global,
         line_ending: LineEnding,
         cx: &mut MutableAppContext,
-    ) -> Task<Result<(clock::Global, String, SystemTime)>>;
+    ) -> Task<Result<(clock::Global, RopeFingerprint, SystemTime)>>;
 
     fn as_any(&self) -> &dyn Any;
 
@@ -238,7 +238,7 @@ pub trait LocalFile: File {
         &self,
         buffer_id: u64,
         version: &clock::Global,
-        fingerprint: String,
+        fingerprint: RopeFingerprint,
         line_ending: LineEnding,
         mtime: SystemTime,
         cx: &mut MutableAppContext,
@@ -386,7 +386,8 @@ impl Buffer {
                 .ok_or_else(|| anyhow!("missing line_ending"))?,
         ));
         this.saved_version = proto::deserialize_version(message.saved_version);
-        this.saved_version_fingerprint = message.saved_version_fingerprint;
+        this.saved_version_fingerprint =
+            proto::deserialize_fingerprint(&message.saved_version_fingerprint)?;
         this.saved_mtime = message
             .saved_mtime
             .ok_or_else(|| anyhow!("invalid saved_mtime"))?
@@ -402,7 +403,7 @@ impl Buffer {
             diff_base: self.diff_base.as_ref().map(|h| h.to_string()),
             line_ending: proto::serialize_line_ending(self.line_ending()) as i32,
             saved_version: proto::serialize_version(&self.saved_version),
-            saved_version_fingerprint: self.saved_version_fingerprint.clone(),
+            saved_version_fingerprint: proto::serialize_fingerprint(self.saved_version_fingerprint),
             saved_mtime: Some(self.saved_mtime.into()),
         }
     }
@@ -530,7 +531,7 @@ impl Buffer {
     pub fn save(
         &mut self,
         cx: &mut ModelContext<Self>,
-    ) -> Task<Result<(clock::Global, String, SystemTime)>> {
+    ) -> Task<Result<(clock::Global, RopeFingerprint, SystemTime)>> {
         let file = if let Some(file) = self.file.as_ref() {
             file
         } else {
@@ -548,7 +549,7 @@ impl Buffer {
         cx.spawn(|this, mut cx| async move {
             let (version, fingerprint, mtime) = save.await?;
             this.update(&mut cx, |this, cx| {
-                this.did_save(version.clone(), fingerprint.clone(), mtime, None, cx);
+                this.did_save(version.clone(), fingerprint, mtime, None, cx);
             });
             Ok((version, fingerprint, mtime))
         })
@@ -558,8 +559,8 @@ impl Buffer {
         &self.saved_version
     }
 
-    pub fn saved_version_fingerprint(&self) -> &str {
-        &self.saved_version_fingerprint
+    pub fn saved_version_fingerprint(&self) -> RopeFingerprint {
+        self.saved_version_fingerprint
     }
 
     pub fn saved_mtime(&self) -> SystemTime {
@@ -581,7 +582,7 @@ impl Buffer {
     pub fn did_save(
         &mut self,
         version: clock::Global,
-        fingerprint: String,
+        fingerprint: RopeFingerprint,
         mtime: SystemTime,
         new_file: Option<Arc<dyn File>>,
         cx: &mut ModelContext<Self>,
@@ -630,7 +631,7 @@ impl Buffer {
     pub fn did_reload(
         &mut self,
         version: clock::Global,
-        fingerprint: String,
+        fingerprint: RopeFingerprint,
         line_ending: LineEnding,
         mtime: SystemTime,
         cx: &mut ModelContext<Self>,
@@ -643,7 +644,7 @@ impl Buffer {
             file.buffer_reloaded(
                 self.remote_id(),
                 &self.saved_version,
-                self.saved_version_fingerprint.clone(),
+                self.saved_version_fingerprint,
                 self.line_ending(),
                 self.saved_mtime,
                 cx,

crates/language/src/proto.rs 🔗

@@ -11,6 +11,15 @@ use text::*;
 
 pub use proto::{BufferState, Operation};
 
+pub fn serialize_fingerprint(fingerprint: RopeFingerprint) -> String {
+    fingerprint.to_hex()
+}
+
+pub fn deserialize_fingerprint(fingerprint: &str) -> Result<RopeFingerprint> {
+    RopeFingerprint::from_hex(fingerprint)
+        .map_err(|error| anyhow!("invalid fingerprint: {}", error))
+}
+
 pub fn deserialize_line_ending(message: proto::LineEnding) -> fs::LineEnding {
     match message {
         proto::LineEnding::Unix => fs::LineEnding::Unix,

crates/project/src/project.rs 🔗

@@ -22,8 +22,8 @@ use gpui::{
 use language::{
     point_to_lsp,
     proto::{
-        deserialize_anchor, deserialize_line_ending, deserialize_version, serialize_anchor,
-        serialize_version,
+        deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version,
+        serialize_anchor, serialize_version,
     },
     range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction,
     CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent,
@@ -5123,7 +5123,7 @@ impl Project {
             buffer_id,
             version: serialize_version(&saved_version),
             mtime: Some(mtime.into()),
-            fingerprint,
+            fingerprint: language::proto::serialize_fingerprint(fingerprint),
         })
     }
 
@@ -5215,7 +5215,9 @@ impl Project {
                             buffer_id,
                             version: language::proto::serialize_version(buffer.saved_version()),
                             mtime: Some(buffer.saved_mtime().into()),
-                            fingerprint: buffer.saved_version_fingerprint().into(),
+                            fingerprint: language::proto::serialize_fingerprint(
+                                buffer.saved_version_fingerprint(),
+                            ),
                             line_ending: language::proto::serialize_line_ending(
                                 buffer.line_ending(),
                             ) as i32,
@@ -5970,6 +5972,7 @@ impl Project {
         _: Arc<Client>,
         mut cx: AsyncAppContext,
     ) -> Result<()> {
+        let fingerprint = deserialize_fingerprint(&envelope.payload.fingerprint)?;
         let version = deserialize_version(envelope.payload.version);
         let mtime = envelope
             .payload
@@ -5984,7 +5987,7 @@ impl Project {
                 .and_then(|buffer| buffer.upgrade(cx));
             if let Some(buffer) = buffer {
                 buffer.update(cx, |buffer, cx| {
-                    buffer.did_save(version, envelope.payload.fingerprint, mtime, None, cx);
+                    buffer.did_save(version, fingerprint, mtime, None, cx);
                 });
             }
             Ok(())
@@ -5999,6 +6002,7 @@ impl Project {
     ) -> Result<()> {
         let payload = envelope.payload;
         let version = deserialize_version(payload.version);
+        let fingerprint = deserialize_fingerprint(&payload.fingerprint)?;
         let line_ending = deserialize_line_ending(
             proto::LineEnding::from_i32(payload.line_ending)
                 .ok_or_else(|| anyhow!("missing line ending"))?,
@@ -6014,7 +6018,7 @@ impl Project {
                 .and_then(|buffer| buffer.upgrade(cx));
             if let Some(buffer) = buffer {
                 buffer.update(cx, |buffer, cx| {
-                    buffer.did_reload(version, payload.fingerprint, line_ending, mtime, cx);
+                    buffer.did_reload(version, fingerprint, line_ending, mtime, cx);
                 });
             }
             Ok(())

crates/rope/Cargo.toml 🔗

@@ -7,7 +7,7 @@ edition = "2021"
 path = "src/rope.rs"
 
 [dependencies]
-bromberg_sl2 = "0.6"
+bromberg_sl2 = { git = "https://github.com/zed-industries/bromberg_sl2", rev = "dac565a90e8f9245f48ff46225c915dc50f76920" }
 smallvec = { version = "1.6", features = ["union"] }
 sum_tree = { path = "../sum_tree" }
 arrayvec = "0.7.1"

crates/rope/src/rope.rs 🔗

@@ -4,7 +4,7 @@ mod point_utf16;
 mod unclipped;
 
 use arrayvec::ArrayString;
-use bromberg_sl2::{DigestString, HashMatrix};
+use bromberg_sl2::HashMatrix;
 use smallvec::SmallVec;
 use std::{
     cmp, fmt, io, mem,
@@ -25,6 +25,8 @@ const CHUNK_BASE: usize = 6;
 #[cfg(not(test))]
 const CHUNK_BASE: usize = 16;
 
+pub type RopeFingerprint = HashMatrix;
+
 #[derive(Clone, Default, Debug)]
 pub struct Rope {
     chunks: SumTree<Chunk>,
@@ -361,8 +363,8 @@ impl Rope {
             .column
     }
 
-    pub fn fingerprint(&self) -> String {
-        self.chunks.summary().fingerprint.to_hex()
+    pub fn fingerprint(&self) -> RopeFingerprint {
+        self.chunks.summary().fingerprint
     }
 }