blob: a7adaf2635ac8c6f01b815f052b23c0b430400fd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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));
}
|