aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/src/Godosa.Core/Runs/StateDigest.cs
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-06 23:39:36 +0200
committergodosa <godosa@godosa.eu>2026-10-06 23:39:36 +0200
commit39066900773e7857faf2d02e7ed51b71d219d97d (patch)
treeffab8e4ddd971626776c3b1f4ce1da2c186c2187 /src/Godosa.Core/Runs/StateDigest.cs
downloadgodosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.tar.gz
godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.zip
godosa-engine: initial public history
Diffstat (limited to 'src/Godosa.Core/Runs/StateDigest.cs')
-rw-r--r--src/Godosa.Core/Runs/StateDigest.cs51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/Godosa.Core/Runs/StateDigest.cs b/src/Godosa.Core/Runs/StateDigest.cs
new file mode 100644
index 0000000..a7adaf2
--- /dev/null
+++ b/src/Godosa.Core/Runs/StateDigest.cs
@@ -0,0 +1,51 @@
+using System.Buffers.Binary;
+using System.Text;
+
+namespace Godosa.Core.Runs;
+
+/// <summary>FNV-1a 64 over state bytes (numbers little-endian, strings UTF-8) for comparing runs.</summary>
+public sealed class StateDigest
+{
+ private const ulong Offset = 14695981039346656037UL, Prime = 1099511628211UL;
+
+ public ulong Value { get; private set; } = Offset;
+ public string Hex => Value.ToString("x16");
+
+ public static ulong Of(ReadOnlySpan<byte> bytes)
+ {
+ var d = new StateDigest();
+ d.Add(bytes);
+ return d.Value;
+ }
+
+ public void Add(ReadOnlySpan<byte> bytes)
+ {
+ var h = Value;
+ foreach (var b in bytes)
+ h = (h ^ b) * Prime;
+ Value = h;
+ }
+
+ public void Add(byte b) => Value = (Value ^ b) * Prime;
+
+ public void Add(uint v)
+ {
+ Span<byte> b = stackalloc byte[4];
+ BinaryPrimitives.WriteUInt32LittleEndian(b, v);
+ Add(b);
+ }
+
+ public void Add(int v) => Add(unchecked((uint)v));
+
+ public void Add(ulong v)
+ {
+ Span<byte> b = stackalloc byte[8];
+ BinaryPrimitives.WriteUInt64LittleEndian(b, v);
+ Add(b);
+ }
+
+ public void Add(long v) => Add(unchecked((ulong)v));
+ public void Add(float v) => Add(BitConverter.SingleToUInt32Bits(v));
+ public void Add(double v) => Add(BitConverter.DoubleToUInt64Bits(v));
+ public void Add(string s) => Add(Encoding.UTF8.GetBytes(s));
+}