This is an automated email from the ASF dual-hosted git repository.

blankensteiner pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-dotpulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new c6c4891  Implementing MurmurHash to remove dependency
c6c4891 is described below

commit c6c4891b92b8cacd3bf3525728bb5c2cddb329ba
Author: Daniel Blankensteiner <[email protected]>
AuthorDate: Mon Sep 29 14:55:08 2025 +0200

    Implementing MurmurHash to remove dependency
---
 CHANGELOG.md                                       |  6 ++
 src/DotPulsar/DotPulsar.csproj                     | 15 +---
 src/DotPulsar/Internal/MurmurHash3.cs              | 82 ++++++++++++++++++++++
 src/DotPulsar/RoundRobinPartitionRouter.cs         |  2 +-
 src/DotPulsar/SinglePartitionRouter.cs             |  2 +-
 tests/DotPulsar.Tests/Internal/MurmurHash3Tests.cs | 45 ++++++++++++
 6 files changed, 138 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7278ca..f9db8cd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,12 @@ The format is based on [Keep a 
Changelog](https://keepachangelog.com/en/1.1.0/)
 
 - Replaced the protobuf-net (version 3.2.56) dependency with Google.Protobuf 
(version 3.32.1)
 - System.Collections.Immutable (version 9.0.9) is now a dependency for .NET 
Standard 2.0 and 2.1
+- Updated the System.IO.Pipelines dependency from version 8.0.0 to 9.0.9 for 
.NET Standard 2.0 and 2.1
+
+### Removed
+
+- The HashDepot dependency has been removed
+- .NET 6 and 7 removed as a target frameworks
 
 ## [4.3.2] - 2025-09-17
 
diff --git a/src/DotPulsar/DotPulsar.csproj b/src/DotPulsar/DotPulsar.csproj
index 94110e7..c778576 100644
--- a/src/DotPulsar/DotPulsar.csproj
+++ b/src/DotPulsar/DotPulsar.csproj
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
+    
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0</TargetFrameworks>
     <LangVersion>latest</LangVersion>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
@@ -29,7 +29,6 @@
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; 
buildtransitive</IncludeAssets>
     </PackageReference>
-    <PackageReference Include="HashDepot" Version="2.0.3" />
     <PackageReference Include="Microsoft.Extensions.ObjectPool" 
Version="9.0.9" />
   </ItemGroup>
  
@@ -38,21 +37,13 @@
     <PackageReference Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
     <PackageReference Include="System.Collections.Immutable" Version="9.0.9" />
     <PackageReference Include="System.Diagnostics.DiagnosticSource" 
Version="9.0.9" />
-    <PackageReference Include="System.IO.Pipelines" Version="8.0.0" />
+    <PackageReference Include="System.IO.Pipelines" Version="9.0.9" />
   </ItemGroup>
 
   <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
     <PackageReference Include="System.Collections.Immutable" Version="9.0.9" />
     <PackageReference Include="System.Diagnostics.DiagnosticSource" 
Version="9.0.9" />
-    <PackageReference Include="System.IO.Pipelines" Version="8.0.0" />
-  </ItemGroup>
-
-  <ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
-    <PackageReference Include="System.IO.Pipelines" Version="8.0.0" />
-  </ItemGroup>
-
-  <ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
-    <PackageReference Include="System.IO.Pipelines" Version="8.0.0" />
+    <PackageReference Include="System.IO.Pipelines" Version="9.0.9" />
   </ItemGroup>
 
   <ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
diff --git a/src/DotPulsar/Internal/MurmurHash3.cs 
b/src/DotPulsar/Internal/MurmurHash3.cs
new file mode 100644
index 0000000..018b4ca
--- /dev/null
+++ b/src/DotPulsar/Internal/MurmurHash3.cs
@@ -0,0 +1,82 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace DotPulsar.Internal;
+
+public static class MurmurHash3
+{
+    private const int UintSize = sizeof(uint);
+
+    public static uint Hash32(ReadOnlySpan<byte> buffer, uint seed)
+    {
+        var length = buffer.Length;
+        var hash = seed;
+        var quotient = Math.DivRem(length, UintSize, out int remainder);
+        var i = 0;
+        var blocks = quotient * UintSize;
+        while (i < blocks)
+        {
+#if NETSTANDARD2_0
+            var value = BitConverter.ToUInt32(buffer.Slice(i, 
UintSize).ToArray(), 0);
+#else
+            var value = BitConverter.ToUInt32(buffer.Slice(i, UintSize));
+#endif
+            Round32(ref value, ref hash);
+            hash = RotateLeft(hash, 13);
+            hash *= 5;
+            hash += 0xe6546b64;
+            i += UintSize;
+        }
+
+        if (remainder > 0)
+        {
+            var remaining = PartialBytesToUInt32(buffer.Slice(i, remainder));
+            Round32(ref remaining, ref hash);
+        }
+
+        hash ^= (uint) length;
+        hash ^= hash >> 16;
+        hash *= 0x85ebca6b;
+        hash ^= hash >> 13;
+        hash *= 0xc2b2ae35;
+        hash ^= hash >> 16;
+        return hash;
+    }
+
+    private static uint RotateLeft(uint value, int offset) => (value << 
offset) | (value >> (32 - offset));
+
+    private static void Round32(ref uint value, ref uint hash)
+    {
+        value *= 0xcc9e2d51;
+        value = RotateLeft(value, 15);
+        value *= 0x1b873593;
+        hash ^= value;
+    }
+
+#if NETSTANDARD2_0
+    private static uint PartialBytesToUInt32(ReadOnlySpan<byte> remainingBytes)
+    {
+        var buffer = new byte[UintSize];
+        remainingBytes.CopyTo(buffer);
+        return BitConverter.ToUInt32(buffer, 0);
+    }
+#else
+    private static uint PartialBytesToUInt32(ReadOnlySpan<byte> remainingBytes)
+    {
+        Span<byte> buffer = stackalloc byte[UintSize];
+        remainingBytes.CopyTo(buffer);
+        return BitConverter.ToUInt32(buffer);
+    }
+#endif
+}
diff --git a/src/DotPulsar/RoundRobinPartitionRouter.cs 
b/src/DotPulsar/RoundRobinPartitionRouter.cs
index bf692e1..bf72951 100644
--- a/src/DotPulsar/RoundRobinPartitionRouter.cs
+++ b/src/DotPulsar/RoundRobinPartitionRouter.cs
@@ -15,7 +15,7 @@
 namespace DotPulsar;
 
 using DotPulsar.Abstractions;
-using HashDepot;
+using DotPulsar.Internal;
 
 /// <summary>
 /// The round-robin partition messages router, which is the default router.
diff --git a/src/DotPulsar/SinglePartitionRouter.cs 
b/src/DotPulsar/SinglePartitionRouter.cs
index c4284c6..6c909a5 100644
--- a/src/DotPulsar/SinglePartitionRouter.cs
+++ b/src/DotPulsar/SinglePartitionRouter.cs
@@ -15,7 +15,7 @@
 namespace DotPulsar;
 
 using DotPulsar.Abstractions;
-using HashDepot;
+using DotPulsar.Internal;
 
 /// <summary>
 /// The single partition messages router.
diff --git a/tests/DotPulsar.Tests/Internal/MurmurHash3Tests.cs 
b/tests/DotPulsar.Tests/Internal/MurmurHash3Tests.cs
new file mode 100644
index 0000000..401610a
--- /dev/null
+++ b/tests/DotPulsar.Tests/Internal/MurmurHash3Tests.cs
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace DotPulsar.Tests.Internal;
+
+using DotPulsar.Internal;
+
+[Trait("Category", "Unit")]
+public sealed class MurmurHash3Tests
+{
+    [Theory]
+    [InlineAutoData("", 0U, 0U)]
+    [InlineAutoData("", 1U, 0x514E28B7U)]
+    [InlineAutoData("", 0xffffffffU, 0x81F16F39U)]
+    [InlineAutoData("\0\0\0\0", 0U, 0x2362F9DEU)]
+    [InlineAutoData("aaaa", 0x9747b28cU, 0x5A97808AU)]
+    [InlineAutoData("aaa", 0x9747b28cU, 0x283E0130U)]
+    [InlineAutoData("aa", 0x9747b28cU, 0x5D211726U)]
+    [InlineAutoData("a", 0x9747b28cU, 0x7FA09EA6U)]
+    [InlineAutoData("abcd", 0x9747b28cU, 0xF0478627U)]
+    [InlineAutoData("abc", 0x9747b28cU, 0xC84A62DDU)]
+    [InlineAutoData("ab", 0x9747b28cU, 0x74875592U)]
+    public void Hash32_GivenInput_ShouldCalculateHash(string text, uint seed, 
uint expected)
+    {
+        // Arrange
+        var data = System.Text.Encoding.UTF8.GetBytes(text);
+
+        // Act
+        var actual = MurmurHash3.Hash32(data, seed);
+
+        // Assert
+        actual.ShouldBe(expected);
+    }
+}

Reply via email to