Append strict collision/topology payloads to the existing prepared package so later physics cutover can drop parsed DAT graphs without adding a second mapping or changing traversal behavior. The full 2,232,170-key catalog is deterministic across worker counts, exact-byte aliased, corruption-isolated, and cancellation-safe.
50 lines
1.5 KiB
C#
50 lines
1.5 KiB
C#
using System.Security.Cryptography;
|
|
|
|
namespace AcDream.Bake;
|
|
|
|
/// <summary>
|
|
/// Offline-only exact-byte deduplication catalog. SHA-256 narrows candidates;
|
|
/// a complete byte comparison is still mandatory before any alias is emitted.
|
|
/// </summary>
|
|
internal sealed class ExactPayloadAliasCatalog
|
|
{
|
|
private readonly Dictionary<string, List<Entry>> _entriesByDigest =
|
|
new(StringComparer.Ordinal);
|
|
|
|
public bool TryFind(ReadOnlySpan<byte> payload, out ulong primaryKey)
|
|
{
|
|
string digest = Digest(payload);
|
|
if (_entriesByDigest.TryGetValue(digest, out List<Entry>? candidates))
|
|
{
|
|
foreach (Entry candidate in candidates)
|
|
{
|
|
if (payload.SequenceEqual(candidate.Payload))
|
|
{
|
|
primaryKey = candidate.PrimaryKey;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
primaryKey = 0;
|
|
return false;
|
|
}
|
|
|
|
public void Add(ulong primaryKey, byte[] payload)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(payload);
|
|
string digest = Digest(payload);
|
|
if (!_entriesByDigest.TryGetValue(digest, out List<Entry>? entries))
|
|
{
|
|
entries = [];
|
|
_entriesByDigest.Add(digest, entries);
|
|
}
|
|
|
|
entries.Add(new Entry(primaryKey, payload));
|
|
}
|
|
|
|
private static string Digest(ReadOnlySpan<byte> payload) =>
|
|
Convert.ToHexString(SHA256.HashData(payload));
|
|
|
|
private sealed record Entry(ulong PrimaryKey, byte[] Payload);
|
|
}
|