Subject: [PATCH v2 15/17] xdiff: create line_hash() and line_equal()

From: "Ezekiel Newren via GitGitGadget" <[email-masked]>
Date: Fri, 15 Aug 2025 01:22:50 +0000

From: Ezekiel Newren <[email-masked]>

These functions use the whitespace iterator, when applicable, to hash,
and compare lines.

Signed-off-by: Ezekiel Newren <[email-masked]>
---
 rust/xdiff/src/lib.rs    | 19 +++++++++++++++++++
 rust/xdiff/src/xutils.rs | 28 ++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/rust/xdiff/src/lib.rs b/rust/xdiff/src/lib.rs
index 9cf0462bcdb9..809c5573c6e7 100644
--- a/rust/xdiff/src/lib.rs
+++ b/rust/xdiff/src/lib.rs
@@ -1,3 +1,7 @@
+use std::hash::Hasher;
+use xxhash_rust::xxh3::Xxh3Default;
+use crate::xutils::*;
+
 pub mod xutils;
 
 pub const XDF_IGNORE_WHITESPACE: u64 = 1 << 1;
@@ -15,3 +19,18 @@ unsafe extern "C" fn xxh3_64(ptr: *const u8, size: usize) -> u64 {
     let slice = std::slice::from_raw_parts(ptr, size);
     xxhash_rust::xxh3::xxh3_64(slice)
 }
+
+#[no_mangle]
+unsafe extern "C" fn xdl_line_hash(ptr: *const u8, size: usize, flags: u64) -> u64 {
+    let line = std::slice::from_raw_parts(ptr, size);
+
+    line_hash(line, flags)
+}
+
+#[no_mangle]
+unsafe extern "C" fn xdl_line_equal(lhs: *const u8, lhs_len: usize, rhs: *const u8, rhs_len: usize, flags: u64) -> bool {
+    let lhs_line = std::slice::from_raw_parts(lhs, lhs_len);
+    let rhs_line = std::slice::from_raw_parts(rhs, rhs_len);
+
+    line_equal(lhs_line, rhs_line, flags)
+}
diff --git a/rust/xdiff/src/xutils.rs b/rust/xdiff/src/xutils.rs
index 38126b47292f..796a5708b6bf 100644
--- a/rust/xdiff/src/xutils.rs
+++ b/rust/xdiff/src/xutils.rs
@@ -1,4 +1,5 @@
 use crate::*;
+use xxhash_rust::xxh3::xxh3_64;
 
 pub(crate) fn xdl_isspace(v: u8) -> bool {
     match v {
@@ -151,6 +152,33 @@ where
     run_option0.is_none() && run_option1.is_none()
 }
 
+
+pub fn line_hash(line: &[u8], flags: u64) -> u64 {
+    if (flags & XDF_WHITESPACE_FLAGS) == 0 {
+        return xxh3_64(line);
+    }
+
+    let mut hasher = Xxh3Default::new();
+    for chunk in WhitespaceIter::new(line, flags) {
+        hasher.update(chunk);
+    }
+
+    hasher.finish()
+}
+
+
+pub fn line_equal(lhs: &[u8], rhs: &[u8], flags: u64) -> bool {
+    if (flags & XDF_WHITESPACE_FLAGS) == 0 {
+        return lhs == rhs;
+    }
+
+    let lhs_it = WhitespaceIter::new(lhs, flags);
+    let rhs_it = WhitespaceIter::new(rhs, flags);
+
+    chunked_iter_equal(lhs_it, rhs_it)
+}
+
+
 #[cfg(test)]
 mod tests {
     use crate::*;
-- 
gitgitgadget